# Ox
Ethereum Standard Library
# Installation
Install Ox via your package manager, a `
```
## Using Unreleased Commits
If you can't wait for a new release to test the latest features, you can either install from the `canary` tag (tracks the [`main`](https://github.com/wevm/viem/tree/main) branch).
:::code-group
```bash [pnpm]
pnpm add ox@canary
```
```bash [npm]
npm install ox@canary
```
```bash [yarn]
yarn add ox@canary
```
```bash [bun]
bun add ox@canary
```
:::
Or clone the [Ox repo](https://github.com/wevm/ox) to your local machine, build, and link it yourself.
```bash
gh repo clone wevm/ox
cd ox
pnpm install
pnpm build
pnpm link --global
```
Then go to the project where you are using Ox and run `pnpm link --global ox` (or the package manager that you used to link Ox globally).
## Security
Ethereum-related projects are often targeted in attacks to steal users' assets. Make sure you follow security best-practices for your project. Some quick things to get started.
* Pin package versions, upgrade mindfully, and inspect lockfile changes to minimize the risk of [supply-chain attacks](https://nodejs.org/en/guides/security/#supply-chain-attacks).
* Install the [Socket Security](https://socket.dev) [GitHub App](https://github.com/apps/socket-security) to help detect and block supply-chain attacks.
* Add a [Content Security Policy](https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html) to defend against external scripts running in your app.
# Imports & Bundle Size
## Imports
There are two approaches to import Modules in Ox:
* [Named Imports](#named-imports): Importing modules via the root `ox` namespace.
* [Entrypoint Imports](#entrypoint-imports): Importing modules via an `ox/{Module}` namespace.
### Named Imports
Modules can be imported via their respective module export in the root `ox` namespace:
```ts twoslash
import { Hex, Rlp } from 'ox'
const rlp = Rlp.fromHex([Hex.fromString('hello'), Hex.fromString('world')])
```
This approach does not compromise on [tree-shakability](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking), as most modern bundlers support Deep Scope Analysis. As a result, this will not impact the bundle size of your application.
Bundlers known to support Deep Scope Analysis include: [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Webpack 5+](https://webpack.js.org/), [esbuild](https://esbuild.github.io/), [swc](https://swc.rs/), and more.
### Entrypoint Imports
If your bundler does not support Deep Scope Analysis, you are also able to import modules via their respective entrypoint:
```ts twoslash
// @noErrors
import * as Hex from 'ox/Hex'
import * as Rlp from 'ox/Rlp'
const rlp = Rlp.fromHex([Hex.fromString('hello'), Hex.fromString('world')])
```
## Tree Shakability & Bundle Size
Each Module in Ox exports a number of functions (e.g. `Hex` exports `from`, `concat`, `padLeft`, etc). It is important to note that Modules **are not stateful instances with methods** (ie. you cannot instantiate a `Hex` class/object), they are merely a collection of pure stateless functions. This is because function exports are [tree-shakable](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking), whereas instance methods are not.
When Modules are imported in Ox, only the functions that you use from that Module will be included in the final bundle of your application. Unused functions are automatically removed, resulting in a lower bundle size.
Whereas, methods that are attached to instances cannot be tree-shaken by bundlers, which will lead to all methods of a given instance being included in the bundle, regardless of whether they are used or not.
# Error Handling
Every function namespace in Ox exports an accompanying error type (`ErrorType`) and parser (`parseError`) that you can use to strongly type your `catch` statements, or inject into a custom type-safe error handling library (e.g. [`neverthrow`](https://github.com/supermacro/neverthrow), [`Effect`](https://effect.website/), etc.).
## Usage with Vanilla TypeScript
Unfortunately, [TypeScript doesn't have an abstraction for typed exceptions](https://github.com/microsoft/TypeScript/issues/13219), so the most pragmatic & vanilla approach would be to explicitly cast error types in the `catch` statement with the function's `.ErrorType` property.
```ts twoslash
import { AbiParameters, Errors, Hex } from 'ox'
try {
AbiParameters.encode(
AbiParameters.from('address'),
['0xc961145a54c96e3ae9baa048c4f4d6b04c13916b']
)
} catch (err) {
const error = err as AbiParameters.encode.ErrorType
error.name
// ^?
if (error.name === 'Address.InvalidAddressError')
error.cause.name
// ^?
}
```
## Usage with `neverthrow`
You can utilize Ox's `.ErrorType` property into custom type-safe error handling libraries like [`neverthrow`](https://github.com/supermacro/neverthrow).
```ts twoslash
// @noErrors
import { AbiParameters } from 'ox'
import { fromThrowable } from 'neverthrow';
const encode = fromThrowable( // [!code hl]
AbiParameters.encode, // [!code hl]
e => e as AbiParameters.encode.ErrorType // [!code hl]
) // [!code hl]
const result = encode(AbiParameters.from('bytes'), ['0xdeadbeef'])
if (result.isErr()) // [!code hl]
result.error.name // [!code hl]
// ^?
```
# Platform Compatibility \[Platforms compatible with Ox]
**Ox supports all modern browsers (Chrome, Edge, Firefox, etc) & runtime environments (Node 18+, Deno, Bun, etc).**
Ox uses modern EcmaScript features such as:
* [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
* Error [`cause`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause)
* TextEncoder [`encode`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/encode)
You can check support for these features on [Can I use...](https://caniuse.com/)
## Polyfills
If your platform does not support one of the required features, it is also possible to import a polyfill.
### Error `cause`
* [core-js](https://github.com/zloirock/core-js)
### `TextEncoder`
* [FastestSmallestTextEncoderDecoder](https://github.com/anonyco/FastestSmallestTextEncoderDecoder)
# Migrating from v0
Ox v1 includes breaking changes to decoded addresses, cryptographic values, blob handling, and Tempo types. This guide covers every breaking change and the migration required for each one.
First, upgrade Ox to v1.
:::code-group
```bash [pnpm]
pnpm add ox@^1
```
```bash [npm]
npm install ox@^1
```
```bash [yarn]
yarn add ox@^1
```
```bash [bun]
bun add ox@^1
```
:::
## ABI addresses are checksummed
ABI decode functions now checksum decoded addresses by default. If your application compares decoded addresses as case-sensitive strings, normalize both sides or pass `checksumAddress: false` to preserve the v0 behavior.
```ts
const values = AbiParameters.decode(parameters, data) // [!code --]
const values = AbiParameters.decode(parameters, data, { // [!code ++]
checksumAddress: false, // [!code ++]
}) // [!code ++]
```
The option is also available on the higher-level ABI decode functions that return addresses.
## Cryptographic coordinates use padded hex
ECDSA and BLS coordinate fields now use padded `Hex.Hex` strings instead of `bigint`. This includes `r`, `s`, `x`, `y`, and BLS `Fp`/`Fp2` values on `Signature`, `PublicKey`, `BlsPoint`, `Transaction`, `Authorization`, `TxEnvelope`, and related Tempo and ERC types.
ECDSA coordinates are 32 bytes. BLS12-381 coordinates are 48 bytes. The `bigintType` generic has been removed.
```ts
const signature = Signature.from({ // [!code --]
r: 0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bfn, // [!code --]
s: 0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8n, // [!code --]
yParity: 1, // [!code --]
}) // [!code --]
const signature = Signature.from({ // [!code ++]
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf', // [!code ++]
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8', // [!code ++]
yParity: 1, // [!code ++]
}) // [!code ++]
```
Use `Hex.fromNumber(value, { size: 32 })` for ECDSA values and `Hex.fromNumber(value, { size: 48 })` for BLS12-381 values when migrating stored bigints.
## Noble and Scure dependencies use v2
Ox now uses v2 of `@noble/ciphers`, `@noble/curves`, `@noble/hashes`, `@scure/bip32`, and `@scure/bip39`.
ECDSA signatures now default to `lowS: true` for both `Secp256k1` and `P256`. In v0, `P256` signatures could have high-S values.
If you use the `noble` re-exports on `Secp256k1`, `P256`, `Ed25519`, `X25519`, or `Bls`, migrate to the noble v2 API. Notable renames include:
| v0 | v1 |
| --- | --- |
| `ProjectivePoint` or `ExtendedPoint` | `Point` |
| `bls.sign` and `bls.verify` | `bls.longSignatures.sign` and `bls.longSignatures.verify` |
Refer to the relevant noble and Scure v2 changelogs for the complete upstream API changes.
## PeerDAS replaces blob sidecars
The EIP-4844 blob-sidecar API has been removed in favor of PeerDAS (EIP-7594).
* `Kzg.Kzg` no longer includes `computeBlobKzgProof`.
* `Blobs.toSidecars`, `Blobs.toProofs`, and `Blobs.sidecarsToVersionedHashes` have been removed.
* `Blobs.BlobSidecar` and `Blobs.BlobSidecars` have been removed.
* `TxEnvelopeEip4844.sidecars` and the legacy network-wrapper serialization have been removed.
Use a PeerDAS-capable KZG backend. It must provide `blobToKzgCommitment`, `computeCells`, `computeCellsAndKzgProofs`, `recoverCellsAndKzgProofs`, and `verifyCellKzgProofBatch`.
Use `BlobCells` to construct and verify cells and data columns.
```ts
const sidecars = Blobs.toSidecars(blobs, { kzg }) // [!code --]
const versionedHashes = Blobs.sidecarsToVersionedHashes(sidecars) // [!code --]
const columns = BlobCells.toDataColumns(blobs, { kzg }) // [!code ++]
const versionedHashes = Blobs.toVersionedHashes(blobs, { kzg }) // [!code ++]
```
`Kzg.Kzg.blobToKzgCommitment` and `Blobs.toVersionedHashes` remain available for transaction versioned-hash derivation.
## Tempo addresses use plain hex
The `TempoAddress` module and its `tempox`-prefixed address format have been removed. Tempo modules now accept plain `Address.Address` hex values.
Remove calls to `TempoAddress.format`, `TempoAddress.parse`, and `TempoAddress.resolve` at application boundaries. The `addressType` generic has also been removed from `Call`, `TxEnvelopeTempo`, `KeyAuthorization`, `AuthorizationTempo`, and `TransactionRequest`.
```ts
import { TempoAddress } from 'ox/tempo' // [!code --]
const formatted = TempoAddress.format(address) // [!code --]
const { address: resolved } = TempoAddress.parse(formatted) // [!code --]
const resolved = address // [!code ++]
```
## Tempo tokens use addresses
The Tempo `TokenId` module has been removed. `feeToken`, `Channel.token`, and the token arguments passed to `PoolId.from` now accept `Address.Address` values instead of numeric token IDs.
```ts
const envelope = TxEnvelopeTempo.from({
// ...
feeToken: 1n, // [!code --]
feeToken: '0x20c0000000000000000000000000000000000001', // [!code ++]
})
```
`Channel.Resolved` has also been removed. Use `Channel.Channel` with address-valued token fields.
## Tempo multisig no longer uses `config_id`
TIP-1061 multisig account addresses now derive directly from the initial configuration. `MultisigConfig.toId` and the `genesisConfigId` fields have been removed.
```ts
const id = MultisigConfig.toId(genesisConfig) // [!code --]
const account = MultisigConfig.getAddress({ genesisConfigId: id }) // [!code --]
const account = MultisigConfig.getAddress(genesisConfig) // [!code ++]
const payload = MultisigConfig.getSignPayload({ // [!code --]
payload: transactionPayload, // [!code --]
account, // [!code --]
genesisConfigId: id, // [!code --]
}) // [!code --]
const payload = MultisigConfig.getSignPayload({ // [!code ++]
payload: transactionPayload, // [!code ++]
account, // [!code ++]
}) // [!code ++]
const envelope = SignatureEnvelope.from({ // [!code --]
account, // [!code --]
genesisConfigId: id, // [!code --]
signatures, // [!code --]
}) // [!code --]
const envelope = SignatureEnvelope.from({ account, signatures }) // [!code ++]
```
Owner approval digests now bind only the account. The signature wire format is `0x05 || rlp([account, signatures, init?])`, `MultisigConfig.maxOwners` is 255 with `u8` weights, and owner approvals may contain nested multisig signatures.
## RPC schema codecs return native quantities
The `ox/zod` RPC schema codecs now decode scalar quantity results to native values. Balance, gas, fee, and block-number quantities decode to `bigint`; chain IDs, transaction counts, and block transaction counts decode to `number`.
Use `RpcSchema.FromZod` when you need the raw JSON-RPC wire types. Use the codec return types when consuming decoded values.
## Transaction envelope type detection expects native types
`TransactionEnvelope.getType` now rejects RPC-style type strings such as `'0x0'` through `'0x4'`. Convert RPC transaction requests before detecting their envelope type.
```ts
const type = TransactionEnvelope.getType(rpcRequest) // [!code --]
const request = TransactionRequest.fromRpc(rpcRequest) // [!code ++]
const type = TransactionEnvelope.getType(request) // [!code ++]
```
## Stricter validation
Ox v1 rejects malformed values that v0 sometimes accepted or normalized. Audit code that relies on permissive parsing, particularly for:
* undersized ABI data, invalid packed-array lengths, and anonymous event topics;
* weak or invalid keystore KDF parameters;
* malformed public keys, blooms, typed data, COSE keys, values, RLP, and JSON-RPC responses;
* non-32-byte access-list storage keys;
* EIP-4844 envelopes without `blobVersionedHashes`; and
* invalid WebAuthn assertion flags or extension data.
See the [v1.0.0 changelog](https://github.com/wevm/ox/blob/main/CHANGELOG.md#100) for the full list of corrected validation and serialization behavior.
# Benchmarks
These benchmarks compare high-level operations across Ox implementations and
engine providers. Lower timings are better.
The following results are mean single-call durations from an Apple M4 Max
running macOS 26.5.2 and Node.js 25.9.0. The comparison uses Ox 1.2.0 and
0.14.33. The fastest result in each row is bold.
| Task | Operation | `ox v0` | `ox` | `ox/node` | `ox/wasm` | Fastest vs. Ox v0 |
| --- | --- | ---: | ---: | ---: | ---: | ---: |
| Calculate Swap Input Amount | `getAmountIn` (bigint) | 484.0 ns | 526.4 ns | 480.0 ns | **479.6 ns** | 1.0× faster |
| Calculate Swap Output Amount | `getAmountOut` (bigint) | 186.7 ns | **184.4 ns** | 191.3 ns | 184.7 ns | 1.0× faster |
| Decode RLP Struct | `Rlp.toBytes` | **146.8 ns** | 149.9 ns | 150.7 ns | 161.0 ns | Baseline |
| Decrypt JSON Keystore | `Keystore.decrypt` | 5.9 µs | 4.7 µs | 5.2 µs | **2.4 µs** | 2.5× faster |
| Derive CREATE2 Contract Address | `ContractAddress.fromCreate2` | 14.7 µs | 11.4 µs | 11.6 µs | **6.8 µs** | 2.2× faster |
| Derive Mnemonic Private Key | `Mnemonic.toPrivateKey` | 7.26 ms | 7.34 ms | **1.82 ms** | 3.04 ms | 4.0× faster |
| Encode Event Topics | `AbiEvent.encode` | 4.5 µs | 3.3 µs | 3.3 µs | **1.0 µs** | 4.7× faster |
| Encode RLP Struct | `Rlp.fromBytes` | 257.0 ns | 118.5 ns | 118.9 ns | **117.6 ns** | 2.2× faster |
| Encode Seaport Fulfill Order | `AbiFunction.encodeData` (cached) | 13.4 µs | 7.4 µs | 7.3 µs | **7.2 µs** | 1.9× faster |
| Encode Seaport Fulfill Order | `AbiFunction.encodeData` (dynamic) | 39.5 µs | 29.3 µs | 28.4 µs | **24.1 µs** | 1.6× faster |
| Encode Uniswap V2 Swap | `AbiFunction.encodeData` (cached) | 1.72 µs | 1.08 µs | **1.07 µs** | 1.19 µs | 1.6× faster |
| Encode Uniswap V2 Swap | `AbiFunction.encodeData` (dynamic) | 8.8 µs | 6.9 µs | 6.7 µs | **4.2 µs** | 2.1× faster |
| Generate Random Private Key | `Secp256k1.randomPrivateKey` | 1.61 µs | **1.47 µs** | 1.51 µs | 1.54 µs | 1.1× faster |
| Get Personal Message Sign Payload | `PersonalMessage.getSignPayload` | 4.9 µs | 3.4 µs | 3.4 µs | **1.0 µs** | 4.8× faster |
| Get Transaction Sign Payload | `TransactionEnvelope.getSignPayload` | 5.6 µs | 3.9 µs | 4.0 µs | **1.5 µs** | 3.6× faster |
| Hash 32-byte Payload | `Hash.keccak256` (32 B) | 3.55 µs | 2.59 µs | 2.60 µs | **343 ns** | 10.4× faster |
| Hash Typed Data | `TypedData.getSignPayload` | 70.3 µs | 52.0 µs | 52.5 µs | **20.0 µs** | 3.5× faster |
| Recover Secp256k1 Public Key | `Secp256k1.recoverPublicKey` (32 B) | 1.05 ms | 1.10 ms | 1.10 ms | **36.6 µs** | 28.8× faster |
| Sign Secp256k1 Message | `Secp256k1.sign` (32 B message) | 178.6 µs | 172.6 µs | 171.9 µs | **24.2 µs** | 7.4× faster |
| Verify Secp256k1 Signature | `Secp256k1.verify` (32 B message) | 1.83 ms | 963.1 µs | 965.0 µs | **31.3 µs** | 58.3× faster |
WASM has the largest effect on operations that perform one or more
Keccak-256 hashes. Node.js has the largest effect on mnemonic derivation
because its engine supplies native PBKDF2.
ABI encoding remains mostly JavaScript data-layout work. The cached case
extracts and prepares Seaport's `fulfillOrder` function before measurement.
The dynamic case searches the complete Seaport ABI and prepares the function
inside every measured call.
The Uniswap V2, bigint, and RLP cases use the inputs from the
[Alloy benchmark suite](https://github.com/alloy-rs/examples/tree/main/benches).
The dynamic Uniswap case parses its JSON ABI inside every measured call.
Provider engines do not override bigint arithmetic or RLP encoding, so small
differences among `ox`, `ox/node`, and `ox/wasm` in those rows are runtime
noise.
## Method
Run the comparison from the Ox repository:
```sh
pnpm bench:comparison --run
```
The harness uses Vitest bench through Vite+. It runs each provider in an
isolated file and runs the files sequentially to avoid CPU contention. Every
provider receives the same inputs.
Provider initialization, WASM compilation, fixture preparation, and keystore
key derivation happen outside the timed functions. The `ox/wasm` variant
combines the aggregate WASM engine with its opt-in Keystore and Secp256k1
providers.
Ox 0.14.33 does not expose the generic `TransactionEnvelope.getSignPayload`
function. That column uses `TxEnvelopeEip1559.getSignPayload`, the equivalent
for the EIP-1559 fixture.
Ox exposes event topic encoding as `AbiEvent.encode`. This benchmark measures
the operation sometimes described as `AbiEvent.encodeTopics`.
These results are a local snapshot, not a performance guarantee. CPU,
JavaScript runtime, OpenSSL, WASM runtime, inputs, and background load can
change both timings and rankings. For lower-level cryptographic measurements,
see [WASM and engine benchmarks](/guides/runtime/engines#benchmarks).
# Guides
## Overview
Task-oriented guides for building with Ox. Each guide combines related modules into a
complete workflow and links to the [API reference](/api) for deeper detail.
New to Ox? Start with [Installation](/installation), then choose a guide below.
# ABIs & Contracts
## Overview
The [Application Binary Interface (ABI)](https://docs.soliditylang.org/en/latest/abi-spec.html)
defines how data is encoded and decoded between your application and a contract's bytecode. Ox
provides a module for each ABI item type — [`Abi`](/api/Abi), [`AbiFunction`](/api/AbiFunction),
[`AbiEvent`](/api/AbiEvent), [`AbiError`](/api/AbiError), and
[`AbiConstructor`](/api/AbiConstructor) — covering everything between your app and the contract:
parsing ABIs, encoding calls, and decoding what comes back. Recipes end at the encoded payload;
hand it to a JSON-RPC transport, or use a higher-level client like [Viem](https://viem.sh) for
full contract workflows.
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([
'function approve(address spender, uint256 amount) returns (bool)',
'event Transfer(address indexed from, address indexed to, uint256 amount)',
])
const approve = AbiFunction.fromAbi(abi, 'approve')
const data = AbiFunction.encodeData(approve, [
'0xcb98643b8786950f0461f3b0edf99d88f274574d',
100_000_000n,
])
// @log: '0x095ea7b3000000000000000000000000cb98643b8786950f0461f3b0edf99d88f274574d0000000000000000000000000000000000000000000000000000000005f5e100'
```
# Deploy Contracts & Compute Addresses
## Overview
A contract deployment is a transaction whose calldata is the contract's bytecode with the
ABI-encoded constructor arguments appended, and no `to` address.
[`AbiConstructor`](/api/AbiConstructor) encodes that deploy data, and
[`ContractAddress`](/api/ContractAddress) computes the address the deployment will land on —
before anything is broadcast.
## Recipes
### Encode Constructor Arguments
Define the constructor with [`AbiConstructor.from`](/api/AbiConstructor/from), then append the
encoded arguments to the bytecode with [`AbiConstructor.encode`](/api/AbiConstructor/encode). The
result is the deploy transaction's calldata.
```ts twoslash
import { AbiConstructor, RpcTransport } from 'ox'
const bytecode = '0x...'
const constructor = AbiConstructor.from('constructor(address owner)')
const data = AbiConstructor.encode(constructor, {
bytecode,
args: ['0x9f1fdab6458c5fc642fa0f4c5af7473c46837357'],
})
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const hash = await transport.request({
method: 'eth_sendTransaction',
params: [{ data }],
})
```
If you are working with a JSON ABI, extract the constructor with
[`AbiConstructor.fromAbi`](/api/AbiConstructor/fromAbi). Note that deploy transactions omit the
`to` address.
### Compute a CREATE Address
Ordinary deployments use the `CREATE` opcode: the resulting address is derived from the deployer
address and its account nonce at deployment time.
[`ContractAddress.fromCreate`](/api/ContractAddress/fromCreate) computes it locally.
```ts twoslash
import { ContractAddress } from 'ox'
const address = ContractAddress.fromCreate({
from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6',
nonce: 0n, // [!code hl]
})
// @log: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2'
```
`nonce` is the deployer's transaction count at the moment of deployment (`eth_getTransactionCount`
for an EOA), not a value you choose.
### Compute a CREATE2 Address
Factory deployments via the [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode derive the
address from the factory address, a salt, and the init code — so the address is deterministic and
independent of nonces. Use
[`ContractAddress.fromCreate2`](/api/ContractAddress/fromCreate2).
```ts twoslash
import { ContractAddress, Hex } from 'ox'
const address = ContractAddress.fromCreate2({
from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6',
bytecode: '0x6394198df16000526103ff60206004601c335afa6040516060f3',
salt: Hex.fromString('hello world'), // [!code hl]
})
// @log: '0x59fbb593abe27cb193b6ee5c5dc7bbde312290ab'
```
`bytecode` is the full init code — the deployment bytecode plus encoded constructor arguments,
i.e. the same `data` produced by `AbiConstructor.encode`. If you already have `keccak256` of the
init code, pass it as `bytecodeHash` instead.
## Best Practices
### CREATE2 Commits to the Init Code
Constructor arguments are part of the init code, so changing them changes the CREATE2 address.
Compute the address from the exact `data` you will deploy, not from the bare bytecode.
### Pin the Deployer Nonce
CREATE addresses shift with every transaction the deployer sends. If a predictable address
matters, compute it from a fresh nonce and deploy before anything else, or use CREATE2.
## See More
# Work with ABIs
## Overview
[`Abi`](/api/Abi) parses human-readable and JSON ABIs into typed objects, and
[`AbiItem`](/api/AbiItem) and [`AbiParameter`](/api/AbiParameter) operate on individual items and
parameters — extraction, formatting, signatures, and selectors. The `Solidity` module supplies
companion constants (e.g. `Solidity.maxUint256`) and regexes for validating types and values.
## Recipes
### Use Human-Readable ABIs
[`Abi.from`](/api/Abi/from) parses Solidity-style signatures into a fully typed JSON ABI — types
are inferred at the type level, so downstream encoding and decoding stay type-safe.
```ts twoslash
import { Abi } from 'ox'
const abi = Abi.from([
'function approve(address spender, uint256 amount) returns (bool)',
'event Transfer(address indexed from, address indexed to, uint256 amount)',
'error InsufficientBalance(uint256 available, uint256 required)',
])
```
Human-readable signatures support functions, events, errors, constructors, fallback/receive
functions, structs, and bare parameters:
```ts
'function balanceOf(address owner) view returns (uint256)'
'event Transfer(address indexed from, address indexed to, uint256 amount)'
'error Unauthorized(address caller)'
'constructor(address owner) payable'
'fallback() external payable'
'receive() external payable'
'struct Account { address owner; uint256 balance; }'
'address spender, uint256 amount'
```
Some syntax rules are enforced for parity between runtime parsing and type-level inference:
whitespace matters (`'function name() returns (string)'`, not `'function name()returns(string)'`),
semicolons are omitted, parameters may be named or unnamed, inline tuples map to `tuple`
parameters, and struct signatures must be declared before the signature that uses them
(recursive structs are not supported).
### Parse a JSON ABI
[`Abi.from`](/api/Abi/from) also accepts JSON ABIs (e.g. compiler output). Extract typed items
with the per-type extractors, such as [`AbiFunction.fromAbi`](/api/AbiFunction/fromAbi).
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([
{
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{ name: 'spender', type: 'address' },
{ name: 'amount', type: 'uint256' },
],
outputs: [{ type: 'bool' }],
},
])
const approve = AbiFunction.fromAbi(abi, 'approve')
```
Each item type has its own extractor — [`AbiEvent.fromAbi`](/api/AbiEvent/fromAbi),
[`AbiError.fromAbi`](/api/AbiError/fromAbi), and
[`AbiConstructor.fromAbi`](/api/AbiConstructor/fromAbi).
### Format Back to Human-Readable
[`Abi.format`](/api/Abi/format) converts a JSON ABI back into human-readable signatures — useful
for display, logging, or storing ABIs compactly.
```ts twoslash
import { Abi } from 'ox'
const abi = Abi.from([
'function approve(address spender, uint256 amount) returns (bool)',
'event Transfer(address indexed from, address indexed to, uint256 amount)',
])
const formatted = Abi.format(abi)
// @log: [
// @log: 'function approve(address spender, uint256 amount) returns (bool)',
// @log: 'event Transfer(address indexed from, address indexed to, uint256 amount)',
// @log: ]
```
Single items and parameters format the same way with
[`AbiItem.format`](/api/AbiItem/format) and [`AbiParameter.format`](/api/AbiParameter/format).
### Extract Items & Compute Selectors
[`AbiItem.fromAbi`](/api/AbiItem/fromAbi) extracts an item by name — or by selector, which is
handy for reverse-lookups from calldata or log topics.
[`AbiItem.getSelector`](/api/AbiItem/getSelector) and
[`AbiItem.getSignatureHash`](/api/AbiItem/getSignatureHash) compute the identifiers themselves.
```ts twoslash
import { Abi, AbiItem } from 'ox'
const abi = Abi.from([
'function approve(address spender, uint256 amount) returns (bool)',
'event Transfer(address indexed from, address indexed to, uint256 amount)',
])
const approve = AbiItem.fromAbi(abi, 'approve')
const signature = AbiItem.getSignature(approve)
// @log: 'approve(address,uint256)'
const selector = AbiItem.getSelector(approve)
// @log: '0x095ea7b3'
const topic = AbiItem.getSignatureHash(abi, 'Transfer')
// @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
const bySelector = AbiItem.fromAbi(abi, '0x095ea7b3')
```
Functions and errors are identified by the first 4 bytes of the signature hash (the selector);
events are identified by the full 32-byte signature hash in `topics[0]`.
## Best Practices
### Keep ABIs Statically Analyzable
Type inference only works when the ABI is a literal in source (or generated as one). ABIs parsed
from runtime strings or fetched JSON widen to generic types — encoding still works, but you lose
compile-time checking of names and arguments.
### Prefer Human-Readable ABIs in Source
They diff cleanly, carry parameter names, and parse to the same JSON ABI. Reserve raw JSON for
ABIs consumed directly from compiler artifacts.
## See More
# Work with Events & Logs
## Overview
Contracts emit events as logs: indexed arguments become `topics` (filterable by the node), while
non-indexed arguments are ABI-encoded into `data`. [`AbiEvent`](/api/AbiEvent) encodes an event's
indexed arguments into topics for log queries (e.g. `eth_getLogs`), and decodes the resulting logs
back into named, typed arguments.
## Recipes
### Build an Event Filter
Encode an event and its indexed arguments into topics with [`AbiEvent.encode`](/api/AbiEvent/encode),
then pass the topics to a log query. Below, we filter for ERC-20 `Transfer` events sent from a
specific address.
```ts twoslash
import { AbiEvent, RpcTransport } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)',
)
const { topics } = AbiEvent.encode(transfer, {
from: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357', // [!code hl]
})
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const logs = await transport.request({
method: 'eth_getLogs',
params: [{ topics }],
})
```
If you are working with a JSON ABI, extract the event with
[`AbiEvent.fromAbi`](/api/AbiEvent/fromAbi) instead of defining it inline.
### Decode a Log Against an Event
Decode each returned log's `topics` and `data` into named arguments with
[`AbiEvent.decode`](/api/AbiEvent/decode).
```ts twoslash
import { AbiEvent, RpcTransport } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)',
)
const { topics } = AbiEvent.encode(transfer, {
from: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
})
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const logs = await transport.request({
method: 'eth_getLogs',
params: [{ topics }],
})
const decoded = logs.map((log) => AbiEvent.decode(transfer, log))
// @log: [
// @log: {
// @log: from: '0x9F1fdAb6458c5fc642fa0F4C5af7473C46837357',
// @log: to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
// @log: value: 1n,
// @log: },
// @log: ...
// @log: ]
```
Decoding throws if the log's selector (`topics[0]`) does not match the event. To decode
heterogeneous logs against a whole ABI, use [`AbiEvent.extractLogs`](/api/AbiEvent/extractLogs),
which matches each log by selector and skips non-matching entries.
### Handle Indexed & Non-Indexed Arguments
Only indexed arguments can be filtered on. Omitted indexed arguments produce a `null` topic,
which matches any value — non-indexed arguments (like `value` below) never appear in `topics`.
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)',
)
const { topics } = AbiEvent.encode(transfer, {
to: '0xcb98643b8786950f0461f3b0edf99d88f274574d', // [!code hl]
})
// @log: [
// @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
// @log: null,
// @log: '0x000000000000000000000000cb98643b8786950f0461f3b0edf99d88f274574d',
// @log: ]
```
Dynamic indexed types (`string`, `bytes`, arrays, and tuples) are stored as keccak256 hashes in
topics, so decoding returns the 32-byte hash — not the original value. Keep such arguments
non-indexed when you need to read them back from logs.
## Best Practices
### Match the Deployed Signature Exactly
The selector and topic layout are derived from the event signature, including which parameters
are `indexed`. A signature that drifts from the deployed contract will fail to match logs or
mis-assign arguments.
### Constrain Block Ranges
Most providers cap `eth_getLogs` queries. Pass `fromBlock`/`toBlock` bounds and paginate over
ranges instead of querying the entire chain in one request.
## See More
# Work with Function Calls
## Overview
[`AbiFunction`](/api/AbiFunction) encodes a function and its arguments into calldata, and decodes
call results and incoming calldata back into typed values. Underneath sits
[`AbiParameters`](/api/AbiParameters), the coder for standalone parameter lists. Recipes below use
a raw JSON-RPC transport; any [EIP-1193 provider](/api/Provider) or client works the same way.
## Recipes
### Encode a Read Call & Decode the Result
Read-only (`pure`/`view`) functions execute via `eth_call` — no transaction, no gas. Encode the
call with [`AbiFunction.encodeData`](/api/AbiFunction/encodeData) and decode the return value with
[`AbiFunction.decodeResult`](/api/AbiFunction/decodeResult). Below, we read an ERC-20 balance.
```ts twoslash
import { AbiFunction, RpcTransport } from 'ox'
const balanceOf = AbiFunction.from(
'function balanceOf(address) returns (uint256)',
)
const data = AbiFunction.encodeData(balanceOf, [
'0xcb98643b8786950f0461f3b0edf99d88f274574d',
])
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const result = await transport.request({
method: 'eth_call',
params: [
{
data,
to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
},
],
})
const balance = AbiFunction.decodeResult(balanceOf, result)
```
If you are working with a JSON ABI, extract the function with
[`AbiFunction.fromAbi`](/api/AbiFunction/fromAbi) instead of defining it inline.
### Encode a State-Modifying Call
State-modifying (`nonpayable`/`payable`) functions require a transaction. The calldata is encoded
exactly the same way — only the JSON-RPC method changes. Below, we approve an ERC-20 spend.
```ts twoslash
import { AbiFunction, RpcTransport, Value } from 'ox'
const approve = AbiFunction.from(
'function approve(address spender, uint256 amount) returns (bool)',
)
const data = AbiFunction.encodeData(approve, [
'0xcb98643b8786950f0461f3b0edf99d88f274574d',
Value.from('100', 6), // 100 USDC (6 decimals) // [!code hl]
])
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const hash = await transport.request({
method: 'eth_sendTransaction',
params: [
{
data,
to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
},
],
})
```
Swap `eth_sendTransaction` for `eth_call` to simulate the call (and decode its return value with
`AbiFunction.decodeResult`), or `eth_estimateGas` to estimate its gas. To sign with a local key
instead of a node-managed account, place the calldata in a
[transaction envelope](/guides/transactions/build-sign-send).
### Decode Incoming Calldata
For routers, inspectors, or smart account implementations, reverse the flow: extract the function
by the calldata's 4-byte selector with [`AbiFunction.fromAbi`](/api/AbiFunction/fromAbi), then
decode the arguments with [`AbiFunction.decodeData`](/api/AbiFunction/decodeData).
```ts twoslash
import { Abi, AbiFunction, Hex } from 'ox'
// Calldata from a transaction `input` or a user operation.
declare const data: Hex.Hex
const abi = Abi.from([
'function approve(address spender, uint256 amount) returns (bool)',
'function transfer(address to, uint256 amount) returns (bool)',
])
const fn = AbiFunction.fromAbi(abi, data) // [!code hl]
const args = AbiFunction.decodeData(fn, data)
// @log: fn.name: 'approve'
// @log: args: ['0xcb98643b8786950F0461f3B0edf99D88F274574D', 100000000n]
```
`fromAbi` throws if no item in the ABI matches the selector — branch on `fn.name` to route the
call.
### Encode & Decode Standalone Parameters
[`AbiParameters.encode`](/api/AbiParameters/encode) and
[`AbiParameters.decode`](/api/AbiParameters/decode) code raw parameter lists without a function
selector — the building blocks for structured data that is hashed, signed, or embedded in other
payloads.
```ts twoslash
import { AbiParameters } from 'ox'
const encoded = AbiParameters.encode(
AbiParameters.from(['address', 'uint32[]']),
['0xcb98643b8786950F0461f3B0edf99D88F274574D', [1, 2, 3]],
)
const decoded = AbiParameters.decode(
AbiParameters.from(['address', 'uint32[]']),
encoded,
)
// @log: ['0xcb98643b8786950F0461f3B0edf99D88F274574D', [1, 2, 3]]
```
Parameters can also be defined as JSON objects (e.g. `[{ type: 'address' }]`) or full
human-readable signatures via [`AbiParameters.from`](/api/AbiParameters/from).
### Packed Encoding
[`AbiParameters.encodePacked`](/api/AbiParameters/encodePacked) implements Solidity's
[`abi.encodePacked`](https://docs.soliditylang.org/en/latest/abi-spec.html#non-standard-packed-mode):
values are concatenated without padding or offsets.
```ts twoslash
import { AbiParameters } from 'ox'
const encoded = AbiParameters.encodePacked(
['address', 'string'],
['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 'hello world'],
)
// @log: '0xd8da6bf26964af9d7eed9e03e53415d37aa9604568656c6c6f20776f726c64'
```
Packed encoding is not self-describing and cannot be decoded — use it for hashing and signature
payloads, not for data you need to read back.
## Best Practices
### Simulate Before You Send
Run the same calldata through `eth_call` before broadcasting a transaction. Reverts surface as
decodable [error data](/guides/abi/errors) instead of a wasted transaction fee.
### Prefer Standard Encoding Over Packed
Packed encoding of multiple dynamic types is ambiguous (`("a", "bc")` and `("ab", "c")` collide).
Reserve `encodePacked` for cases that require byte-exact parity with Solidity, and hash structured
data with standard encoding otherwise.
## See More
# Work with Reverts & Custom Errors
## Overview
When a contract call reverts, the node returns ABI-encoded revert data: a 4-byte error selector
followed by the encoded arguments. [`AbiError`](/api/AbiError) decodes custom errors, legacy
`Error(string)` revert reasons, and compiler `Panic` codes back into typed values — and encodes
them again for testing.
## Recipes
### Decode Revert Data from `eth_call`
A reverted `eth_call` surfaces its revert data on the `data` field of the JSON-RPC error response.
[`AbiError.extract`](/api/AbiError/extract) matches the data's selector against the ABI and
decodes the arguments in one step.
```ts twoslash
import { Abi, AbiError, Hex } from 'ox'
// Revert data from an `eth_call` JSON-RPC error response.
declare const data: Hex.Hex
const abi = Abi.from([
'function transfer(address to, uint256 amount) returns (bool)',
'error InsufficientBalance(uint256 available, uint256 required)',
])
const { error, args } = AbiError.extract(abi, data)
// @log: {
// @log: error: { name: 'InsufficientBalance', type: 'error', ... },
// @log: args: [100n, 320n],
// @log: }
```
`Error(string)` reverts (from `require(condition, "reason")`) and `Panic` reverts (from failed
`assert`s, overflows, etc.) are matched automatically, even when they are not present in the ABI.
### Match an Error by Selector
To branch on a specific error before decoding, compare the first 4 bytes of the revert data
against the error's selector from [`AbiError.getSelector`](/api/AbiError/getSelector).
```ts twoslash
import { AbiError, Hex } from 'ox'
declare const data: Hex.Hex
const insufficientBalance = AbiError.from(
'error InsufficientBalance(uint256 available, uint256 required)',
)
const selector = Hex.slice(data, 0, 4) // [!code hl]
if (selector === AbiError.getSelector(insufficientBalance)) {
const [available, required] = AbiError.decode(insufficientBalance, data)
}
```
The built-in Solidity cases have exported selectors and definitions — `Panic` codes map to
human-readable descriptions via [`AbiError.panicReasons`](/api/AbiError).
```ts twoslash
import { AbiError, Hex } from 'ox'
declare const data: Hex.Hex
if (Hex.slice(data, 0, 4) === AbiError.solidityErrorSelector) {
const reason = AbiError.decode(AbiError.solidityError, data)
}
// @log: 'Not enough Ether provided.'
if (Hex.slice(data, 0, 4) === AbiError.solidityPanicSelector) {
const code = AbiError.decode(AbiError.solidityPanic, data)
// @log: 'Arithmetic operation resulted in underflow or overflow.'
const reason = AbiError.panicReasons[Number(code)]
}
```
### Encode Errors for Testing
[`AbiError.encode`](/api/AbiError/encode) produces the selector-prefixed revert data for an error
and its arguments — useful for stubbing `eth_call` responses or asserting expected reverts in
tests.
```ts twoslash
import { AbiError } from 'ox'
const error = AbiError.from(
'error InsufficientBalance(uint256 available, uint256 required)',
)
const data = AbiError.encode(error, [100n, 320n])
// @log: '0xcf47918100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000140'
```
## Best Practices
### Keep Custom Errors in the ABI
Revert data identifies an error only by its 4-byte selector. Include every custom error the
contract (and the libraries it calls) can throw in the ABI you pass to `AbiError.extract`, or
matching will fail with a "not found" error.
### Treat Revert Reasons as Untrusted Output
Revert strings and error arguments come from contract code. Log them for diagnostics, but do not
render them unescaped or branch security decisions on their contents.
## See More
# Account Abstraction
:::info
These guides cover Ox's low-level primitives. If you are looking for a high-level bundler and
smart account client, check out [Viem's Account Abstraction guides](https://viem.sh/account-abstraction).
:::
## Overview
Account abstraction moves accounts from externally-owned key pairs to smart contracts, changing
how transactions are built, executed, and attributed. Ox ships primitives for each layer of that
stack: [`UserOperation`](/ercs/erc4337/UserOperation) constructs and signs ERC-4337 user
operations, [`Calls`](/ercs/erc7821/Calls) and [`Execute`](/ercs/erc7821/Execute) encode ERC-7821
batched executions, and [`Attribution`](/ercs/erc8021/Attribution) appends ERC-8021 attribution
codes to calldata. To upgrade an existing EOA into a smart account, see
[Delegate with EIP-7702](/guides/transactions/eip-7702).
```ts twoslash
import { Value } from 'ox'
import { UserOperation } from 'ox/erc4337'
import { Execute } from 'ox/erc7821'
// 1. Encode a batch of calls for an ERC-7821 account.
const callData = Execute.encodeData([
{
to: '0xcafebabecafebabecafebabecafebabecafebabe',
value: Value.fromEther('1'),
},
{
data: '0xdeadbeef',
to: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
},
])
// 2. Wrap it in an ERC-4337 user operation.
const userOperation = UserOperation.from({
callData,
callGasLimit: 300_000n,
maxFeePerGas: Value.fromGwei('20'),
maxPriorityFeePerGas: Value.fromGwei('2'),
nonce: 0n,
preVerificationGas: 100_000n,
sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
verificationGasLimit: 100_000n,
})
```
## Guides
# Attribute Calldata with ERC-8021
## Overview
[ERC-8021](https://eip.tools/eip/8021) appends a self-describing suffix to transaction calldata so
the entities that facilitated a transaction — apps, wallets, and services — can be attributed
onchain. Because ABI decoding ignores trailing calldata bytes, the suffix travels with the
transaction without changing its behavior. The [`Attribution`](/ercs/erc8021/Attribution) module
encodes and extracts these suffixes.
## Recipes
### Append an Attribution Suffix
Convert attribution codes to a data suffix with `Attribution.toDataSuffix` and concatenate it onto
the encoded call.
```ts twoslash
import { AbiFunction, Hex } from 'ox'
import { Attribution } from 'ox/erc8021'
const transfer = AbiFunction.from(
'function transfer(address recipient, uint256 amount)',
)
const data = AbiFunction.encodeData(transfer, [
'0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
100n,
])
const suffix = Attribution.toDataSuffix({
codes: ['baseapp', 'morpho'], // [!code hl]
})
// @log: '0x626173656170702c6d6f7270686f0e0080218021802180218021802180218021'
const calldata = Hex.concat(data, suffix)
```
The example above uses schema 0 (canonical registry). Pass a `codeRegistry` for schema 1 (custom
registry), or fields like `appCode`, `walletCode`, and `metadata` for schema 2 (CBOR-encoded).
### Parse Attribution Codes
Extract the attribution from transaction calldata with `Attribution.fromData`. It returns
`undefined` when no valid suffix is present.
```ts twoslash
import { Attribution } from 'ox/erc8021'
const attribution = Attribution.fromData(
'0xdddddddd62617365617070070080218021802180218021802180218021',
)
// @log: { codes: ['baseapp'], id: 0 }
if (attribution?.codes) {
// Resolve `attribution.codes` against the code registry.
}
```
The `id` field reports the schema (`0` canonical registry, `1` custom registry, `2` CBOR-encoded),
so consumers can resolve codes against the right registry.
## Best Practices
### Append the Suffix Last
The ERC-8021 marker must be the final bytes of calldata. Apply the suffix after all other calldata
construction and wrapping, or parsers will not find it.
### Pick the Smallest Schema That Fits
Schema 0 with registered codes is the cheapest. Reach for schema 1 only when you operate a custom
registry, and schema 2 only when you need optional fields or arbitrary metadata.
### Parse Defensively
Any transaction can carry trailing bytes that look like data. `Attribution.fromData` validates the
marker and structure and returns `undefined` otherwise — always handle that case.
## See More
# Batch Calls with ERC-7821
## Overview
[ERC-7821](https://eips.ethereum.org/EIPS/eip-7821) is a minimal interface —
`execute(bytes32 mode, bytes executionData)` — that smart accounts expose to execute a batch of
calls atomically. The [`Calls`](/ercs/erc7821/Calls) module encodes and decodes the
`executionData` payload, and [`Execute`](/ercs/erc7821/Execute) produces complete `execute`
function data with the correct mode.
## Recipes
### Encode a Batch of Calls
Encode an array of `{ to, value, data }` calls into ERC-7821 `executionData` with `Calls.encode`.
```ts twoslash
import { Calls } from 'ox/erc7821'
const executionData = Calls.encode([
{
data: '0xdeadbeef',
to: '0xcafebabecafebabecafebabecafebabecafebabe',
value: 1n,
},
{
data: '0xcafebabe',
to: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
value: 2n,
},
])
```
`value` and `data` are optional and default to `0n` and `0x`. This is only the `executionData`
argument — see the next recipe for complete `execute` calldata.
### Encode an `execute` Payload
Produce the full calldata for the account's `execute` function with `Execute.encodeData`. The
mode is selected automatically based on whether `opData` is present.
```ts twoslash
import { Execute } from 'ox/erc7821'
const data = Execute.encodeData([
{
data: '0xcafebabe',
to: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
value: 1n,
},
])
// With account-defined authorization data (`opData` mode).
const dataWithOpData = Execute.encodeData(
[
{
data: '0xcafebabe',
to: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
value: 1n,
},
],
{ opData: '0xdeadbeef' },
)
```
Use the resulting data as a transaction's `data` field, or as the `callData` of an
[ERC-4337 user operation](/guides/account-abstraction/user-operations).
### Decode Incoming Executions
Recover the calls (and optional `opData`) from `execute` calldata with `Execute.decodeData` — for
example inside a wallet, simulator, or indexer inspecting a batch.
```ts twoslash
import { Hex } from 'ox'
import { Execute } from 'ox/erc7821'
// Calldata for `execute(bytes32,bytes)` (eg. from a transaction request).
declare const data: Hex.Hex
const { calls, opData } = Execute.decodeData(data) // [!code hl]
// @log: {
// @log: calls: [
// @log: {
// @log: data: '0xcafebabe',
// @log: to: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
// @log: value: 1n,
// @log: },
// @log: ],
// @log: }
```
For the "batch of batches" mode, use `Execute.decodeBatchOfBatchesData` (and
`Execute.encodeBatchOfBatchesData` to produce it).
## Best Practices
### Batches Are Ordered and Atomic
ERC-7821 accounts execute calls in order and revert the whole batch if any call fails. Sequence
dependent calls (approve → swap) accordingly, and do not assume partial execution.
### Treat `opData` as Account-Defined
The meaning of `opData` (signatures, paymaster data, nonces) is defined by the account
implementation, not the standard. Encode exactly what the target account expects.
## See More
# Build ERC-4337 User Operations
:::info
This guide is intended to be low-level. If you are looking for a high-level bundler and smart
account client, check out [Viem's Account Abstraction guides](https://viem.sh/account-abstraction).
:::
## Overview
[ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) routes smart account transactions as "user
operations" through bundlers and the EntryPoint contract. The
[`UserOperation`](/ercs/erc4337/UserOperation) module constructs, hashes, signs, and packs user
operations, [`EntryPoint`](/ercs/erc4337/EntryPoint) provides the ABIs and addresses for
EntryPoint versions `0.6`–`0.9`, and [`UserOperationGas`](/ercs/erc4337/UserOperationGas) and
[`UserOperationReceipt`](/ercs/erc4337/UserOperationReceipt) convert bundler RPC responses.
## Recipes
### Construct a User Operation
Instantiate a user operation with `UserOperation.from`. The `callData` is what the smart account
executes — typically an encoded [ERC-7821 batch](/guides/account-abstraction/erc-7821) or another
account-specific `execute` call.
```ts twoslash
import { Value } from 'ox'
import { UserOperation } from 'ox/erc4337'
const userOperation = UserOperation.from({
callData: '0xdeadbeef',
callGasLimit: 300_000n,
maxFeePerGas: Value.fromGwei('20'),
maxPriorityFeePerGas: Value.fromGwei('2'),
nonce: 69n,
preVerificationGas: 100_000n,
sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
verificationGasLimit: 100_000n,
})
```
For a counterfactual (not yet deployed) account on EntryPoint `0.7`+, also set `factory` and
`factoryData` so the EntryPoint can deploy the account on first use.
### Compute the Hash & Sign Payload
Compute the signing payload for a target chain and EntryPoint with
`UserOperation.getSignPayload`, sign it, and attach the signature.
```ts twoslash
import { Secp256k1, Value } from 'ox'
import { EntryPoint, UserOperation } from 'ox/erc4337'
const userOperation = UserOperation.from({
callData: '0xdeadbeef',
callGasLimit: 300_000n,
maxFeePerGas: Value.fromGwei('20'),
maxPriorityFeePerGas: Value.fromGwei('2'),
nonce: 69n,
preVerificationGas: 100_000n,
sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
verificationGasLimit: 100_000n,
})
const payload = UserOperation.getSignPayload(userOperation, {
chainId: 1,
entryPointAddress: EntryPoint.addressV07, // [!code hl]
entryPointVersion: '0.7', // [!code hl]
})
const signature = Secp256k1.sign({
payload,
privateKey: '0x...',
})
const userOperation_signed = UserOperation.from(userOperation, { signature })
```
The same value is the "user operation hash" bundlers and explorers use — compute it directly with
`UserOperation.hash`. On EntryPoint `0.8`+ the payload is EIP-712 based; use
`UserOperation.toTypedData` when signing with a wallet's `eth_signTypedData_v4`.
### Pack for the EntryPoint
EntryPoint `0.7`+ consumes the packed representation onchain. Convert a signed user operation
with `UserOperation.toPacked`, and unpack contract data with `UserOperation.fromPacked`.
```ts twoslash
import { UserOperation } from 'ox/erc4337'
declare const userOperation: UserOperation.UserOperation<'0.7', true>
const packed = UserOperation.toPacked(userOperation) // [!code hl]
// Recover the structured form from a packed user operation.
const unpacked = UserOperation.fromPacked(packed)
```
`UserOperation.toInitCode` computes the packed `initCode` field on its own, including the special
EIP-7702 `0x7702` factory convention.
### Convert to & from RPC
Bundler JSON-RPC methods exchange hex-quantity payloads. Convert with `UserOperation.toRpc` and
submit via a [`RpcTransport`](/api/RpcTransport) typed with the
[`RpcSchema.Bundler`](/ercs/erc4337/RpcSchema) schema.
```ts twoslash
import { RpcSchema, RpcTransport } from 'ox'
import {
EntryPoint,
RpcSchema as RpcSchema_erc4337,
UserOperation,
UserOperationReceipt,
} from 'ox/erc4337'
declare const userOperation: UserOperation.UserOperation<'0.7', true>
const transport = RpcTransport.fromHttp('https://bundler.example.com', {
schema: RpcSchema.from>(),
})
const userOpHash = await transport.request({
method: 'eth_sendUserOperation',
params: [UserOperation.toRpc(userOperation), EntryPoint.addressV07], // [!code hl]
})
const receipt = await transport.request({
method: 'eth_getUserOperationReceipt',
params: [userOpHash],
})
if (receipt) {
const { success, actualGasUsed } = UserOperationReceipt.fromRpc(receipt)
}
```
Convert incoming payloads the other way with `UserOperation.fromRpc`, and gas estimates from
`eth_estimateUserOperationGas` with `UserOperationGas.fromRpc`.
## Best Practices
### Pin the EntryPoint Version
The hash — and therefore the signature — commits to the EntryPoint address, version, and chain ID.
Use the `EntryPoint.addressV06`–`addressV09` constants and keep the `entryPointVersion` consistent
across hashing, signing, and submission.
### Sign After Gas Values Are Final
All gas limits and fee fields are part of the signed hash. Estimate with
`eth_estimateUserOperationGas` first; changing any field after signing invalidates the signature.
### Prefer Typed Data on EntryPoint 0.8+
`UserOperation.toTypedData` produces an EIP-712 definition, so wallet users see a structured,
human-readable signing prompt instead of an opaque hash.
## See More
# Accounts & Keys
## Overview
An Ethereum account is a secp256k1 key pair and the address derived from it. Ox provides the
primitives for the whole key lifecycle: generating [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
mnemonics, deriving [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) HD
keys, computing and validating addresses, and encrypting private keys at rest as JSON keystores.
```ts twoslash
import { Address, Mnemonic, Secp256k1 } from 'ox'
// Generate a mnemonic and derive a private key (`m/44'/60'/0'/0/0`).
const mnemonic = Mnemonic.random(Mnemonic.english)
const privateKey = Mnemonic.toPrivateKey(mnemonic)
// Derive the public key and address.
const publicKey = Secp256k1.getPublicKey({ privateKey })
const address = Address.fromPublicKey(publicKey)
```
## Guides
# Derive & Validate Addresses
## Overview
An Ethereum address is the last 20 bytes of the keccak256 hash of an uncompressed secp256k1
public key. The [`Address`](/api/Address) module derives, checksums, validates, and compares
addresses; the [`PublicKey`](/api/PublicKey) module handles the public keys they are derived
from.
## Recipes
### Derive an Address from a Private Key
Extract the public key with [`Secp256k1.getPublicKey`](/api/Secp256k1/getPublicKey), then
convert it to an address with [`Address.fromPublicKey`](/api/Address/fromPublicKey).
```ts twoslash
import { Address, Secp256k1 } from 'ox'
const privateKey = Secp256k1.randomPrivateKey()
const publicKey = Secp256k1.getPublicKey({ privateKey })
const address = Address.fromPublicKey(publicKey)
```
### Derive an Address from a Public Key
When you already have a serialized public key — for example one recovered from a signature —
instantiate it with [`PublicKey.from`](/api/PublicKey/from) before deriving the address.
```ts twoslash
import { Address, PublicKey } from 'ox'
const publicKey = PublicKey.from(
'0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
)
const address = Address.fromPublicKey(publicKey)
// @log: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
```
Pass `{ checksum: true }` to return the [ERC-55](https://eips.ethereum.org/EIPS/eip-55)
checksummed form instead of lowercase.
### Checksum & Validate an Address
Compute the ERC-55 mixed-case form with [`Address.checksum`](/api/Address/checksum), and check
untrusted input with [`Address.validate`](/api/Address/validate) (returns `false`) or
[`Address.assert`](/api/Address/assert) (throws).
```ts twoslash
import { Address } from 'ox'
const checksummed = Address.checksum(
'0xa0cf798816d4b9b9866b5330eea46a18382f251e',
)
// @log: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
const valid = Address.validate('0xA0Cf798816D4b9b9866b5330EEa46a18382f251e')
// @log: true
const invalid = Address.validate('0xdeadbeef')
// @log: false
```
By default, mixed-case input is also verified against its checksum (`strict: true`). Pass
`{ strict: false }` to accept any correctly-shaped 20-byte hex string. Use
[`Address.from`](/api/Address/from) to convert a validated string into a typed `Address`.
### Compare Addresses
Use [`Address.isEqual`](/api/Address/isEqual) to compare addresses regardless of casing.
```ts twoslash
import { Address } from 'ox'
const equal = Address.isEqual(
'0xa0cf798816d4b9b9866b5330eea46a18382f251e',
'0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
)
// @log: true
```
## Best Practices
### Compare with Address.isEqual, Not ===
The same address can arrive lowercase, uppercase, or checksummed. Strict string equality
produces false negatives; `Address.isEqual` does not.
### Validate at the Boundary
Run `Address.validate` (or `Address.assert`) on user input, RPC responses, and decoded
calldata before storing or acting on an address — checksum verification catches most
transcription errors.
### Checksum for Display
Store and compare addresses in lowercase, but render the `Address.checksum` form in UIs so
users (and their wallets) can spot corruption.
## See More
# Mnemonics & HD Wallets
## Overview
A [BIP-39 mnemonic phrase](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) is a
list of words that is a representation of a seed, which can be used to derive the keys of a
[BIP-32 Hierarchical Deterministic (HD) Wallet](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki).
We can combine a mnemonic phrase (or seed) with an Ethereum-specific derivation path (e.g.
`m/44'/60'/0'/0/0`) to derive a private key and its associated Ethereum address. The
[`Mnemonic`](/api/Mnemonic) module handles phrases; the [`HdKey`](/api/HdKey) module handles
the derived key tree.
## Recipes
### Generate a Random Mnemonic
We can generate a random mnemonic phrase using [`Mnemonic.random`](/api/Mnemonic/random).
```ts twoslash
import { Mnemonic } from 'ox'
const mnemonic = Mnemonic.random(Mnemonic.english)
// @log: 'buyer zoo end danger ice capable shrug naive twist relief mass bonus'
```
Ox supports the following languages:
| Language | Export |
| ------------------- | ----------------------------- |
| English | `Mnemonic.english` |
| Czech | `Mnemonic.czech` |
| French | `Mnemonic.french` |
| Italian | `Mnemonic.italian` |
| Japanese | `Mnemonic.japanese` |
| Korean | `Mnemonic.korean` |
| Portuguese | `Mnemonic.portuguese` |
| Simplified Chinese | `Mnemonic.simplifiedChinese` |
| Spanish | `Mnemonic.spanish` |
| Traditional Chinese | `Mnemonic.traditionalChinese` |
### Derive a Private Key at a Path
Derive a private key from a mnemonic phrase using
[`Mnemonic.toPrivateKey`](/api/Mnemonic/toPrivateKey). This will use the default path of
`m/44'/60'/0'/0/0`.
```ts twoslash
import { Mnemonic } from 'ox'
const mnemonic = Mnemonic.random(Mnemonic.english)
const privateKey = Mnemonic.toPrivateKey(mnemonic)
```
We can also specify a custom path using the [`Mnemonic.path`](/api/Mnemonic/path) function.
```ts twoslash
import { Mnemonic } from 'ox'
const mnemonic = Mnemonic.random(Mnemonic.english)
const path = Mnemonic.path({ account: 1, index: 2 }) // `m/44'/60'/1'/0/2`
const privateKey = Mnemonic.toPrivateKey(mnemonic, { path })
// or, we can pass the path as a string
const privateKey_2 = Mnemonic.toPrivateKey(mnemonic, {
path: "m/44'/60'/1'/0/2",
})
```
Mnemonic private keys are derived on the secp256k1 curve, so an address follows via
[`Secp256k1.getPublicKey`](/api/Secp256k1/getPublicKey) and
[`Address.fromPublicKey`](/api/Address/fromPublicKey) — see
[Derive & Validate Addresses](/guides/accounts/addresses).
### Derive Many Accounts (HD Paths)
Convert the mnemonic to an HD key once with [`Mnemonic.toHdKey`](/api/Mnemonic/toHdKey), then
derive one account per address index.
```ts twoslash
import { Address, Mnemonic } from 'ox'
const mnemonic = Mnemonic.random(Mnemonic.english)
const hdKey = Mnemonic.toHdKey(mnemonic)
const addresses = []
for (let index = 0; index < 3; index++) {
const account = hdKey.derive(Mnemonic.path({ index }))
addresses.push(Address.fromPublicKey(account.publicKey))
}
```
Each `account` also exposes `privateKey`, `publicKey`, and extended keys — see the
[`HdKey`](/api/HdKey) reference.
### Restore an HD Key from a Seed or Extended Key
An HD key does not have to come from a mnemonic. Restore one from a master seed with
[`HdKey.fromSeed`](/api/HdKey/fromSeed), or from a serialized extended private key (`xpriv`)
with [`HdKey.fromExtendedKey`](/api/HdKey/fromExtendedKey).
```ts twoslash
import { HdKey, Mnemonic } from 'ox'
declare const xpriv: string
// From a master seed.
const seed = Mnemonic.toSeed(
'test test test test test test test test test test test junk',
)
const hdKey = HdKey.fromSeed(seed)
// From an extended private key.
const hdKey_2 = HdKey.fromExtendedKey(xpriv)
const account = hdKey.derive(HdKey.path({ index: 0 }))
```
## Best Practices
### Store the Phrase, Not the Keys
Every account is re-derivable from the mnemonic, so the phrase is the single secret worth
protecting. Never persist it in plaintext — encrypt derived keys at rest with a
[JSON keystore](/guides/accounts/keystores).
### Validate Before Deriving
User-entered phrases should be checked with [`Mnemonic.validate`](/api/Mnemonic/validate)
against the expected wordlist before derivation — a typo otherwise silently derives a
different (empty) wallet.
### Use Hardened Account Paths
Stick to the BIP-44 layout that `Mnemonic.path`/`HdKey.path` produce (`m/44'/60'/account'/0/index`).
Non-hardened variations of the same numbers derive entirely different keys and break
interoperability with other wallets.
## See More
# Work with Keystores
## Overview
A [JSON keystore](https://ethereum.org/en/developers/docs/data-structures-and-encoding/web3-secret-storage/)
(Web3 Secret Storage, version 3) stores a private key encrypted under a password-derived key —
the format used by Geth and most wallet export flows. The [`Keystore`](/api/Keystore) module
derives keys with scrypt or PBKDF2 and encrypts/decrypts private keys against them.
## Recipes
### Encrypt a Private Key
Derive an encryption key from a password with [`Keystore.pbkdf2`](/api/Keystore/pbkdf2) (or
[`Keystore.scrypt`](/api/Keystore/scrypt)), then encrypt the private key with
[`Keystore.encrypt`](/api/Keystore/encrypt).
```ts twoslash
import { Keystore, Secp256k1 } from 'ox'
const privateKey = Secp256k1.randomPrivateKey()
// Derive an encryption key from a password.
const [key, opts] = Keystore.pbkdf2({ password: 'testpassword' })
// Encrypt the private key.
const keystore = Keystore.encrypt(privateKey, key, opts)
// @log: {
// @log: "crypto": {
// @log: "cipher": "aes-128-ctr",
// @log: "ciphertext": "...",
// @log: "kdf": "pbkdf2",
// @log: ...
// @log: },
// @log: "id": "...",
// @log: "version": 3,
// @log: }
```
The resulting object is plain JSON — persist it with `JSON.stringify` and it will
interoperate with Geth, ethers, and other keystore-aware tooling.
### Decrypt a Keystore
Re-derive the decryption key from the keystore's stored KDF parameters with
[`Keystore.toKey`](/api/Keystore/toKey), then recover the private key with
[`Keystore.decrypt`](/api/Keystore/decrypt).
```ts twoslash
import { Keystore } from 'ox'
declare const keystore: Keystore.Keystore
// Derive the decryption key from the keystore & password.
const key = Keystore.toKey(keystore, { password: 'testpassword' })
// Decrypt the private key.
const privateKey = Keystore.decrypt(keystore, key)
// @log: '0x...'
```
`toKey` reads which KDF (and which parameters) the keystore was encrypted with, so the same
code handles both scrypt and PBKDF2 keystores.
### Choose scrypt vs PBKDF2
scrypt is memory-hard, making large-scale GPU/ASIC cracking expensive — it is the default in
Geth exports and the better choice for new keystores. PBKDF2 is cheaper to compute (for
attackers too) but universally supported. Both have async variants that keep the main thread
responsive.
```ts twoslash
import { Keystore, Secp256k1 } from 'ox'
const privateKey = Secp256k1.randomPrivateKey()
const [key, opts] = await Keystore.scryptAsync({ password: 'testpassword' })
const keystore = Keystore.encrypt(privateKey, key, opts)
```
See [`Keystore.scryptAsync`](/api/Keystore/scryptAsync) and
[`Keystore.pbkdf2Async`](/api/Keystore/pbkdf2Async) for tuning parameters (cost factor `n`,
iteration count).
## Best Practices
### Prefer the Async KDF Variants
Key derivation is deliberately slow. In browsers, servers, and anything interactive, use
`scryptAsync`/`pbkdf2Async`/[`toKeyAsync`](/api/Keystore/toKeyAsync) so derivation does not
block the event loop.
### The Keystore Is Only as Strong as the Password
The KDF slows brute force; it does not fix a weak password. Keep the default work factors
(218 scrypt cost / 262,144 PBKDF2 iterations) or raise them — never lower them for
convenience.
### Treat Keystore JSON as Sensitive
A keystore file is an offline-crackable target. Store it with the same care as any secret, and
zero out decrypted private keys as soon as they have served their purpose.
## See More
# Chain Data & State
## Overview
Everything a node returns — blocks, receipts, logs, proofs — arrives as hex-encoded RPC objects.
Ox's chain-data modules ([`Block`](/api/Block), [`TransactionReceipt`](/api/TransactionReceipt),
[`Log`](/api/Log), [`Filter`](/api/Filter), [`AccountProof`](/api/AccountProof), and friends)
convert between that wire format and typed JavaScript objects with a consistent `fromRpc`/`toRpc`
pattern. Alongside them sit [`Ens`](/api/Ens) for name hashing, [`Bloom`](/api/Bloom) for log
pre-checks, and [`StateOverrides`](/api/StateOverrides) /
[`BlockOverrides`](/api/BlockOverrides) for simulation.
```ts twoslash
import { Block, RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const block = await transport
.request({ method: 'eth_getBlockByNumber', params: ['latest', false] })
.then(Block.fromRpc) // [!code hl]
// @log: { number: 19868020n, timestamp: 1662222222n, ... }
```
# Query Logs, Filters & Bloom
## Overview
[`Filter`](/api/Filter) expresses `eth_getLogs` queries in typed form, [`Log`](/api/Log) converts
the results, and [`Bloom`](/api/Bloom) checks a block's `logsBloom` before you pay for a log
query. Pair them with [`AbiEvent`](/api/AbiEvent) to build topics from Solidity event signatures.
## Recipes
### Build Log Filters
Encode an event into topics with [`AbiEvent.encode`](/api/AbiEvent/encode), then serialize the
filter for the wire with [`Filter.toRpc`](/api/Filter/toRpc).
```ts twoslash
import { AbiEvent, Filter, RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)',
)
const { topics } = AbiEvent.encode(transfer)
const filter = Filter.toRpc({
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
fromBlock: 19760235n,
toBlock: 19760240n,
topics,
})
const logs = await transport.request({
method: 'eth_getLogs',
params: [filter],
})
```
The same RPC filter object works with `eth_newFilter` + `eth_getFilterChanges` for
polling-based subscriptions.
### Convert RPC Logs
[`Log.fromRpc`](/api/Log/fromRpc) converts hex block numbers and indices into `bigint` and
`number` values.
```ts twoslash
import { Log, RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const logs = await transport.request({
method: 'eth_getLogs',
params: [
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
fromBlock: '0x12d846b',
toBlock: '0x12d8470',
},
],
})
const converted = logs.map((log) => Log.fromRpc(log))
// @log: [{
// @log: address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
// @log: blockNumber: 19760236n,
// @log: logIndex: 271,
// @log: ...
// @log: }]
```
To decode a log's `topics` and `data` into named event arguments, use
[`AbiEvent.decode`](/api/AbiEvent/decode) — see
[Work with Events & Logs](/guides/abi/events).
### Pre-Check Membership with Bloom Filters
Every block header carries a 256-byte `logsBloom`. [`Bloom.contains`](/api/Bloom/contains) tests
whether an address or topic *may* appear in the block's logs, letting you skip `eth_getLogs`
calls for blocks that definitely contain nothing of interest.
```ts twoslash
import { Block, Bloom, RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const block = await transport
.request({ method: 'eth_getBlockByNumber', params: ['latest', false] })
.then(Block.fromRpc)
const mayContain = Bloom.contains(
block!.logsBloom,
'0xef2d6d194084c2de36e0dabfce45d046b37d1106',
)
// @log: true
```
For repeated checks against the same bloom, use [`Bloom.prepare`](/api/Bloom/prepare) with
[`Bloom.containsPrepared`](/api/Bloom/containsPrepared) to skip the per-call conversion.
## Best Practices
### Treat Bloom Hits as Maybes
Bloom filters are probabilistic: a negative result is definitive, but a positive result may be a
false positive. Always confirm a hit by fetching and decoding the actual logs.
### Scope Filters Tightly
Providers cap `eth_getLogs` ranges and result sizes. Constrain `address`, `topics`, and the block
range, and paginate long backfills in fixed-size windows.
## See More
# Resolve ENS Names
## Overview
[`Ens`](/api/Ens) provides the local primitives of ENS resolution: normalizing names, hashing
them into registry keys, and computing multichain coin types. The onchain half — querying the
registry and resolver contracts — needs a transport or client; for a batteries-included flow, use
[Viem's ENS actions](https://viem.sh/docs/ens/actions/getEnsAddress).
## Recipes
### Normalize a Name
User input must be normalized per [ENSIP-15](https://docs.ens.domains/ensip/15) before hashing or
display. [`Ens.normalize`](/api/Ens/normalize) applies UTS-46 normalization and throws on
disallowed characters.
```ts twoslash
import { Ens } from 'ox'
const name = Ens.normalize('WEVM.eth')
// @log: 'wevm.eth'
```
### Compute Namehash & Labelhash
[`Ens.namehash`](/api/Ens/namehash) hashes a full name into the node used as the key of the ENS
registry; [`Ens.labelhash`](/api/Ens/labelhash) hashes a single label (e.g. for registrar token
IDs).
```ts twoslash
import { Ens } from 'ox'
const node = Ens.namehash('wevm.eth')
// @log: '0x08c85f2f4059e930c45a6aeff9dcd3bd95dc3c5c1cddef6a0626b31152248560'
const label = Ens.labelhash('wevm')
// @log: '0xcca19c3b64f2cbc38b510a15f4c577cb455225ed774a1e100cd539af6d3f2eb7'
```
Pass the `namehash` output to registry and resolver calls such as `resolver(bytes32)` and
`addr(bytes32)`.
### Coin Types for Multichain Addresses
Multichain resolvers key addresses by [ENSIP-11](https://docs.ens.domains/ensip/11) coin type.
[`Ens.toCoinType`](/api/Ens/toCoinType) converts an EVM chain ID into its coin type.
```ts twoslash
import { Ens } from 'ox'
const coinType = Ens.toCoinType(10n)
// @log: 2147483658n
const mainnet = Ens.toCoinType(1n)
// @log: 60n
```
Mainnet maps to the SLIP-44 Ether coin type (`60`); other EVM chains set the most significant
bit over their chain ID.
## Best Practices
### Normalize Before Hashing
`namehash` and `labelhash` operate on raw strings — hashing an unnormalized name produces a
different node than wallets and resolvers expect. Run every user-supplied name through
`Ens.normalize` first.
### Never Trust a Name Without Forward Resolution
When displaying a reverse-resolved name, resolve it forward again and check that it maps back to
the original address before treating the name as verified.
## See More
# Simulate with State Overrides
## Overview
`eth_call` and `eth_simulateV1` accept override sets that ephemerally patch chain state for the
duration of a call. [`StateOverrides`](/api/StateOverrides) types per-account overrides
(balance, nonce, code, storage) and [`BlockOverrides`](/api/BlockOverrides) types the block
context (number, timestamp, fees); both convert to the wire format with `toRpc`.
## Recipes
### Override Balances & Code for `eth_call`
Give the caller a funded balance or swap a contract's bytecode with
[`StateOverrides.toRpc`](/api/StateOverrides/toRpc), then pass the set as the third parameter of
`eth_call`.
```ts twoslash
import { RpcTransport, StateOverrides } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const stateOverrides = StateOverrides.toRpc({
// Fund the caller with 1 ETH.
'0xd2135CfB216b74109775236E36d4b433F1DF507B': {
balance: 1_000_000_000_000_000_000n, // [!code hl]
},
// Replace the callee's bytecode with a mock.
'0x0D44f617435088c947F00B31160f64b074e412B4': {
code: '0x6042805f5260205ff3', // [!code hl]
},
})
const result = await transport.request({
method: 'eth_call',
params: [
{
from: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
to: '0x0D44f617435088c947F00B31160f64b074e412B4',
data: '0xdeadbeef',
},
'latest',
stateOverrides, // [!code hl]
],
})
```
Storage can be overridden too: `state` replaces the account's entire storage, while `stateDiff`
patches individual slots.
### Override Block Context
Simulate a call as if it executed in a different block — a future timestamp, another block
number, or a custom base fee — with [`BlockOverrides.toRpc`](/api/BlockOverrides/toRpc) as the
fourth `eth_call` parameter.
```ts twoslash
import { BlockOverrides, RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const blockOverrides = BlockOverrides.toRpc({
number: 19868021n, // [!code hl]
time: 1735689600n, // [!code hl]
})
const result = await transport.request({
method: 'eth_call',
params: [
{
to: '0x0D44f617435088c947F00B31160f64b074e412B4',
data: '0xdeadbeef',
},
'latest',
{},
blockOverrides, // [!code hl]
],
})
```
`eth_simulateV1` accepts the same `stateOverrides` and `blockOverrides` objects per simulated
block in its `blockStateCalls`.
## Best Practices
### Prefer `stateDiff` over `state`
`state` wipes every storage slot the override does not mention, which silently breaks contracts
that read untouched slots. Use `stateDiff` unless you intend to replace the whole storage layout.
### Build Overrides in Typed Form
Keep balances and nonces as `bigint` throughout your code and convert once at the boundary with
`toRpc` — hand-built hex quantities are a common source of off-by-encoding bugs.
## See More
# Verify State & Account Proofs
## Overview
[`AccountProof`](/api/AccountProof) types the Merkle proofs returned by `eth_getProof`, covering
an account's balance, nonce, code hash, and storage slots.
[`BinaryStateTree`](/api/BinaryStateTree) implements the
[EIP-7864](https://eips.ethereum.org/EIPS/eip-7864) binary state tree, the proposed successor to
Ethereum's hexary state trie.
## Recipes
### Fetch & Convert `eth_getProof` Results
Request a proof for an account and a set of storage keys, then decode it with
[`AccountProof.fromRpc`](/api/AccountProof/fromRpc).
```ts twoslash
import { AccountProof, RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const proof = await transport
.request({
method: 'eth_getProof',
params: [
'0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
['0x0000000000000000000000000000000000000000000000000000000000000000'],
'latest',
],
})
.then(AccountProof.fromRpc)
// @log: {
// @log: address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
// @log: balance: 1n,
// @log: nonce: 2,
// @log: storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
// @log: accountProof: [...],
// @log: storageProof: [{ key: '0x00...00', proof: [...], value: 3n }],
// @log: }
```
The `accountProof` and `storageProof` arrays contain the RLP-encoded trie nodes linking the
account (and each storage slot) to the block's `stateRoot`.
### Work with Binary State Trees (EIP-7864)
Build a binary state tree from key-value pairs and compute its Merkle root with
[`BinaryStateTree.merkelize`](/api/BinaryStateTree/merkelize).
```ts twoslash
import { BinaryStateTree, Bytes } from 'ox'
const tree = BinaryStateTree.create()
BinaryStateTree.insert(
tree,
Bytes.fromHex(
'0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54',
),
Bytes.fromHex(
'0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1',
),
)
const root = BinaryStateTree.merkelize(tree)
```
Keys are split into a 31-byte stem and a 1-byte sub-index, mirroring the EIP-7864 layout.
## Best Practices
### Verify Against a Trusted Root
A proof is only as good as the root it is checked against. Compare proofs to the `stateRoot` of a
block header you have independently verified (or received from a trusted light-client protocol),
not to a value returned by the same untrusted node.
### Pin the Block
Fetch proofs with an explicit block number or hash rather than `latest`, so the proof and the
header you verify against cannot drift across a reorg between requests.
## See More
# Work with Blocks & Receipts
## Overview
[`Block`](/api/Block), [`Withdrawal`](/api/Withdrawal), and
[`TransactionReceipt`](/api/TransactionReceipt) convert between the hex-quantity RPC
representation and typed objects with `bigint` quantities. Each module offers `fromRpc` for
decoding node responses and `toRpc` for serializing back to the wire format.
## Recipes
### Convert an RPC Block to a Typed Object
Fetch a block with `eth_getBlockByNumber` and pass the result to
[`Block.fromRpc`](/api/Block/fromRpc).
```ts twoslash
import { Block, RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const block = await transport
.request({ method: 'eth_getBlockByNumber', params: ['latest', false] })
.then(Block.fromRpc)
// @log: {
// @log: hash: '0xebc3644804e4040c0a74c5a5bbbc6b46a71a5d4010fe0c92ebb2fdf4a43ea5dd',
// @log: number: 19868020n,
// @log: size: 520n,
// @log: timestamp: 1662222222n,
// @log: ...
// @log: }
```
`Block.fromRpc` returns `null` when the block is not found, and converts embedded transactions
when the block was fetched with full transaction objects.
### Read Consensus Withdrawals
Post-Shanghai blocks embed validator withdrawals. `Block.fromRpc` converts the embedded
`withdrawals` list automatically; use [`Withdrawal.fromRpc`](/api/Withdrawal/fromRpc) for
standalone RPC values.
```ts twoslash
import { Withdrawal } from 'ox'
const withdrawal = Withdrawal.fromRpc({
address: '0x00000000219ab540356cBB839Cbe05303d7705Fa',
amount: '0x620323',
index: '0x0',
validatorIndex: '0x1',
})
// @log: {
// @log: address: '0x00000000219ab540356cBB839Cbe05303d7705Fa',
// @log: amount: 6423331n,
// @log: index: 0,
// @log: validatorIndex: 1
// @log: }
```
The `amount` is denominated in Gwei, as defined by the consensus specification.
### Convert Receipts
Fetch a receipt with `eth_getTransactionReceipt` and decode it with
[`TransactionReceipt.fromRpc`](/api/TransactionReceipt/fromRpc), which also converts the
receipt's embedded logs and maps `status` and `type` to their named variants.
```ts twoslash
import { RpcTransport, TransactionReceipt } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const receipt = await transport
.request({
method: 'eth_getTransactionReceipt',
params: [
'0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0',
],
})
.then(TransactionReceipt.fromRpc)
// @log: {
// @log: blockNumber: 19868015n,
// @log: gasUsed: 175034n,
// @log: status: 'success',
// @log: type: 'eip1559',
// @log: ...
// @log: }
```
## Best Practices
### Handle the `null` Case
`eth_getBlockByNumber` and `eth_getTransactionReceipt` return `null` for unknown hashes and
not-yet-mined transactions — the `fromRpc` functions preserve that `null` in their return type,
so narrow before use.
### Round-Trip with `toRpc`
When persisting or forwarding chain data, serialize typed objects back to the wire format with
`Block.toRpc`, `Withdrawal.toRpc`, and `TransactionReceipt.toRpc` instead of hand-rolling hex
conversions.
## See More
# Cryptography
## Overview
The signing curves, hashes, and ciphers Ethereum (and its ecosystem) runs on — audited
implementations, tree-shakable. Modules such as [`Secp256k1`](/api/Secp256k1),
[`P256`](/api/P256), and [`Hash`](/api/Hash) expose stateless functions that accept and return
`Hex` or `Bytes`. Heavy algorithms (BLS12-381, ML-DSA, some hashes) can be backed by pluggable
[engines](/guides/runtime/engines) such as WASM or native Node.js crypto.
```ts twoslash
import { Hash, Hex, Secp256k1 } from 'ox'
declare const privateKey: Hex.Hex
const payload = Hash.keccak256(Hex.fromString('agree to terms'))
// @log: '0x6f7a…b21c'
const signature = Secp256k1.sign({ payload, privateKey })
// @log: { r: '0x1c34…', s: '0x4f8d…', yParity: 0 }
const signer = Secp256k1.recoverAddress({ payload, signature })
// @log: '0x71bE63f3384f5fb98995898A86B02Fb2426c5788'
```
# BLS Signatures & Aggregation
## Overview
[`Bls`](/api/Bls) implements BLS12-381 signatures — the scheme Ethereum consensus validators
use — with points represented as structured [`BlsPoint`](/api/BlsPoint) values. By default,
public keys are short G1 points (48 bytes) and signatures are long G2 points (96 bytes); pass
`size: 'long-key:short-sig'` to flip that trade-off. Pairing operations are heavy, so the
default implementation can be swapped for a faster backend via
[engines](/guides/runtime/engines).
## Recipes
### Sign and Verify a Payload
[`Bls.createKeyPair`](/api/Bls/createKeyPair) generates a key pair, and
[`Bls.sign`](/api/Bls/sign) / [`Bls.verify`](/api/Bls/verify) sign and check payloads.
```ts twoslash
import { Bls, Hex } from 'ox'
const payload = Hex.random(32)
const { privateKey, publicKey } = Bls.createKeyPair()
const signature = Bls.sign({ payload, privateKey }) // [!code hl]
const verified = Bls.verify({ payload, publicKey, signature })
// @log: true
```
`verify` infers the point groups from the inputs, so it works unchanged with either key size.
### Aggregate Signatures and Public Keys
[`Bls.aggregate`](/api/Bls/aggregate) combines many signatures over the same payload into one,
and many public keys into one — a single pairing check then verifies the whole set.
```ts twoslash
import { Bls, Hex } from 'ox'
const payload = Hex.random(32)
const privateKeys = Array.from({ length: 100 }, () => Bls.randomPrivateKey())
const publicKeys = privateKeys.map((privateKey) =>
Bls.getPublicKey({ privateKey }),
)
const signatures = privateKeys.map((privateKey) =>
Bls.sign({ payload, privateKey }),
)
const publicKey = Bls.aggregate(publicKeys) // [!code hl]
const signature = Bls.aggregate(signatures) // [!code hl]
const verified = Bls.verify({ payload, publicKey, signature })
// @log: true
```
All points in one call must come from the same group. When aggregating serialized (hex or
bytes) points, pass `{ group: 'G1' }` or `{ group: 'G2' }` so they can be deserialized.
### Serialize BLS Points
Structured points serialize to compressed hex or bytes with
[`BlsPoint.toHex`](/api/BlsPoint/toHex) and [`BlsPoint.toBytes`](/api/BlsPoint/toBytes), and
deserialize with [`BlsPoint.fromHex`](/api/BlsPoint/fromHex) and
[`BlsPoint.fromBytes`](/api/BlsPoint/fromBytes).
```ts twoslash
import { Bls, BlsPoint, Hex } from 'ox'
const payload = Hex.random(32)
const { privateKey, publicKey } = Bls.createKeyPair()
const signature = Bls.sign({ payload, privateKey })
const publicKeyHex = BlsPoint.toHex(publicKey) // [!code hl]
// @log: '0xacafff52…b32d9e66' (48 bytes)
const signatureHex = BlsPoint.toHex(signature)
// @log: '0xb4698f76…4ebe427c' (96 bytes)
const publicKey2 = BlsPoint.fromHex(publicKeyHex, 'G1')
const signature2 = BlsPoint.fromHex(signatureHex, 'G2')
```
Deserialization needs the group name because 48-byte values are G1 and 96-byte values are G2.
## Best Practices
### Aggregate Over a Single Payload
A plain aggregate verification assumes every signer signed the same payload. Mixing payloads
without a proof-of-possession scheme opens rogue-key attacks — stick to one payload per
aggregate unless you know why you are deviating.
### Install a Faster Engine for Bulk Verification
Pairing checks dominate BLS cost. For validator-scale workloads, install the WASM or Node
[engine](/guides/runtime/engines) instead of the pure-JS default.
## See More
# Convert Signature Formats
## Overview
[`Signature`](/api/Signature) is the structured ECDSA form every Ox signer returns: an object
with `r`, `s`, and an optional recovery bit `yParity`. The module converts between that shape
and every serialized form you will meet in the wild — 64/65-byte hex, DER, compact bytes,
legacy `v` values, JSON-RPC objects, and RLP tuples.
## Recipes
### Instantiate a Signature
[`Signature.from`](/api/Signature/from) accepts a structured object — or any serialized form,
which it parses automatically.
```ts twoslash
import { Signature } from 'ox'
const signature = Signature.from({
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
yParity: 0,
})
const parsed = Signature.from(
'0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db81b',
)
// @log: { r: '0x6e100a35…', s: '0x4a90a229…', yParity: 0 }
```
### Convert Between Hex, Bytes, and Objects
[`Signature.toHex`](/api/Signature/toHex) serializes a signature to its 65-byte form, and
[`Signature.fromHex`](/api/Signature/fromHex) parses it back.
```ts twoslash
import { Signature } from 'ox'
const signature = Signature.from({
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
yParity: 0,
})
const hex = Signature.toHex(signature) // [!code hl]
// @log: '0x6e100a35…6db81b'
const restored = Signature.fromHex(hex)
// @log: { r: '0x6e100a35…', s: '0x4a90a229…', yParity: 0 }
```
[`Signature.toBytes`](/api/Signature/toBytes) and
[`Signature.fromBytes`](/api/Signature/fromBytes) do the same for `Uint8Array` values, and
[`Signature.from`](/api/Signature/from) accepts any of these forms directly.
### Convert DER and Compact Forms
Hardware modules and Web Crypto emit DER; some verifiers expect a bare 64-byte `r ++ s`
encoding. Use [`Signature.toDerHex`](/api/Signature/toDerHex) and
[`Signature.toCompactBytes`](/api/Signature/toCompactBytes) to produce them.
```ts twoslash
import { Signature } from 'ox'
const signature = Signature.from({
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
})
const der = Signature.toDerHex(signature) // [!code hl]
// @log: '0x304402206e100a35…6db8'
const compact = Signature.toCompactBytes(signature)
// @log: Uint8Array [110, 16, 10, …] (64 bytes)
const fromDer = Signature.fromDerHex(der)
```
[`Signature.fromDerBytes`](/api/Signature/fromDerBytes) and
[`Signature.fromCompactBytes`](/api/Signature/fromCompactBytes) parse the byte variants. DER
and compact forms carry no recovery bit, so the results have no `yParity`.
### Convert Legacy v and yParity
Pre-EIP-155 tooling encodes the recovery bit as `v` (27/28).
[`Signature.fromLegacy`](/api/Signature/fromLegacy) and
[`Signature.toLegacy`](/api/Signature/toLegacy) translate whole signatures;
[`Signature.vToYParity`](/api/Signature/vToYParity) and
[`Signature.yParityToV`](/api/Signature/yParityToV) translate just the bit.
```ts twoslash
import { Signature } from 'ox'
const signature = Signature.fromLegacy({
r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf',
s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8',
v: 28, // [!code hl]
})
// @log: { r: '0x6e100a35…', s: '0x4a90a229…', yParity: 1 }
const legacy = Signature.toLegacy(signature)
// @log: { r: '0x6e100a35…', s: '0x4a90a229…', v: 28 }
const yParity = Signature.vToYParity(28)
// @log: 1
const v = Signature.yParityToV(1)
// @log: 28
```
### Convert RPC and Tuple Formats
JSON-RPC responses hex-encode `yParity`; transaction envelopes and EIP-7702 authorization
lists serialize signatures as RLP tuples. [`Signature.fromRpc`](/api/Signature/fromRpc),
[`Signature.toRpc`](/api/Signature/toRpc), [`Signature.fromTuple`](/api/Signature/fromTuple),
and [`Signature.toTuple`](/api/Signature/toTuple) cover both.
```ts twoslash
import { Signature } from 'ox'
const signature = Signature.fromRpc({
r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
yParity: '0x0',
})
const rpc = Signature.toRpc(signature) // [!code hl]
// @log: { r: '0x635dc203…', s: '0x50c2667a…', yParity: '0x0' }
const tuple = Signature.toTuple(signature)
// @log: [yParity: '0x', r: '0x635dc203…', s: '0x50c2667a…']
const restored = Signature.fromTuple(tuple)
```
`fromRpc` also accepts responses that carry a legacy `v` field instead of `yParity`.
## Best Practices
### Preserve yParity
Recovery-based verification (and `eth_sendRawTransaction`) needs the recovery bit. Only drop
to DER or compact forms when the verifier holds the public key.
### Validate Untrusted Input
Run externally supplied signatures through
[`Signature.validate`](/api/Signature/validate) (boolean) or
[`Signature.assert`](/api/Signature/assert) (throws) before use — both check the `r`, `s`,
and `yParity` ranges.
## See More
# Ed25519 & X25519
## Overview
[`Ed25519`](/api/Ed25519) provides EdDSA signatures and [`X25519`](/api/X25519) provides
Diffie-Hellman key agreement, both on Curve25519. They are the workhorses of off-chain
infrastructure — session keys, encrypted channels, p2p identities — and complement the ECDSA
curves Ethereum uses onchain. Keys, signatures, and secrets are plain `Hex` or `Bytes` values.
## Recipes
### Sign and Verify with Ed25519
[`Ed25519.createKeyPair`](/api/Ed25519/createKeyPair) generates a key pair;
[`Ed25519.sign`](/api/Ed25519/sign) and [`Ed25519.verify`](/api/Ed25519/verify) sign and check
payloads.
```ts twoslash
import { Ed25519 } from 'ox'
const { privateKey, publicKey } = Ed25519.createKeyPair()
const signature = Ed25519.sign({ payload: '0xdeadbeef', privateKey }) // [!code hl]
const verified = Ed25519.verify({
payload: '0xdeadbeef',
publicKey,
signature,
})
// @log: true
```
Ed25519 hashes internally, so payloads of any length can be signed directly — no keccak256
step required.
### Derive a Shared Secret with X25519
[`X25519.getSharedSecret`](/api/X25519/getSharedSecret) computes the same 32-byte secret on
both sides of an exchange from one party's private key and the other's public key.
```ts twoslash
import { X25519 } from 'ox'
const alice = X25519.createKeyPair()
const bob = X25519.createKeyPair()
const sharedSecretAlice = X25519.getSharedSecret({
privateKey: alice.privateKey, // [!code hl]
publicKey: bob.publicKey, // [!code hl]
})
const sharedSecretBob = X25519.getSharedSecret({
privateKey: bob.privateKey,
publicKey: alice.publicKey,
})
// @log: sharedSecretAlice === sharedSecretBob
```
Feed the secret into a KDF before using it as an encryption key — see
[Work with AES-GCM](/guides/crypto/encryption).
### Reuse an Ed25519 Key Pair for X25519
An existing Ed25519 identity can also perform key agreement.
[`Ed25519.toX25519PrivateKey`](/api/Ed25519/toX25519PrivateKey) and
[`Ed25519.toX25519PublicKey`](/api/Ed25519/toX25519PublicKey) convert signing keys to their
Montgomery-curve equivalents.
```ts twoslash
import { Ed25519, X25519 } from 'ox'
const signer = Ed25519.createKeyPair()
const peer = Ed25519.createKeyPair()
const sharedSecret = X25519.getSharedSecret({
privateKey: Ed25519.toX25519PrivateKey({ privateKey: signer.privateKey }), // [!code hl]
publicKey: Ed25519.toX25519PublicKey({ publicKey: peer.publicKey }), // [!code hl]
})
```
Both parties convert their own private key and the peer's public key, then derive the secret
as usual.
## Best Practices
### Run Shared Secrets Through a KDF
Raw X25519 output is a curve point coordinate, not a uniformly random key. Derive the actual
symmetric key with HKDF or [`Hash.hmac256`](/api/Hash/hmac256) before encrypting.
### Separate Long-Lived Identities from Session Keys
Key conversion is convenient, but a compromised session secret should not burn a signing
identity. Prefer fresh X25519 pairs per session and sign them with the Ed25519 identity.
## See More
# Hash Data
## Overview
[`Hash`](/api/Hash) computes the digests Ethereum and its ecosystem rely on: keccak256 for
addresses, selectors, and sign payloads, plus SHA-256, RIPEMD-160, HMAC-SHA256, and BLAKE3.
Every function accepts `Hex` or `Bytes` and returns the same format it was given. The default
implementation is the audited [noble-hashes](https://github.com/paulmillr/noble-hashes)
library; a faster backend can be installed via [engines](/guides/runtime/engines).
## Recipes
### Hash with Keccak256
[`Hash.keccak256`](/api/Hash/keccak256) is Ethereum's canonical hash — use it for sign
payloads, event topics, and anything consumed onchain.
```ts twoslash
import { Hash, Hex } from 'ox'
const hash = Hash.keccak256(Hex.fromString('hello world')) // [!code hl]
// @log: '0x3ea2f1d0abf3fc66cf29eebb70cbd4e7fe762ef8a09bcc06c8edf641230afec0'
```
Pass `{ as: 'Bytes' }` to get a `Uint8Array` regardless of the input format.
### Hash with SHA-256 and RIPEMD-160
[`Hash.sha256`](/api/Hash/sha256) and [`Hash.ripemd160`](/api/Hash/ripemd160) cover the
precompile-backed hashes (addresses `0x02` and `0x03`) and Bitcoin-style key hashing.
```ts twoslash
import { Hash } from 'ox'
const sha = Hash.sha256('0xdeadbeef')
// @log: '0x5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953'
const ripemd = Hash.ripemd160('0xdeadbeef')
// @log: '0x226821c2f5423e11fe9af68bd285c249db2e4b5a'
```
### Compute HMAC and BLAKE3
[`Hash.hmac256`](/api/Hash/hmac256) produces keyed HMAC-SHA256 digests — the standard tool for
deriving keys from shared secrets. [`Hash.blake3`](/api/Hash/blake3) is a fast modern hash for
content addressing and checksums.
```ts twoslash
import { Hash, Hex } from 'ox'
const mac = Hash.hmac256(Hex.fromString('secret-key'), '0xdeadbeef') // [!code hl]
const digest = Hash.blake3('0xdeadbeef')
// @log: '0x53147f3ce49ed4f60dfa5b9654c36ba6103c11f5737df3dabd4cbd296c4161bd'
```
### Hash Incrementally
For streamed or chunked data, the `create*` variants ([`Hash.createKeccak256`](/api/Hash/createKeccak256),
[`Hash.createSha256`](/api/Hash/createSha256), [`Hash.createRipemd160`](/api/Hash/createRipemd160),
[`Hash.createHmac256`](/api/Hash/createHmac256), [`Hash.createBlake3`](/api/Hash/createBlake3))
return a stateful hasher that absorbs any number of chunks.
```ts twoslash
import { Hash } from 'ox'
const hasher = Hash.createKeccak256()
hasher.update('0xdead')
hasher.update('0xbeef')
const hash = hasher.digest() // [!code hl]
// @log: '0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1'
```
`digest` consumes the state — call `clone()` first to branch several digests from the same
prefix.
## Best Practices
### Use keccak256 for Anything Onchain
Addresses, function selectors, event topics, and EIP-191/EIP-712 sign payloads are all
keccak256. Reach for SHA-256 only when a spec (WebAuthn, P256, precompiles) demands it.
### Validate Digest Inputs
When accepting a "hash" from external input, [`Hash.validate`](/api/Hash/validate) checks that
the value is well-formed 32-byte hex before you use it as a sign payload.
## See More
# Post-Quantum Signatures (ML-DSA)
## Overview
[`MlDsa44`](/api/MlDsa44) implements ML-DSA-44 (FIPS 204, the standardized Dilithium2) — a
lattice-based signature scheme that stays secure against quantum attackers. The private key is
a compact 32-byte seed; the public key is 1,312 bytes and signatures are 2,420 bytes. The
default implementation can be swapped for a faster backend via
[engines](/guides/runtime/engines).
## Recipes
### Generate Keys, Sign, and Verify
[`MlDsa44.createKeyPair`](/api/MlDsa44/createKeyPair) generates the seed and expands its
public key; [`MlDsa44.sign`](/api/MlDsa44/sign) and [`MlDsa44.verify`](/api/MlDsa44/verify)
mirror the ECDSA signer APIs.
```ts twoslash
import { MlDsa44 } from 'ox'
const { privateKey, publicKey } = MlDsa44.createKeyPair()
const signature = MlDsa44.sign({ payload: '0xdeadbeef', privateKey }) // [!code hl]
const verified = MlDsa44.verify({
payload: '0xdeadbeef',
publicKey,
signature,
})
// @log: true
```
The 32-byte seed is the canonical interchange form of an ML-DSA private key — back up the
seed, and [`MlDsa44.getPublicKey`](/api/MlDsa44/getPublicKey) deterministically re-derives the
public key.
### Domain-Separate with a Context String
FIPS 204 supports a context string (up to 255 bytes) so signatures from one protocol cannot be
replayed in another. Pass the same `context` to both `sign` and `verify`.
```ts twoslash
import { Hex, MlDsa44 } from 'ox'
const { privateKey, publicKey } = MlDsa44.createKeyPair()
const context = Hex.fromString('my-app:login:v1')
const signature = MlDsa44.sign({
context, // [!code hl]
payload: '0xdeadbeef',
privateKey,
})
const verified = MlDsa44.verify({
context, // [!code hl]
payload: '0xdeadbeef',
publicKey,
signature,
})
// @log: true
```
Verification with a different (or missing) context returns `false`.
## Best Practices
### Enable Hedged Signing on Hardware
Signing is deterministic by default. Pass `extraEntropy: true` to `sign` for the hedged FIPS
204 variant, which protects against fault attacks and randomness-reuse pitfalls at the cost of
reproducibility.
### Budget for Signature Size
At 2,420 bytes per signature and 1,312 bytes per public key, ML-DSA payloads are two orders of
magnitude larger than ECDSA. Plan storage and calldata costs accordingly before committing to
onchain verification.
## See More
# Work with AES-GCM
## Overview
[`AesGcm`](/api/AesGcm) wraps the Web Crypto API's
[AES-GCM](https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams) cipher, which combines
high-performance encryption with built-in message integrity. Keys are non-extractable
`CryptoKey`s derived from a password with [`AesGcm.getKey`](/api/AesGcm/getKey) (PBKDF2) or
from a WebAuthn PRF output with [`AesGcm.fromPrf`](/api/AesGcm/fromPrf). All functions are
async.
## Recipes
### Derive a Key from a Password
[`AesGcm.getKey`](/api/AesGcm/getKey) stretches a password into an AES-256-GCM key using
PBKDF2 (900,000 iterations by default).
```ts twoslash
import { AesGcm } from 'ox'
const key = await AesGcm.getKey({ password: 'qwerty' }) // [!code hl]
// @log: CryptoKey {}
```
A random salt is generated per call — pass explicit `salt` (and optionally `iterations`)
[options](/api/AesGcm/getKey) and persist the salt, or a key derived later from the same
password will not decrypt earlier data.
### Encrypt Data
[`AesGcm.encrypt`](/api/AesGcm/encrypt) encrypts `Hex` or `Bytes` data with the derived key.
```ts twoslash
import { AesGcm, Hex } from 'ox'
const key = await AesGcm.getKey({ password: 'qwerty' })
const data = Hex.fromString('i am top secret')
const encrypted = await AesGcm.encrypt(data, key) // [!code hl]
// @log: '0x5e257b25bcf53d5431e54e5a68ca0138306d31bb6154f35a97bb8ea18111e7d82bcf619d3c76c4650688bc5310eed80b8fc86d1e3e'
```
A fresh random initialization vector is generated on every call and prepended to the
ciphertext, so the output is self-contained.
### Decrypt Data
[`AesGcm.decrypt`](/api/AesGcm/decrypt) reads the prepended IV and returns the original data.
GCM authentication means tampered ciphertext throws instead of decrypting to garbage.
```ts twoslash
import { AesGcm, Hex } from 'ox'
const key = await AesGcm.getKey({ password: 'qwerty' })
const data = Hex.fromString('i am top secret')
const encrypted = await AesGcm.encrypt(data, key)
const decrypted = await AesGcm.decrypt(encrypted, key) // [!code hl]
// @log: '0x6920616d20746f7020736563726574'
```
Convert back to a string with [`Hex.toString`](/api/Hex/toString).
## Best Practices
### Persist the Salt
The default random salt makes each derived key unique. Store it (it is not secret) next to the
ciphertext and pass it back to `getKey` when decrypting.
### Prefer Hardware-Derived Keys Over Passwords
Where a passkey is available, [`AesGcm.fromPrf`](/api/AesGcm/fromPrf) derives the key from the
authenticator's PRF output — no password to phish or brute-force. See
[Derive Secrets with PRF](/guides/webauthn/prf).
## See More
# Work with P256
## Overview
[`P256`](/api/P256) implements ECDSA and ECDH on the NIST P256 (secp256r1) curve — the curve
used by passkeys, secure enclaves, and much of Ethereum account abstraction. Signatures and
public keys use the same structured [`Signature`](/api/Signature) and
[`PublicKey`](/api/PublicKey) shapes as `Secp256k1`, so the two signers are interchangeable at
the type level.
## Recipes
### Create a Key Pair
[`P256.createKeyPair`](/api/P256/createKeyPair) generates a random private key and its
corresponding public key in one call.
```ts twoslash
import { P256 } from 'ox'
const { privateKey, publicKey } = P256.createKeyPair() // [!code hl]
// @log: {
// @log: privateKey: '0x…',
// @log: publicKey: { prefix: 4, x: '0x…', y: '0x…' },
// @log: }
```
[`P256.randomPrivateKey`](/api/P256/randomPrivateKey) and
[`P256.getPublicKey`](/api/P256/getPublicKey) perform the two steps separately.
### Sign a Payload
[`P256.sign`](/api/P256/sign) signs the payload as-is and returns a structured signature with
a recovery bit.
```ts twoslash
import { Hex, P256 } from 'ox'
declare const privateKey: Hex.Hex
const signature = P256.sign({ payload: '0xdeadbeef', privateKey }) // [!code hl]
// @log: { r: '0x…', s: '0x…', yParity: 0 }
```
Pass `hash: true` to SHA-256-hash the payload before signing — matching what WebAuthn
authenticators and Web Crypto verifiers expect.
### Verify a Signature
[`P256.verify`](/api/P256/verify) checks a signature against the payload and the signer's
public key.
```ts twoslash
import { P256 } from 'ox'
const { privateKey, publicKey } = P256.createKeyPair()
const signature = P256.sign({ payload: '0xdeadbeef', privateKey })
const verified = P256.verify({ payload: '0xdeadbeef', publicKey, signature }) // [!code hl]
// @log: true
```
If signing used `hash: true`, pass `hash: true` here as well.
### Recover a Public Key
[`P256.recoverPublicKey`](/api/P256/recoverPublicKey) recovers the signing public key from the
payload and a signature that carries `yParity`.
```ts twoslash
import { P256 } from 'ox'
const { privateKey } = P256.createKeyPair()
const signature = P256.sign({ payload: '0xdeadbeef', privateKey })
const publicKey = P256.recoverPublicKey({
payload: '0xdeadbeef',
signature, // [!code hl]
})
// @log: { prefix: 4, x: '0x…', y: '0x…' }
```
Signatures from `WebCryptoP256` or WebAuthn have no `yParity`, so they cannot be recovered —
verify those against a stored public key instead.
### Derive a Shared Secret (ECDH)
[`P256.getSharedSecret`](/api/P256/getSharedSecret) computes an Elliptic Curve Diffie-Hellman
secret between one party's private key and the other's public key.
```ts twoslash
import { P256 } from 'ox'
const alice = P256.createKeyPair()
const bob = P256.createKeyPair()
const sharedSecret = P256.getSharedSecret({
privateKey: alice.privateKey, // [!code hl]
publicKey: bob.publicKey, // [!code hl]
})
```
Both sides derive the same secret. Run it through a KDF (for example
[`Hash.hmac256`](/api/Hash/hmac256)) before using it as a symmetric key.
## Best Practices
### Match Hashing on Both Sides
`sign` and `verify` must agree on `hash`. Signing a pre-hashed digest but verifying with
`hash: true` (or vice versa) fails silently with `false`.
### Prefer Hardware-Backed Keys in Browsers
Raw hex private keys live in JavaScript memory. In browser contexts, prefer
[`WebCryptoP256`](/guides/crypto/webcrypto-p256) (non-extractable `CryptoKey`s) or
[passkeys](/guides/webauthn/signing).
## See More
# Work with Secp256k1
## Overview
[`Secp256k1`](/api/Secp256k1) implements ECDSA on the curve behind Ethereum accounts and
transactions. Signing returns a structured [`Signature`](/api/Signature) object (`r`, `s`,
`yParity`), and public keys are structured [`PublicKey`](/api/PublicKey) objects, so results
plug directly into transaction envelopes and message signing.
## Recipes
### Create a Key Pair
[`Secp256k1.createKeyPair`](/api/Secp256k1/createKeyPair) generates a random private key with
its corresponding public key. Derive the Ethereum address with
[`Address.fromPublicKey`](/api/Address/fromPublicKey).
```ts twoslash
import { Address, Secp256k1 } from 'ox'
const { privateKey, publicKey } = Secp256k1.createKeyPair()
const address = Address.fromPublicKey(publicKey) // [!code hl]
// @log: '0x71bE63f3384f5fb98995898A86B02Fb2426c5788'
```
[`Secp256k1.randomPrivateKey`](/api/Secp256k1/randomPrivateKey) and
[`Secp256k1.getPublicKey`](/api/Secp256k1/getPublicKey) perform the two steps separately.
### Sign a Payload
Hash the message first — [`Secp256k1.sign`](/api/Secp256k1/sign) signs the 32-byte payload it
is given.
```ts twoslash
import { Hash, Hex, Secp256k1 } from 'ox'
declare const privateKey: Hex.Hex
const payload = Hash.keccak256(Hex.fromString('agree to terms'))
const signature = Secp256k1.sign({ payload, privateKey }) // [!code hl]
// @log: { r: '0x1c34…', s: '0x4f8d…', yParity: 0 }
```
Serialize the result with [`Signature.toHex`](/api/Signature/toHex) — see
[Convert Signature Formats](/guides/crypto/signatures).
### Verify a Signature
[`Secp256k1.verify`](/api/Secp256k1/verify) accepts either the signer's address or their
public key.
```ts twoslash
import { Address, Secp256k1 } from 'ox'
const { privateKey, publicKey } = Secp256k1.createKeyPair()
const address = Address.fromPublicKey(publicKey)
const payload = '0xdeadbeef'
const signature = Secp256k1.sign({ payload, privateKey })
const verified = Secp256k1.verify({ address, payload, signature }) // [!code hl]
// @log: true
```
Pass `publicKey` instead of `address` to verify against the key directly — required when the
signature has no `yParity` to recover from.
### Recover the Signer
[`Secp256k1.recoverAddress`](/api/Secp256k1/recoverAddress) and
[`Secp256k1.recoverPublicKey`](/api/Secp256k1/recoverPublicKey) recover the signer from the
payload and a signature that carries its recovery bit (`yParity`).
```ts twoslash
import { Hex, Secp256k1 } from 'ox'
declare const privateKey: Hex.Hex
const payload = '0xdeadbeef'
const signature = Secp256k1.sign({ payload, privateKey })
const address = Secp256k1.recoverAddress({ payload, signature }) // [!code hl]
// @log: '0x71bE63f3384f5fb98995898A86B02Fb2426c5788'
const publicKey = Secp256k1.recoverPublicKey({ payload, signature })
// @log: { prefix: 4, x: '0xd6c2…', y: '0x9a47…' }
```
## Best Practices
### Hash Before Signing
Sign keccak256 digests, never raw application data. For user-facing messages, prefer the
EIP-191 flow in [Sign Personal Messages](/guides/messages/personal-messages), which prefixes
and hashes for you.
### Preserve the Recovery Bit
`yParity` is what makes address recovery possible. Serialize signatures with
[`Signature.toHex`](/api/Signature/toHex) (65 bytes) rather than dropping to `r ++ s` when the
verifier needs to identify the signer.
## See More
# Work with WebCryptoP256
## Overview
[`WebCryptoP256`](/api/WebCryptoP256) wraps the
[Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) for P256:
private keys are non-extractable
[`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)s that the runtime
never exposes to JavaScript, while public keys and signatures use Ox's structured
[`PublicKey`](/api/PublicKey) and [`Signature`](/api/Signature) shapes. All functions are
async.
## Recipes
### Create a Non-Extractable Key Pair
[`WebCryptoP256.createKeyPair`](/api/WebCryptoP256/createKeyPair) generates an ECDSA signing
key. The private key cannot be exported or serialized by default.
```ts twoslash
import { WebCryptoP256 } from 'ox'
const { privateKey, publicKey } = await WebCryptoP256.createKeyPair() // [!code hl]
// @log: {
// @log: privateKey: CryptoKey {},
// @log: publicKey: { prefix: 4, x: '0x…', y: '0x…' },
// @log: }
```
Persist the `CryptoKey` in IndexedDB if the key must survive a page reload — only pass
`extractable: true` if you genuinely need to export it.
### Sign and Verify in the Browser
[`WebCryptoP256.sign`](/api/WebCryptoP256/sign) SHA-256-hashes the payload and signs it with
the `CryptoKey`; [`WebCryptoP256.verify`](/api/WebCryptoP256/verify) checks the result against
the structured public key.
```ts twoslash
import { WebCryptoP256 } from 'ox'
const { privateKey, publicKey } = await WebCryptoP256.createKeyPair()
const signature = await WebCryptoP256.sign({
payload: '0xdeadbeef',
privateKey, // [!code hl]
})
const verified = await WebCryptoP256.verify({
payload: '0xdeadbeef',
publicKey,
signature,
})
// @log: true
```
Web Crypto signatures carry no `yParity`, so the signer cannot be recovered — store the public
key alongside whatever the signature protects. Ox normalizes signatures to low-S so they
round-trip with [`P256.verify`](/api/P256/verify) and onchain verifiers.
### Derive a Shared Secret (ECDH)
Key agreement needs a dedicated key pair from
[`WebCryptoP256.createKeyPairECDH`](/api/WebCryptoP256/createKeyPairECDH); then
[`WebCryptoP256.getSharedSecret`](/api/WebCryptoP256/getSharedSecret) computes the
Diffie-Hellman secret.
```ts twoslash
import { WebCryptoP256 } from 'ox'
const alice = await WebCryptoP256.createKeyPairECDH()
const bob = await WebCryptoP256.createKeyPairECDH()
const sharedSecret = await WebCryptoP256.getSharedSecret({
privateKey: alice.privateKey, // [!code hl]
publicKey: bob.publicKey, // [!code hl]
})
```
Passing an ECDSA `CryptoKey` throws — Web Crypto binds each key to a single algorithm, so
signing and agreement always use separate pairs.
## Best Practices
### Keep Keys Non-Extractable
The default `extractable: false` is the point of this module: even an XSS payload cannot read
the private key, only ask the runtime to sign with it.
### Verify With a Stored Public Key
Without a recovery bit there is no "recover the signer" flow. Treat the public key as part of
the credential record and verify against it explicitly.
## See More
# Data & Encoding
## Overview
Everything on Ethereum bottoms out in byte data. Ox represents it with two primitive types —
[`Hex`](/api/Hex) and [`Bytes`](/api/Bytes) — and ships the codecs that move values between them
and the wire: RLP for protocol serialization, Base64/Base58/Bech32m/CBOR for ecosystem interchange,
plus bigint-safe JSON and lossless ether/gwei unit conversion.
```ts twoslash
import { Hex, Value } from 'ox'
const amount = Value.fromEther('1.5')
// @log: 1500000000000000000n
const quantity = Hex.fromNumber(amount)
// @log: '0x14d1120d7b160000'
```
# Base32 Coding
## Overview
[`Base32`](/api/Base32) implements the raw BIP-173 character set — the alphabet Bech32 addresses
build on — without a checksum or human-readable prefix. Reach for it when a protocol hands you
bare base32 data; for checksummed addresses use [`Bech32m`](/api/Bech32m) instead.
## Recipes
### Encode & Decode Data
Round-trip hex payloads with [`Base32.fromHex`](/api/Base32/fromHex) and
[`Base32.toHex`](/api/Base32/toHex); [`Base32.fromBytes`](/api/Base32/fromBytes) and
[`Base32.toBytes`](/api/Base32/toBytes) cover `Uint8Array` payloads.
```ts twoslash
import { Base32 } from 'ox'
const encoded = Base32.fromHex('0xdeadbeef')
// @log: 'm6kmamc'
const decoded = Base32.toHex(encoded)
// @log: '0xdeadbeef'
```
## Best Practices
### Prefer Bech32m for Addresses
Base32 carries no integrity protection. When encoding anything a user might copy by hand — an
address, an invoice — use [`Bech32m`](/guides/data/bech32m), which adds a prefix and a
checksum that catches transcription errors.
## See More
# Base58 Coding
## Overview
[`Base58`](/api/Base58) is the alphabet behind Bitcoin addresses, IPFS CIDv0 hashes, and Solana
public keys — Base64 without the visually ambiguous characters (`0`, `O`, `I`, `l`). Ox converts
Base58 values to and from [`Hex`](/api/Hex), [`Bytes`](/api/Bytes), and plain strings.
## Recipes
### Encode & Decode Data
Round-trip a value with [`Base58.fromString`](/api/Base58/fromString) and
[`Base58.toString`](/api/Base58/toString).
```ts twoslash
import { Base58 } from 'ox'
const encoded = Base58.fromString('Hello World!')
// @log: '2NEpo7TZRRrLZSi2U'
const decoded = Base58.toString(encoded)
// @log: 'Hello World!'
```
### Bring Base58 Identifiers into Primitive Types
Use [`Base58.toHex`](/api/Base58/toHex) or [`Base58.toBytes`](/api/Base58/toBytes) to convert
external identifiers — a Solana public key, an IPFS CIDv0 hash — into the types the rest of Ox
operates on.
```ts twoslash
import { Base58 } from 'ox'
const hex = Base58.toHex('2NEpo7TZRRrLZSi2U') // [!code hl]
// @log: '0x48656c6c6f20576f726c6421'
```
Decoding preserves leading zero bytes (encoded as `1` characters), matching Bitcoin's address
conventions.
## Best Practices
### Expect Typed Errors from Untrusted Input
The decoder validates every character against the Base58 alphabet and throws
`Base58.InvalidCharacterError` on corruption. Wrap decoding of user-supplied identifiers and
surface the failure instead of propagating malformed bytes.
## See More
# Base64 Coding
## Overview
[`Base64`](/api/Base64) converts between Base64 strings and Ox's primitive types — the encoding
behind data URLs, HTTP payloads, and WebAuthn's transport format. Encoders exist for
[`Hex`](/api/Base64/fromHex), [`Bytes`](/api/Base64/fromBytes), and plain
[strings](/api/Base64/fromString), each with a matching decoder.
## Recipes
### Encode & Decode Data
Round-trip a value with [`Base64.fromString`](/api/Base64/fromString) and
[`Base64.toString`](/api/Base64/toString).
```ts twoslash
import { Base64 } from 'ox'
const encoded = Base64.fromString('hello world')
// @log: 'aGVsbG8gd29ybGQ='
const decoded = Base64.toString(encoded)
// @log: 'hello world'
```
[`Base64.fromBytes`](/api/Base64/fromBytes) and [`Base64.toBytes`](/api/Base64/toBytes) do the
same for `Uint8Array` payloads.
### Embed Calldata in URLs
Use [`Base64.fromHex`](/api/Base64/fromHex) with URL-safe characters to embed calldata or other
hex payloads in query strings, data URLs, and JSON APIs, then recover the hex with
[`Base64.toHex`](/api/Base64/toHex).
```ts twoslash
import { Base64 } from 'ox'
const encoded = Base64.fromHex('0xa9059cbb', { url: true, pad: false }) // [!code hl]
// @log: 'qQWcuw'
const calldata = Base64.toHex(encoded)
// @log: '0xa9059cbb'
```
## Best Practices
### Use URL-Safe Base64 on the Wire
The standard Base64 alphabet contains `+` and `/`, which break query strings and path segments.
Pass `{ url: true }` whenever the encoded value travels inside a URL.
## See More
# Bech32m Coding
## Overview
[`Bech32m`](/api/Bech32m) (BIP-350) combines a human-readable prefix with a checksummed data
part — the format behind Bitcoin Taproot addresses and other modern address schemes. The
checksum catches transcription errors before they become lost funds.
## Recipes
### Encode Data with a Prefix
[`Bech32m.encode`](/api/Bech32m/encode) takes a human-readable part (HRP) and the data bytes to
protect.
```ts twoslash
import { Bech32m } from 'ox'
const address = Bech32m.encode('tempo', new Uint8Array(20)) // [!code hl]
// @log: 'tempo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqwa7xtm'
```
### Decode & Verify a Checksum
[`Bech32m.decode`](/api/Bech32m/decode) verifies the checksum and returns the prefix and data,
throwing a typed error on corruption.
```ts twoslash
import { Bech32m } from 'ox'
declare const address: string
const { hrp, data } = Bech32m.decode(address) // [!code hl]
// @log: { hrp: 'tempo', data: Uint8Array(20) }
```
For raw BIP-173 base32 data without a checksum, use [`Base32`](/guides/data/base32).
## Best Practices
### Treat the Prefix as Part of the Address
The HRP is covered by the checksum: `tempo1…` and `other1…` encoding the same bytes are
different addresses. Validate that a decoded `hrp` matches the network you expect before using
the data part.
## See More
# CBOR Coding
## Overview
[`Cbor`](/api/Cbor) round-trips JavaScript values through the Concise Binary Object
Representation (RFC 8949) — the serialization behind WebAuthn attestation objects, COSE keys,
and IPFS/IPLD blocks.
## Recipes
### Encode & Decode Values
[`Cbor.encode`](/api/Cbor/encode) serializes objects, arrays, and primitives;
[`Cbor.decode`](/api/Cbor/decode) recovers them.
```ts twoslash
import { Cbor } from 'ox'
const encoded = Cbor.encode({ foo: 'bar', baz: [1, 2, 3] })
// @log: '0xa263666f6f636261726362617a83010203'
const decoded = Cbor.decode(encoded)
// @log: { foo: 'bar', baz: [1, 2, 3] }
```
### Choose the Output Type
Pass `{ as: 'Bytes' }` to encode straight to a `Uint8Array` when the payload feeds an API that
expects raw bytes rather than hex.
```ts twoslash
import { Cbor } from 'ox'
const bytes = Cbor.encode({ alg: -7 }, { as: 'Bytes' }) // [!code hl]
// @log: Uint8Array [161, 99, 97, 108, 103, 38]
```
## Best Practices
### Decode Before You Trust
CBOR from an authenticator or a network peer is untrusted input. Decode it, then validate the
shape of the result — decoding succeeding says nothing about the payload matching the structure
your code expects.
## See More
# CompactSize Coding
## Overview
[`CompactSize`](/api/CompactSize) implements Bitcoin's variable-length integer encoding, used to
length-prefix scripts and payloads on the wire. Values up to `0xfc` take one byte; larger values
get a marker byte plus a little-endian integer.
## Recipes
### Encode a Length Prefix
[`CompactSize.toHex`](/api/CompactSize/toHex) (or
[`CompactSize.toBytes`](/api/CompactSize/toBytes)) encodes an integer with the smallest valid
representation.
```ts twoslash
import { CompactSize } from 'ox'
const encoded = CompactSize.toHex(520) // [!code hl]
// @log: '0xfd0802'
```
### Decode a Varint & Advance a Cursor
[`CompactSize.fromHex`](/api/CompactSize/fromHex) returns both the decoded value and the number
of bytes consumed, so a parser knows how far to advance its cursor.
```ts twoslash
import { CompactSize } from 'ox'
const { value, size } = CompactSize.fromHex('0xfd0802') // [!code hl]
// @log: { value: 520n, size: 3 }
```
Decoding enforces minimal encodings and throws `CompactSize.NonMinimalEncodingError` on padded
values, matching Bitcoin consensus rules.
## Best Practices
### Track the Consumed Size
A CompactSize prefix is one, three, five, or nine bytes long. Always advance parsing offsets by
the returned `size` rather than assuming a fixed width.
## See More
# Format Ether & Gwei Values
## Overview
User interfaces speak decimal strings; Ethereum speaks integral wei. [`Value`](/api/Value)
converts between the two with pure bigint arithmetic — no floating point, no precision loss.
## Recipes
### Parse User Input to Wei
Use [`Value.fromEther`](/api/Value/fromEther) to turn a decimal string from a form input into a
wei amount ready for a transaction's `value` field, and [`Value.fromGwei`](/api/Value/fromGwei)
for user-supplied gas prices.
```ts twoslash
import { Value } from 'ox'
const value = Value.fromEther('0.05') // [!code hl]
// @log: 50000000000000000n
const maxFeePerGas = Value.fromGwei('20')
// @log: 20000000000n
```
Malformed input such as `'1.2.3'` throws `Value.InvalidDecimalNumberError` — surface it as form
validation feedback instead of letting garbage reach a transaction.
### Format Wei for Display
[`Value.formatEther`](/api/Value/formatEther) and [`Value.formatGwei`](/api/Value/formatGwei)
render wei balances and gas prices as human-readable decimal strings.
```ts twoslash
import { Value } from 'ox'
const balance = Value.formatEther(1_500_000_000_000_000_000n)
// @log: '1.5'
const gasPrice = Value.formatGwei(20_000_000_000n)
// @log: '20'
```
Trailing zeros are trimmed, so `1_000_000_000_000_000_000n` formats as `'1'`, not `'1.000000'`.
### Handle Token Decimals
ERC-20 tokens define their own precision — pass the token's `decimals` to
[`Value.from`](/api/Value/from) and [`Value.format`](/api/Value/format) to parse and render token
amounts (e.g. `6` for USDC).
```ts twoslash
import { Value } from 'ox'
const decimals = 6 // from the token contract's `decimals()` function
const amount = Value.from('100.5', decimals) // [!code hl]
// @log: 100500000n
const display = Value.format(100_500_000n, decimals)
// @log: '100.5'
```
Input with more fractional digits than `decimals` is rounded half-away-from-zero rather than
silently truncated.
## Best Practices
### Keep Amounts as BigInt
Convert only at the edges: parse once when input arrives, format once when a value is displayed.
All arithmetic, comparison, and storage in between should stay in wei (`bigint`).
### Never Round-Trip Through Number
`Number` loses integer precision above 2^53 — roughly 0.009 ether in wei. Avoid `parseFloat`,
`Number(value)`, and arithmetic operators on stringified amounts; `Value` exists so you never
need them.
## See More
# Serialize JSON Safely
## Overview
`JSON.stringify` throws on `bigint`, and integers above `Number.MAX_SAFE_INTEGER` silently lose
precision in `JSON.parse` — routine hazards once wei amounts move through APIs, caches, and
storage. [`Json`](/api/Json) provides drop-in replacements that round-trip bigints intact, plus
[RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) canonicalization for hashing and signing.
## Recipes
### Parse JSON Containing BigInts
[`Json.parse`](/api/Json/parse) restores bigint values that were serialized with
[`Json.stringify`](/api/Json/stringify), so wei balances survive the round-trip through your API
or database without truncating to a lossy `number`.
```ts twoslash
import { Json } from 'ox'
const data = Json.parse(
'{"balance":"69420694206942069420694206942069420694206942069420#__bigint"}',
)
// @log: { balance: 69420694206942069420694206942069420694206942069420n }
```
Plain JSON without the bigint marker takes a fast path through native `JSON.parse`, so it is safe
to use `Json.parse` for every payload.
### Stringify Without Precision Loss
[`Json.stringify`](/api/Json/stringify) serializes bigint values with a marker suffix instead of
throwing, letting wei-denominated state travel through JSON APIs unchanged.
```ts twoslash
import { Json } from 'ox'
const json = Json.stringify({
to: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
value: 1_000_000_000_000_000_000n, // [!code hl]
})
// @log: '{"to":"0xd8da6bf26964af9d7eed9e03e53415d37aa96045","value":"1000000000000000000#__bigint"}'
```
It accepts the same `replacer` and `space` arguments as native `JSON.stringify`.
### Canonicalize for Hashing & Signing
[`Json.canonicalize`](/api/Json/canonicalize) emits RFC 8785 canonical JSON — keys recursively
sorted, no whitespace — so structurally equal objects always hash to the same digest.
```ts twoslash
import { Hash, Hex, Json } from 'ox'
const canonical = Json.canonicalize({ b: 2, a: 1 }) // [!code hl]
// @log: '{"a":1,"b":2}'
const digest = Hash.keccak256(Hex.fromString(canonical))
```
Canonicalization rejects `bigint` and non-finite numbers by design — convert those to strings
before hashing.
## Best Practices
### Pair Stringify with Parse
The `#__bigint` marker is an Ox convention: only `Json.parse` revives it. When the consumer is a
third party, convert bigints to explicit decimal strings (e.g. with
[`Value.format`](/api/Value/format)) instead of leaking the marker into their schema.
### Canonicalize Before You Hash
Plain `JSON.stringify` output depends on key insertion order, so equal objects can produce
different digests. Any time a JSON document feeds a hash or a signature, build it with
`Json.canonicalize`.
## See More
# Work with Bytes & Hex
## Overview
When working with Ethereum, byte data — addresses, hashes, signatures, serialized payloads — is
commonly represented as either **hexadecimal strings** or **byte arrays**. Ox models the two with
[`Hex`](/api/Hex) ([`Hex.Hex`](/api/Hex/types#hexhex), a `0x`-prefixed `string`) and
[`Bytes`](/api/Bytes) ([`Bytes.Bytes`](/api/Bytes/types#bytesbytes), a `Uint8Array` instance).
Every operation on one module has a mirror on the other, so recipes below show whichever side is
most idiomatic.
## Recipes
### Instantiate from Primitives
Construct values with [`Hex.from`](/api/Hex/from) & [`Bytes.from`](/api/Bytes/from), or lift
booleans, numbers, and strings with the typed constructors:
[`Hex.fromBoolean`](/api/Hex/fromBoolean) / [`Bytes.fromBoolean`](/api/Bytes/fromBoolean),
[`Hex.fromNumber`](/api/Hex/fromNumber) / [`Bytes.fromNumber`](/api/Bytes/fromNumber), and
[`Hex.fromString`](/api/Hex/fromString) / [`Bytes.fromString`](/api/Bytes/fromString).
```ts twoslash
import { Bytes, Hex } from 'ox'
const hex = Hex.from('0xdeadbeef')
// @log: '0xdeadbeef'
const bytes = Bytes.from([0xde, 0xad, 0xbe, 0xef])
// @log: Uint8Array [0xde, 0xad, 0xbe, 0xef]
const bool = Hex.fromBoolean(true)
// @log: '0x1'
const bigint = Hex.fromNumber(420n)
// @log: '0x1a4'
const string = Hex.fromString('hello')
// @log: '0x68656c6c6f'
```
`Hex` can also be instantiated from `Bytes`, and vice versa — `Hex.from(bytes)` and
`Bytes.from(hex)` convert between the two representations.
### Convert Between Types
Recover primitive JavaScript values with [`Hex.toBigInt`](/api/Hex/toBigInt) /
[`Bytes.toBigInt`](/api/Bytes/toBigInt), [`Hex.toBoolean`](/api/Hex/toBoolean) /
[`Bytes.toBoolean`](/api/Bytes/toBoolean), [`Hex.toNumber`](/api/Hex/toNumber) /
[`Bytes.toNumber`](/api/Bytes/toNumber), and [`Hex.toString`](/api/Hex/toString) /
[`Bytes.toString`](/api/Bytes/toString).
```ts twoslash
import { Bytes, Hex } from 'ox'
const bool = Bytes.toBoolean(Bytes.from([1]))
// @log: true
const bigint = Hex.toBigInt('0x01a4')
// @log: 420n
const number = Bytes.toNumber(Bytes.from([1, 164]))
// @log: 420
const string = Hex.toString('0x68656c6c6f')
// @log: 'hello'
```
Prefer `toBigInt` over `toNumber` for on-chain quantities — wei amounts routinely exceed
`Number.MAX_SAFE_INTEGER`.
### Concatenate, Pad, Slice & Trim
Byte-manipulation helpers exist on both modules — [`Hex.concat`](/api/Hex/concat) /
[`Bytes.concat`](/api/Bytes/concat), [`Hex.padLeft`](/api/Hex/padLeft) /
[`Hex.padRight`](/api/Hex/padRight), [`Hex.slice`](/api/Hex/slice) /
[`Bytes.slice`](/api/Bytes/slice), [`Hex.trimLeft`](/api/Hex/trimLeft) /
[`Hex.trimRight`](/api/Hex/trimRight), and [`Hex.size`](/api/Hex/size) /
[`Bytes.size`](/api/Bytes/size). Sizes and offsets are measured in bytes, not characters.
```ts twoslash
import { Bytes, Hex } from 'ox'
const concatenated = Hex.concat('0xdead', '0xbeef')
// @log: '0xdeadbeef'
const padded = Hex.padLeft('0xdead', 4)
// @log: '0x0000dead'
const sliced = Hex.slice('0x0123456789', 1, 4)
// @log: '0x234567'
const trimmed = Bytes.trimLeft(Bytes.from([0x00, 0x00, 0xde, 0xad]))
// @log: Uint8Array [0xde, 0xad]
const size = Hex.size('0xdeadbeefdeadbeefdeadbeefdeadbeef')
// @log: 16
```
`padLeft` & `padRight` default to a size of `32` bytes — the width of an EVM word — so
`Hex.padLeft('0xdead')` produces an ABI-ready word.
### Compare & Validate
[`Hex.isEqual`](/api/Hex/isEqual) & [`Bytes.isEqual`](/api/Bytes/isEqual) compare by value;
[`Hex.validate`](/api/Hex/validate) & [`Bytes.validate`](/api/Bytes/validate) return a boolean
for untrusted input, while [`Hex.assert`](/api/Hex/assert) & [`Bytes.assert`](/api/Bytes/assert)
throw a typed error instead.
```ts twoslash
import { Bytes, Hex } from 'ox'
const equal = Bytes.isEqual(
Bytes.from([0xde, 0xad, 0xbe, 0xef]),
Bytes.from([0xca, 0xfe, 0xba, 0xbe]),
)
// @log: false
const valid = Hex.validate('0xdeadbeefz')
// @log: false
Hex.assert('abc')
// @error: Error: Hex.InvalidHexValueError
```
Reach for `assert` at trust boundaries where invalid data should halt processing, and `validate`
where you branch on the result.
### Generate Random Values
[`Hex.random`](/api/Hex/random) & [`Bytes.random`](/api/Bytes/random) produce cryptographically
secure random bytes of a given length — ready for `CREATE2` salts, nonces, and session
identifiers.
```ts twoslash
import { Bytes, Hex } from 'ox'
const salt = Hex.random(32)
// @log: '0x86d8b4…' (32 random bytes)
const nonce = Bytes.random(16)
// @log: Uint8Array(16) [134, 216, …]
```
## Best Practices
### Choose the Representation per Boundary
Most Ox functions accept either type. Use `Hex` at serialization boundaries — JSON-RPC and
signing payloads speak `0x`-prefixed strings — and keep `Bytes` for repeated binary work, where
avoiding hex round-trips in hot paths saves allocations.
### Validate Before You Trust
A `0x` prefix does not make a string valid hex. Run external input through `validate` or
`assert` before slicing, padding, or converting it, so malformed data fails loudly at the edge.
## See More
# Work with RLP
## Overview
Recursive Length Prefix (RLP) is the Ethereum protocol's core serialization method — a
space-efficient standard for packaging and transferring arbitrarily nested byte data.
[`Rlp`](/api/Rlp) encodes and decodes it. RLP underpins
[transaction envelope serialization](/guides/transactions/build-sign-send),
[EIP-7702 authorization](/api/Authorization/getSignPayload) sign payloads, and
[`CREATE` contract address derivation](/api/ContractAddress/fromCreate).
## Recipes
### Encode & Decode a Value
Round-trip a single value with [`Rlp.fromHex`](/api/Rlp/fromHex) and
[`Rlp.toHex`](/api/Rlp/toHex).
```ts twoslash
import { Rlp } from 'ox'
const rlp = Rlp.fromHex('0x68656c6c6f')
// @log: '0x8568656c6c6f'
const value = Rlp.toHex(rlp)
// @log: '0x68656c6c6f'
```
### Encode Nested Data
[`Rlp.fromHex`](/api/Rlp/fromHex) serializes arbitrarily nested arrays of
[`Hex`](/api/Hex) values into a single RLP payload.
```ts twoslash
import { Hex, Rlp } from 'ox'
const rlp = Rlp.fromHex([
Hex.fromString('hello'),
Hex.fromNumber(1337),
[Hex.fromString('foo'), Hex.fromString('bar')], // [!code hl]
])
// @log: '0xd28568656c6c6f820539c883666f6f83626172'
```
Working with `Uint8Array` data instead? [`Rlp.fromBytes`](/api/Rlp/fromBytes) accepts nested
[`Bytes`](/api/Bytes) and returns `Bytes`.
### Decode to Hex or Bytes
[`Rlp.toHex`](/api/Rlp/toHex) deserializes an RLP payload back into its original nested
structure with `Hex` leaves; [`Rlp.toBytes`](/api/Rlp/toBytes) does the same with `Bytes`
leaves.
```ts twoslash
import { Rlp } from 'ox'
const values = Rlp.toHex('0xd28568656c6c6f820539c883666f6f83626172')
// @log: ['0x68656c6c6f', '0x0539', ['0x666f6f', '0x626172']]
```
Either function accepts `Hex` or `Bytes` input, so raw payloads from the wire decode without a
manual conversion step.
## Best Practices
### Bring Your Own Schema
RLP encodes structure, not types. Decoding returns nested `Hex` (or `Bytes`) leaves — it is up
to you to reinterpret each position (`Hex.toString`, `Hex.toNumber`, …) according to the schema
the data was encoded with, in the same order.
## See More
# JSON-RPC & Providers
## Overview
For an application to communicate with the Ethereum network, it needs to connect to an Ethereum
Node and exchange messages in a standardized format. All Ethereum Nodes implement the
[JSON-RPC specification](https://www.jsonrpc.org/specification), and most Wallets expose an
[EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) Provider interface on top of it. Ox provides
type-safe primitives for both sides of the wire: [`RpcRequest`](/api/RpcRequest),
[`RpcResponse`](/api/RpcResponse), [`RpcTransport`](/api/RpcTransport),
[`RpcSchema`](/api/RpcSchema), and [`Provider`](/api/Provider).
```ts twoslash
import { RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com') // [!code hl]
const blockNumber = await transport.request({ method: 'eth_blockNumber' })
// @log: '0x1a2b3c'
```
# Send JSON-RPC Requests
## Overview
[`RpcRequest`](/api/RpcRequest) builds [JSON-RPC 2.0](https://www.jsonrpc.org/specification)
request objects, [`RpcResponse`](/api/RpcResponse) parses what the node returns, and
[`RpcTransport`](/api/RpcTransport) bundles both behind an HTTP `request` function. All three are
stateless and transport-agnostic — pair them with `fetch`, WebSockets, or any messaging layer.
## Recipes
### Build a Request Store
[`RpcRequest.createStore`](/api/RpcRequest/createStore) returns a `prepare` function that builds
strongly-typed JSON-RPC request objects with an auto-incrementing `id`.
```ts twoslash
import { RpcRequest } from 'ox'
const store = RpcRequest.createStore()
const request_1 = store.prepare({
method: 'eth_blockNumber',
})
// @log: { id: 0, jsonrpc: '2.0', method: 'eth_blockNumber' }
const request_2 = store.prepare({
method: 'eth_getBlockByNumber',
params: ['latest', false],
})
// @log: { id: 1, jsonrpc: '2.0', method: 'eth_getBlockByNumber', params: ['latest', false] }
```
Use [`RpcRequest.from`](/api/RpcRequest/from) instead to build a single request and manage the
`id` yourself.
### Send over HTTP Fetch
A prepared request is a plain JSON-serializable object — POST it to any RPC endpoint.
```ts twoslash
import { RpcRequest } from 'ox'
const store = RpcRequest.createStore()
const request = store.prepare({
method: 'eth_getBlockByNumber',
params: ['latest', false],
})
const response = await fetch('https://1.rpc.thirdweb.com', {
body: JSON.stringify(request),
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res.json())
```
### Send with an RPC Transport
[`RpcTransport.fromHttp`](/api/RpcTransport/fromHttp) wraps the prepare → fetch → parse loop into
a single `request` function that manages `id`s and raises JSON-RPC errors for you.
```ts twoslash
import { RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const blockNumber = await transport.request({ method: 'eth_blockNumber' })
// @log: '0x1a2b3c'
```
The transport is also EIP-1193 compatible — see
[Use EIP-1193 Providers](/guides/rpc/providers).
### Parse Responses
[`RpcResponse.parse`](/api/RpcResponse/parse) extracts the JSON-RPC `result`, throws a typed error
when the response contains an `error`, and — given the originating `request` — strongly types the
result.
```ts twoslash
import { RpcRequest, RpcResponse } from 'ox'
const store = RpcRequest.createStore()
const request = store.prepare({
method: 'eth_getBlockByNumber',
params: ['latest', false],
})
const block = await fetch('https://1.rpc.thirdweb.com', {
body: JSON.stringify(request),
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => res.json())
.then((res) => RpcResponse.parse(res, { request }))
```
Set `raw: true` to receive the whole `{ result, error }` response object instead of throwing on
errors.
## Best Practices
### Reuse One Store per Connection
A store increments its `id` on every `prepare` call. Create one store per connection or session so
ids stay unique and responses can be correlated with their requests.
### Let a Transport Own the Plumbing
Reach for `RpcTransport.fromHttp` unless you control the wire format yourself. For a full-featured
client with retries, batching, and wallet actions, use [Viem](https://viem.sh).
## See More
# Serve & Handle RPC Requests
## Overview
On the serving side of JSON-RPC — an API route, a service worker, or an
[EIP-1193 Provider `request` handler](/api/Provider/from) in a Wallet —
[`RpcResponse.from`](/api/RpcResponse/from) builds spec-compliant response objects for incoming
[`RpcRequest`](/api/RpcRequest)s.
## Recipes
### Handle Requests in a Server or Worker
Match on `request.method`, answer what you can locally, and proxy the rest to an upstream node.
Passing `{ request }` fills the response's `id` and `jsonrpc` properties from the request.
```ts twoslash
import { RpcRequest, RpcResponse, RpcSchema } from 'ox'
const accounts = [
'0xd2135CfB216b74109775236E36d4b433F1DF507B',
'0x0D44f617435088c947F00B31160f64b074e412B4',
] as const
async function handleRequest(request: RpcRequest.RpcRequest) {
if (request.method === 'eth_accounts') {
return RpcResponse.from({ result: accounts }, { request }) // [!code hl]
}
if (request.method === 'eth_chainId') {
return RpcResponse.from({ result: '0x1' }, { request }) // [!code hl]
}
// Fall back to an upstream node for everything else.
return await fetch('https://1.rpc.thirdweb.com', {
body: JSON.stringify(request),
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => res.json())
.then((res) => RpcResponse.from(res))
}
```
The `RpcSchema.Eth` annotation narrows `request.method` and types each `result` against the
method's return type.
### Return Typed Errors
[`RpcResponse`](/api/RpcResponse) exports an error class for every JSON-RPC error code (see
[RpcResponse errors](/api/RpcResponse/errors)). Throw them inside your handler and convert
anything caught with [`RpcResponse.parseError`](/api/RpcResponse/parseError) before responding.
```ts twoslash
import { RpcRequest, RpcResponse, RpcSchema } from 'ox'
function handleRequest(request: RpcRequest.RpcRequest) {
try {
if (request.method !== 'eth_chainId')
throw new RpcResponse.MethodNotSupportedError() // [!code hl]
return RpcResponse.from({ result: '0x1' }, { request })
} catch (error) {
const { code, message } = RpcResponse.parseError(error) // [!code hl]
return RpcResponse.from({ error: { code, message } }, { request }) // [!code hl]
}
}
```
`RpcResponse.parseError` maps unknown exceptions to
[`RpcResponse.InternalError`](/api/RpcResponse/errors) (code `-32603`), so callers always receive
a structured JSON-RPC error object.
## Best Practices
### Always Echo the Request `id`
JSON-RPC clients correlate responses by `id`. Pass `{ request }` to `RpcResponse.from` instead of
filling `id` and `jsonrpc` by hand.
### Respond with JSON-RPC Errors, Not Exceptions
A thrown exception terminates the transport; a JSON-RPC error keeps the session alive and tells
the client what went wrong. Map failures to the typed error classes and their well-known codes.
## See More
# Type-Safe RPC Schemas
## Overview
[`RpcSchema`](/api/RpcSchema) statically types JSON-RPC method names, parameters, and return
values. The default schema covers the `eth_` and `wallet_` namespaces; a schema built with
[`RpcSchema.from`](/api/RpcSchema/from) plugs the same type information into
[`RpcTransport`](/api/RpcTransport), [`Provider`](/api/Provider), and
[`RpcRequest.createStore`](/api/RpcRequest/createStore).
## Recipes
### Type a Transport with a Schema
`RpcSchema.from` is a runtime no-op — it exists purely to tag a transport with the union of
methods it supports.
```ts twoslash
import { RpcSchema, RpcTransport } from 'ox'
const schema = RpcSchema.from<
| RpcSchema.Default
| {
Request: {
method: 'ox_getMagic'
params: [id: number]
}
ReturnType: `0x${string}`
}
>()
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com', {
schema, // [!code hl]
})
const magic = await transport.request({
method: 'ox_getMagic', // [!code hl]
params: [1],
})
```
Include `RpcSchema.Default` in the union to keep the standard `eth_` and `wallet_` methods
available alongside your custom ones.
### Extend with Custom Methods
The same schema types an [EIP-1193 Provider](/api/Provider)'s `request` function — useful when a
Wallet exposes methods beyond the standard namespaces.
```ts twoslash
import 'ox/window'
import { Provider, RpcSchema } from 'ox'
const schema = RpcSchema.from<
| RpcSchema.Default
| {
Request: {
method: 'wallet_getSecret' // [!code hl]
params: [id: string] // [!code hl]
}
ReturnType: `0x${string}` // [!code hl]
}
>()
const provider = Provider.from(window.ethereum, { schema })
const secret = await provider.request({
method: 'wallet_getSecret',
params: ['1'],
})
```
`RpcRequest.createStore({ schema })` accepts the same option, so a Wallet can share one schema
between the requests it sends and the requests it handles.
## Best Practices
### Define the Schema Once
Declare the schema in a shared module and import it wherever a store, transport, or provider is
created. Diverging copies defeat the purpose of end-to-end typing.
### Types Are Not Validation
A schema types the compile-time surface only — nothing is checked at runtime. Validate untrusted
requests and responses with runtime schemas — see [Validate with Zod](/guides/schemas/zod).
## See More
# Use EIP-1193 Providers
## Overview
[EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) defines a JavaScript Ethereum Provider API for
interacting with the Ethereum network from an arbitrary JavaScript environment (e.g. Web
Application, Server, etc). You would typically use one when communicating with a Wallet — most
Browser Extension Wallets inject a `window.ethereum` object that conforms to the EIP-1193 API.
Ox's [`Provider`](/api/Provider) module instantiates typed providers, and the `ox/window`
entrypoint augments `window.ethereum` with the provider types.
## Recipes
### Wrap an Injected Provider
External EIP-1193 Providers can be instantiated with [`Provider.from`](/api/Provider/from).
Importing `ox/window` types `window.ethereum`.
```ts twoslash
import 'ox/window'
import { Provider } from 'ox'
const provider = Provider.from(window.ethereum)
const blockNumber = await provider.request({ method: 'eth_blockNumber' })
```
You can also plug in a Provider distributed by a library:
| Library | Description |
| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| [`mipd`](https://github.com/wevm/mipd) | Multi-injected browser wallet provider discovery |
| [`@walletconnect/ethereum-provider`](https://www.npmjs.com/package/@walletconnect/ethereum-provider) | Connect and interact with WalletConnect-enabled wallets |
| [`@metamask/sdk`](https://docs.metamask.io/wallet/connect/metamask-sdk/javascript/) | Connect and interact with MetaMask Wallet |
| [`@coinbase/wallet-sdk`](https://github.com/coinbase/coinbase-wallet-sdk) | Connect and interact with Coinbase Wallet |
| [`@safe-global/safe-apps-provider`](https://github.com/safe-global/safe-apps-sdk/tree/main/packages/safe-apps-provider) | Connect and interact with Safe Wallets |
### Create a Provider from a Transport
Ox's [`RpcTransport`](/api/RpcTransport) is also EIP-1193 compliant, and can be used to
instantiate an EIP-1193 Provider. This means you can use any HTTP RPC endpoint as an EIP-1193
Provider.
```ts twoslash
import { Provider, RpcTransport } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const provider = Provider.from(transport)
const blockNumber = await provider.request({ method: 'eth_blockNumber' })
```
### Emit Provider Events
Event emitters for EIP-1193 Providers can be created using
[`Provider.createEmitter`](/api/Provider/createEmitter) — useful for Wallets that distribute a
Provider (e.g. webpage injection via `window.ethereum`).
```ts twoslash
import { Provider, RpcRequest, RpcResponse } from 'ox'
// 1. Instantiate a Provider Emitter.
const emitter = Provider.createEmitter() // [!code hl]
const store = RpcRequest.createStore()
const provider = Provider.from({
// 2. Pass the Emitter to the Provider.
...emitter, // [!code hl]
async request(args) {
return await fetch('https://1.rpc.thirdweb.com', {
body: JSON.stringify(store.prepare(args)),
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => res.json())
.then(RpcResponse.parse)
},
})
// 3. Emit Provider Events.
emitter.emit('accountsChanged', ['0x...']) // [!code hl]
```
Consumers subscribe with `provider.on('accountsChanged', ...)` and the other
[EIP-1193 events](https://eips.ethereum.org/EIPS/eip-1193#events).
### Handle Provider Errors
Wallets reject requests with well-known EIP-1193 error codes.
[`Provider.parseError`](/api/Provider/parseError) converts an unknown thrown value into a typed
[Provider error](/api/Provider/errors), such as `Provider.UserRejectedRequestError`.
```ts twoslash
// @noErrors
import { Provider } from 'ox'
const provider = Provider.from(window.ethereum)
try {
const accounts = await provider.request({
method: 'eth_requestAccounts',
})
// @log: ['0x71bE63f3384f5fb98995898A86B02Fb2426c5788']
} catch (e) {
const error = Provider.parseError(e)
if (error instanceof Provider.UserRejectedRequestError) {
// @log: code: 4001 — user rejected the request
}
}
```
## Best Practices
### Feature-Detect the Injected Provider
`window.ethereum` is `undefined` outside wallet-enabled browsers. Check for it (or discover
providers with [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) via `mipd`) before wrapping.
### Parse Errors at the Boundary
Wrap `provider.request` calls in `try`/`catch` and normalize failures with `Provider.parseError`
so application code can branch on typed error classes instead of numeric codes.
## See More
# Messages & Authentication
## Overview
Ethereum accounts prove ownership and intent off-chain by signing structured messages.
Ox provides primitives for every common signing envelope: [ERC-191](https://eips.ethereum.org/EIPS/eip-191)
personal messages, [EIP-712](https://eips.ethereum.org/EIPS/eip-712) typed data,
[Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) authentication, and the
[ERC-6492](https://eips.ethereum.org/EIPS/eip-6492)/[ERC-8010](https://eips.ethereum.org/EIPS/eip-8010)
wrappers used by smart accounts.
```ts twoslash
import { Hex, PersonalMessage, Secp256k1 } from 'ox'
// Compute the EIP-191 payload for a message.
const payload = PersonalMessage.getSignPayload(Hex.fromString('hello world'))
// Sign the payload.
const signature = Secp256k1.sign({ payload, privateKey: '0x...' })
// Recover the signer.
const signer = Secp256k1.recoverAddress({ payload, signature })
```
## Guides
# Sign Personal Messages (EIP-191)
## Overview
The [ERC-191 Signed Data](https://eips.ethereum.org/EIPS/eip-191) standard defines a specification
for handling signed data in Ethereum contracts. Signable data is prefixed with a version byte
(e.g. `0x45` for personal messages). This protects an end-user from signing obscured transaction
data constructed by a malicious actor and consequently losing funds.
[`PersonalMessage`](/api/PersonalMessage) handles the `0x45` (personal message) version and
[`ValidatorData`](/api/ValidatorData) the `0x00` (intended validator) version. Ox supports the
following ERC-191 versions:
| Module | Name | Version |
| ----------------------------------------- | ------------------------------------------------------------------------- | ------- |
| [`PersonalMessage`](/api/PersonalMessage) | Personal Message (aka. `personal_sign`) | `0x45` |
| [`TypedData`](/api/TypedData) | Typed Data — see [Sign Typed Data (EIP-712)](/guides/messages/typed-data) | `0x01` |
| [`ValidatorData`](/api/ValidatorData) | Data with intended validator | `0x00` |
## Recipes
### Compute the Sign Payload & Sign
Personal messages are typically used to sign arbitrary messages that will be displayed to the
user, for example, a [Sign-In with Ethereum (SIWE) message](/guides/messages/siwe). Compute the
signable payload with [`PersonalMessage.getSignPayload`](/api/PersonalMessage/getSignPayload),
then sign it — here with [`Secp256k1.sign`](/api/Secp256k1/sign).
```ts twoslash
import { Hex, PersonalMessage, Secp256k1 } from 'ox'
const payload = PersonalMessage.getSignPayload(Hex.fromString('hello world'))
const signature = Secp256k1.sign({
payload,
privateKey: '0x...',
})
```
Any Ox signer works — see [Work with Secp256k1](/guides/crypto/secp256k1) for the full signer
lifecycle.
### Verify & Recover the Signer
Recompute the payload from the exact message that was signed, then recover the signing address
with [`Secp256k1.recoverAddress`](/api/Secp256k1/recoverAddress), or check against a known
address with [`Secp256k1.verify`](/api/Secp256k1/verify).
```ts twoslash
import { Hex, PersonalMessage, Secp256k1, Signature } from 'ox'
declare const signature: Signature.Signature
const payload = PersonalMessage.getSignPayload(Hex.fromString('hello world'))
const signer = Secp256k1.recoverAddress({ payload, signature })
const verified = Secp256k1.verify({
address: signer,
payload,
signature,
})
// @log: true
```
### Sign with a Wallet (personal\_sign)
Most Wallets expose a [`personal_sign` RPC interface](https://docs.metamask.io/wallet/reference/json-rpc-methods/personal_sign/)
that can be used to sign Personal Messages. This means you can use the `personal_sign` RPC method
to sign a message without the ceremony of constructing and signing it yourself.
```ts twoslash
import 'ox/window'
import { Hex, Provider } from 'ox'
const provider = Provider.from(window.ethereum)
const [address] = await provider.request({ method: 'eth_requestAccounts' })
const signature = await provider.request({
method: 'personal_sign',
params: [Hex.fromString('hello world'), address],
})
```
### Sign Intended-Validator Data (ERC-191 0x00)
The `0x00` version binds a signature to an intended validator (e.g. the contract that will
consume it), so it cannot be replayed against another verifier. Compute the payload with
[`ValidatorData.getSignPayload`](/api/ValidatorData/getSignPayload).
```ts twoslash
import { Hex, Secp256k1, ValidatorData } from 'ox'
const payload = ValidatorData.getSignPayload({
data: Hex.fromString('hello world'),
validator: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
})
const signature = Secp256k1.sign({
payload,
privateKey: '0x...',
})
```
If you need the raw `0x19 ‖ 0x00 ‖ validator ‖ data` envelope before hashing, use
[`ValidatorData.encode`](/api/ValidatorData/encode).
## Best Practices
### Hash via the Module, Not by Hand
Always derive payloads with `PersonalMessage.getSignPayload` (or `ValidatorData.getSignPayload`)
so the ERC-191 version byte and length prefix are applied. The prefix is what prevents a signed
message from doubling as a valid transaction or other signable payload.
### Recover Against the Exact Bytes
Verification recomputes the payload from the message bytes. Any difference in encoding or
whitespace between what the user signed and what the server hashes will recover a different
address.
## See More
# Sign Typed Data (EIP-712)
## Overview
Typed Data is signed data that presents structured, human-readable data to the user to sign.
This structure (and encoding format) is defined by the
[EIP-712 standard](https://eips.ethereum.org/EIPS/eip-712). The
[`TypedData`](/api/TypedData) module computes sign payloads, domain separators, and serialized
representations of typed data.
## Recipes
### Define & Hash Typed Data
A signable Typed Data payload can be computed using
[`TypedData.getSignPayload`](/api/TypedData/getSignPayload):
```ts twoslash
import { TypedData } from 'ox'
const payload = TypedData.getSignPayload({
domain: {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0x0000000000000000000000000000000000000000',
},
types: {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' },
],
},
primaryType: 'Mail',
message: {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
contents: 'Hello, Bob!',
},
})
```
The payload is `keccak256(0x19 ‖ 0x01 ‖ domainSeparator ‖ hashStruct(message))` — the ERC-191
`0x01` version envelope.
### Sign & Verify
Sign the payload using a signer — here [`Secp256k1.sign`](/api/Secp256k1/sign) — then recover
the signer with [`Secp256k1.recoverAddress`](/api/Secp256k1/recoverAddress).
```ts twoslash
import { Secp256k1, TypedData } from 'ox'
const payload = TypedData.getSignPayload({
domain: {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0x0000000000000000000000000000000000000000',
},
types: {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' },
],
},
primaryType: 'Mail',
message: {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
contents: 'Hello, Bob!',
},
})
const signature = Secp256k1.sign({
payload,
privateKey: '0x...',
})
const signer = Secp256k1.recoverAddress({ payload, signature })
```
Compare the recovered signer against the expected address with
[`Address.isEqual`](/api/Address/isEqual).
### Sign with a Wallet (eth\_signTypedData\_v4)
Most Wallets expose a [`eth_signTypedData_v4` RPC interface](https://docs.metamask.io/wallet/reference/json-rpc-methods/eth_signtypeddata_v4/)
that can be used to sign Typed Data. This means you can use the `eth_signTypedData_v4` RPC method
to sign a message without the ceremony of constructing and signing it yourself.
```ts twoslash
// @noErrors
import 'ox/window'
import { Hex, Provider, Secp256k1, TypedData } from 'ox'
const provider = Provider.from(window.ethereum)
const [address] = await provider.request({ method: 'eth_requestAccounts' })
const payload = TypedData.serialize({
/* ... */
})
const signature = await provider.request({
method: 'eth_signTypedData_v4',
params: [address, payload],
})
```
[`TypedData.serialize`](/api/TypedData/serialize) produces the JSON string that
`eth_signTypedData_v4` expects as its second parameter.
### Extract the Domain
Derive the EIP-712 domain schema with
[`TypedData.extractEip712DomainTypes`](/api/TypedData/extractEip712DomainTypes), and its
[`domainSeparator`](/api/TypedData/domainSeparator) — useful when interoperating with contracts
that expose `eip712Domain()` (ERC-5267).
```ts twoslash
import { TypedData } from 'ox'
const domain = {
name: 'Ether!',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
} as const
const types = TypedData.extractEip712DomainTypes(domain)
// @log: [
// @log: { 'name': 'name', 'type': 'string' },
// @log: { 'name': 'version', 'type': 'string' },
// @log: { 'name': 'chainId', 'type': 'uint256' },
// @log: { 'name': 'verifyingContract', 'type': 'address' },
// @log: ]
const separator = TypedData.domainSeparator(domain)
// @log: '0x9911ee4f58a7059a8f5385248040e6984d80e2c849500fe6a4d11c4fa98c2af3'
```
## Best Practices
### Bind Signatures to a Domain
Include `chainId` and `verifyingContract` in the domain so a signature for one contract on one
chain cannot be replayed against another.
### Validate Untrusted Definitions
When typed data arrives from an external source, check it with
[`TypedData.validate`](/api/TypedData/validate) (returns `false`) or
[`TypedData.assert`](/api/TypedData/assert) (throws) before hashing or signing.
## See More
# Sign-In with Ethereum (SIWE)
## Overview
**Sign-In with Ethereum (SIWE)** is a standard described by
[EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) for how Ethereum accounts authenticate with
off-chain services by signing a standard message format. The [`Siwe`](/api/Siwe) module
generates nonces, creates and parses messages, and validates their fields. This guide details
how to perform SIWE with Ox in a client-server architecture.
## Recipes
The recipes below form one flow: the server issues a nonce, the client creates and signs the
message, and the server validates the result.
### Generate a Nonce
Using [`Siwe.generateNonce`](/api/Siwe/generateNonce), you can generate a random nonce that can
be used to prevent replay attacks.
```ts twoslash [Server]
import { Siwe } from 'ox'
function handler() {
const nonce = Siwe.generateNonce()
return nonce
}
```
Your server should generate a new nonce for each SIWE process it performs. The nonce should be
stored for later use (e.g. in the session or database) to validate the signature.
### Create the SIWE Message
Before you can create a SIWE message, you need to source the following information:
* `address`: The Ethereum address performing the signing.
* `chainId`: The [EIP-155](https://eips.ethereum.org/EIPS/eip-155) Chain ID to which the session is bound,
* `domain`: [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) authority that is requesting the signing.
* `uri`: [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) URI referring to the resource that is the subject of the signing (as in the subject of a claim).
* `version`: The current version of the SIWE Message.
```ts twoslash [Client]
function onClick() {
const data = {
address: '', // e.g. Wagmi `useAccount()`/`getAccount()`
chainId: 1,
domain: window.location.host,
nonce: '', // e.g. `await getNonceFromServer()`
uri: window.location.origin,
version: '1',
} as const
}
```
Once you have the information, you can create the SIWE message with
[`Siwe.createMessage`](/api/Siwe/createMessage).
```ts twoslash [Client]
import { Siwe } from 'ox'
function onClick() {
const data = {
address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
chainId: 1,
domain: 'example.com',
nonce:
'65ed4681d4efe0270b923ff5f4b097b1c95974dc33aeebecd5724c42fd86dfd25dc70b27ef836b2aa22e68f19ebcccc1',
uri: 'https://example.com/path',
version: '1',
} as const satisfies Siwe.Message
const message = Siwe.createMessage(data)
}
```
In addition, to the required fields, there are some optional fields you can include:
* `expirationTime`: Time when the signed authentication message is no longer valid.
* `issuedAt`: Time when the message was generated, typically the current time.
* `notBefore`: Time when the signed authentication message will become valid.
* `requestId`: A system-specific identifier that may be used to uniquely refer to the sign-in request.
* `resources`: A list of information or references to information the user wishes to have resolved as part of authentication by the relying party.
* `scheme`: [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) URI scheme of the origin of the request.
* `statement`: A human-readable ASCII assertion that the user will sign.
### Sign the Message
Once the message is created, the next step is to sign it. In this guide, we will assume a
browser wallet will sign over JSON-RPC, but you could also sign with
[`Secp256k1.sign`](/api/Secp256k1/sign) if you have access to the private key directly.
```ts twoslash [Client]
import 'ox/window'
//---cut---
import { Hex, Provider, Siwe } from 'ox'
async function onClick() {
const data = {
address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
chainId: 1,
domain: 'example.com',
nonce:
'65ed4681d4efe0270b923ff5f4b097b1c95974dc33aeebecd5724c42fd86dfd25dc70b27ef836b2aa22e68f19ebcccc1',
uri: 'https://example.com/path',
version: '1',
} as const satisfies Siwe.Message
const message = Siwe.createMessage(data)
const provider = Provider.from(window.ethereum)
const signature = await provider.request({
method: 'personal_sign',
params: [Hex.fromString(message), data.address],
})
}
```
:::info
To keep this example simple, we use `window.ethereum` to create our [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) Provider. Since `window.ethereum` is considered deprecated, you should use [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) instead. We recommend either using [Wagmi](https://wagmi.sh) to manage the wallet connection and signing, but you can also use a lower-level library like [`mipd`](https://github.com/wevm/mipd) if all you want is the provider.
:::
### Validate the Signature
Now that we have our message and signature, we can validate them to confirm the address did
indeed sign the message. This validation must be performed in such a way that it cannot be
tampered with. In our case, we will use the server.
```ts twoslash [Server]
// @errors: 2322
import { Address, Hex, PersonalMessage, Secp256k1, Siwe } from 'ox'
function handler() {
const payload = {
// ↑ Sent by client
message: 'example.com wants you to sign in with your Ethereum account: ...',
signature: '0x...',
} as const
// Parse message string into structured object
const parsed = Siwe.parseMessage(payload.message)
if (!parsed.address) return false
// Validate message fields (e.g. `now >= expirationTime`), nonce, etc.
const isValid = Siwe.validateMessage({
message: parsed,
nonce: '',
})
if (!isValid) return false
const personalMessage = PersonalMessage.encode(
Hex.fromString(payload.message),
)
const verified = Address.isEqual(
Address.from(parsed.address),
Secp256k1.recoverAddress({
payload: personalMessage,
signature: payload.signature,
}),
)
return verified
}
```
## Best Practices
### Issue a Fresh Nonce per Attempt
Generate a new nonce for every sign-in attempt and invalidate it once used. Reusing nonces
allows a captured signature to be replayed.
### Validate on the Server
Both [`Siwe.validateMessage`](/api/Siwe/validateMessage) and signature recovery must run in an
environment the client cannot tamper with. Client-side checks are cosmetic only.
### Account for Smart Accounts
Counterfactual smart accounts cannot produce a plain ECDSA signature — they return an
[ERC-6492 wrapped signature](/guides/messages/smart-account-signatures) instead. Detect the
wrapper before attempting ECDSA recovery.
## See More
# Smart Account Signatures (6492/8010)
## Overview
Smart accounts verify signatures onchain via [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271)
`isValidSignature` — which fails when the account contract does not exist yet.
[`SignatureErc6492`](/ercs/erc6492/SignatureErc6492) wraps a signature with the factory call
that deploys the account, so verifiers can validate signatures from **counterfactual**
(not-yet-deployed) accounts. [`SignatureErc8010`](/ercs/erc8010/SignatureErc8010) wraps a
signature with a signed [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) authorization, so
verifiers can validate against an EOA whose delegation is not yet live onchain.
## Recipes
### Wrap a Signature for a Counterfactual Account (ERC-6492)
Wrap the account's signature together with the factory address (`to`) and the calldata that
deploys the account (`data`) using [`SignatureErc6492.wrap`](/ercs/erc6492/SignatureErc6492/wrap).
```ts twoslash
import { Address, Hex, PersonalMessage, Secp256k1, Signature } from 'ox'
import { SignatureErc6492 } from 'ox/erc6492'
declare const factory: Address.Address
declare const factoryData: Hex.Hex
const payload = PersonalMessage.getSignPayload(Hex.fromString('hello world'))
const signature = Secp256k1.sign({ payload, privateKey: '0x...' })
const wrapped = SignatureErc6492.wrap({
data: factoryData,
signature: Signature.toHex(signature),
to: factory,
})
```
The wrapped value ends in the ERC-6492 magic bytes
(`SignatureErc6492.magicBytes`), which is how verifiers distinguish it from a plain signature.
### Unwrap & Verify (ERC-6492)
Detect the wrapper with [`SignatureErc6492.validate`](/ercs/erc6492/SignatureErc6492/validate),
then recover the constituent parts with
[`SignatureErc6492.unwrap`](/ercs/erc6492/SignatureErc6492/unwrap).
```ts twoslash
import { SignatureErc6492 } from 'ox/erc6492'
declare const wrapped: SignatureErc6492.Wrapped
if (!SignatureErc6492.validate(wrapped))
throw new Error('not an ERC-6492 wrapped signature')
const { data, signature, to } = SignatureErc6492.unwrap(wrapped) // [!code hl]
```
For full counterfactual verification, perform an `eth_call` that deploys
[`SignatureErc6492.universalSignatureValidatorBytecode`](/ercs/erc6492/SignatureErc6492)
with the signer, payload hash, and wrapped signature as constructor arguments — it validates
deployed accounts (ERC-1271), undeployed accounts, and plain ECDSA signatures alike.
### Delegate Verification with ERC-8010
Wrap a signature together with a signed EIP-7702 authorization using
[`SignatureErc8010.wrap`](/ercs/erc8010/SignatureErc8010/wrap), so verifiers can apply the
delegation before checking the signature.
```ts twoslash
import { Authorization, PersonalMessage, Secp256k1, Signature } from 'ox'
import { SignatureErc8010 } from 'ox/erc8010'
// 1. Sign the EIP-7702 authorization for the delegation.
const authorization = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 1,
nonce: 69n,
})
const authorizationSignature = Secp256k1.sign({
payload: Authorization.getSignPayload(authorization),
privateKey: '0x...',
})
const authorizationSigned = Authorization.from(authorization, {
signature: authorizationSignature,
})
// 2. Sign the payload.
const signature = Secp256k1.sign({
payload: PersonalMessage.getSignPayload('0xdeadbeef'),
privateKey: '0x...',
})
// 3. Wrap the signature with the authorization.
const wrapped = SignatureErc8010.wrap({
authorization: authorizationSigned,
signature: Signature.toHex(signature),
})
```
On the verifying side, [`SignatureErc8010.unwrap`](/ercs/erc8010/SignatureErc8010/unwrap)
recovers the authorization and the inner signature:
```ts twoslash
import { SignatureErc8010 } from 'ox/erc8010'
declare const wrapped: SignatureErc8010.Wrapped
const { authorization, signature } = SignatureErc8010.unwrap(wrapped)
```
## Best Practices
### Check the Magic Bytes First
Both formats terminate in distinctive magic bytes. Use `validate` before unwrapping, and fall
back to plain ECDSA verification when it returns `false` — EOAs and deployed accounts still
produce unwrapped signatures.
### Serialize the Inner Signature
`wrap` expects the inner signature as serialized hex. Convert structured signatures with
[`Signature.toHex`](/api/Signature/toHex) before wrapping.
### Verify Against Live Chain State
Wrappers only carry the *instructions* to make verification possible. Trustworthy verification
still requires executing them against current chain state (e.g. the universal validator via
`eth_call`), since the account may have been deployed, upgraded, or re-delegated since signing.
## See More
# Runtime & Performance
## Overview
Ox runs on portable JavaScript cryptography by default and lets performance-sensitive
applications opt into faster backends. Install a WASM or Node.js [`Engine`](/api/Engine) to
accelerate cryptography without changing calling code, create an independently owned WASM KZG
instance for blobs and PeerDAS, and manage Ox's global caches and bundle footprint.
```ts twoslash
import { Engine, Hash } from 'ox/wasm'
await Engine.install()
const digest = Hash.keccak256('0xdeadbeef')
```
# Caching & Bundle Size
## Overview
Ox keeps a small set of module-instance-global caches to avoid recomputing derived values.
The `Caches` module exposes them: [`Address.checksum`](/api/Address/checksum) results are
memoized in a bounded map holding up to 32,768 entries with first-in-first-out eviction.
Long-running processes and test suites can clear or tune these caches directly.
## Recipes
### Clear Global Caches
Reset every global cache in one call — for example between test cases, or in a long-running
process after a burst of one-off work.
```ts twoslash
import { Address, Caches } from 'ox'
// Checksumming populates the global checksum cache.
Address.checksum('0xa0cf798816d4b9b9866b5330eea46a18382f251e')
Caches.clear()
```
Installing, setting, or resetting an [engine](/guides/runtime/engines) also clears Ox's
derived cryptographic caches automatically.
### Clear a Single Cache
Each cache is exported as a bounded `Map`, so the standard `Map` API applies when only one
cache should be inspected or reset.
```ts twoslash
import { Address, Caches } from 'ox'
Address.checksum('0xa0cf798816d4b9b9866b5330eea46a18382f251e')
Caches.checksum.size
// @log: 1
Caches.checksum.clear()
```
### Tune Cache Capacity
Lower `maxSize` to trade hit rate for memory in constrained environments. Once the bound is
reached, writes evict the oldest entry first.
```ts twoslash
import { Caches } from 'ox'
Caches.checksum.maxSize = 1_024
```
The default bound is 32,768 entries per cache.
## Bundle Size
Ox modules are collections of pure, stateless functions — not stateful instances — so
bundlers can tree-shake unused functions out of the final bundle. Both named imports
(`import { Hex } from 'ox'`) and entrypoint imports (`import * as Hex from 'ox/Hex'`) stay
tree-shakable; the [Imports & Bundle Size](/imports) page covers both approaches and which
bundlers support them.
Optional entrypoints such as `ox/wasm` and `ox/node` live outside the default entrypoint, so
their runtime-specific artifacts are only bundled when an application imports them.
## See More
# WASM & Engines
## Overview
Ox uses portable JavaScript cryptography by default. An [`Engine`](/api/Engine)
replaces individual implementations without changing the `Hash`, `Secp256k1`,
`Keystore`, or other public APIs that call them.
| Engine | Runtime | Benefits | Trade-offs |
| --------- | ------------------------- | ----------------------------------- | ------------------------------------ |
| `ox` | Browser, Node, and edge | Audited, isomorphic, no setup | Slower for some primitives |
| `ox/wasm` | Runtimes with WebAssembly | Fast, isomorphic, portable | Async startup and memory marshalling |
| `ox/node` | Node.js 22 and newer | Native cryptography, no compilation | Node-only and intentionally partial |
| Custom | Implementation-dependent | Any supported primitive or provider | You own correctness and key handling |
Engines are partial. Anything they omit leaves the currently installed
implementation unchanged, falling back to Ox's default when no override was
installed earlier. [`Engine.install`](/api/Engine/install) resolves selected
provider modules in parallel and installs them only after every module is
ready. Calls merge, including within the same slot, and Ox selects an
implementation when a cryptographic function is called.
Install an engine once during application startup, before making cryptographic
calls. The registry belongs to one loaded Ox module instance, so separate
copies of Ox have separate registries.
## Recipes
### Use the Default Engine
No setup is required:
```ts twoslash
import { Hash } from 'ox'
const digest = Hash.keccak256('0xdeadbeef')
```
Ox's defaults use the
[`@noble`](https://github.com/paulmillr/noble-hashes) and
[`@scure`](https://github.com/paulmillr/scure-bip32) JavaScript libraries.
[`Engine.get()`](/api/Engine/get) returns `{}` until an override is installed
because defaults are fallbacks, not registered overrides.
**Benefits**
* Works across browsers, Node.js, and edge runtimes.
* Covers Ox's complete cryptography surface.
* Requires no initialization or runtime-specific entrypoint.
* Keeps runtime-specific dependencies out of the default entrypoint.
**Trade-offs**
* Pure JavaScript can be slower than WASM or platform-native implementations.
* It cannot use Node's OpenSSL and hardware-accelerated SHA paths.
* It may not satisfy a policy requiring a particular native, hardware, or
validated provider.
### Install the WASM Engine
The WASM engine compiles and installs asynchronously:
```ts twoslash
import { Engine, Hash } from 'ox/wasm'
await Engine.install()
const digest = Hash.keccak256('0xdeadbeef')
```
It supplies the following partial slots:
* `Hash`: BLAKE3, HMAC-SHA256, Keccak256, RIPEMD-160, and SHA-256.
* `Keystore`: synchronous PBKDF2-HMAC-SHA256.
* `MlDsa44`: public-key derivation, signing, and verification.
* `Mnemonic`: BIP-39 seed derivation.
* `Secp256k1`: public-key derivation, shared-secret calculation, recovery,
signing, and verification.
* `Ed25519`: public-key derivation, signing, verification, and private-key
conversion to X25519.
* `X25519`: public-key derivation and shared-secret calculation.
Other operations keep their current implementation, or use Ox's default when
no earlier override exists. In particular, asynchronous KDFs remain on the
default because wrapping synchronous WASM in a promise would not make it yield.
Random key generation for `MlDsa44` and `Secp256k1` remains host-backed.
The dedicated `ox/wasm/Keystore` provider also supplies synchronous scrypt.
Install that provider explicitly. The aggregate engine excludes scrypt because
its relative performance depends on `N`, `r`, `p`, and the runtime.
KZG is intentionally outside the global registry. Use the explicit,
independently owned factory described in the
[WASM KZG guide](/guides/runtime/kzg).
**Benefits**
* Runs in browsers, Node.js, and other runtimes with WebAssembly.
* Accelerates hashes, key derivation, Ed25519, ML-DSA-44, Secp256k1, and X25519
on common runtimes.
* Keeps cryptographic calls synchronous after one asynchronous startup step.
* Embeds the compiled module, with no separate WASM asset to host.
* Clears copied secret inputs, staged outputs, and explicit workspaces after
each sensitive call, including after recoverable traps.
**Trade-offs**
* Requires asynchronous initialization before cryptographic calls.
* Copies inputs and outputs across WASM linear memory.
* Gains vary by primitive, input size, runtime, and processor.
* Adds the WASM implementation without removing JavaScript fallbacks from the
bundle.
* Uses pinned portable C implementations that Ox must keep reviewed and
updated.
### Install the Node Engine
The Node engine uses the built-in `node:crypto` implementation. Its setup is
asynchronous to match `ox/wasm`, although Node requires no compilation:
```ts twoslash
import { Engine, Hash } from 'ox/node'
await Engine.install()
const digest = Hash.sha256('0xdeadbeef')
```
It supplies the following partial slots:
* `Hash`: HMAC-SHA256, RIPEMD-160, and SHA-256.
* `Keystore`: AES-CTR and synchronous/asynchronous PBKDF2-HMAC-SHA256.
* `Mnemonic`: BIP-39 seed derivation.
* `Ed25519`: public-key derivation, signing, and private-key conversion to
X25519.
* `P256`: public-key derivation.
* `X25519`: public-key derivation and shared-secret calculation.
Other operations keep their current implementation, or use Ox's default when
no earlier override exists. Node's `sha3-256` is not Ethereum Keccak256 and
must not be substituted for it. Ed25519 verification stays on the default
because Node/OpenSSL does not implement Ox's ZIP-215 semantics. Scrypt also
stays on the default because OpenSSL rejects parameter combinations accepted
by Ox's public API.
**Benefits**
* Uses Node's native OpenSSL-backed cryptography and libuv threadpool.
* Can use processor acceleration for hashes, AES, and supported curves.
* Requires no WASM compilation or memory marshalling.
* Lives in a separate entrypoint, so browser bundles do not resolve
`node:crypto`.
**Trade-offs**
* Supports Node.js only and must not be imported into browser bundles.
* Does not provide Keccak256, BLAKE3, scrypt, or ZIP-215 verification.
* Native call overhead can affect short-input rankings.
* Algorithm availability and validation modes depend on the Node and OpenSSL
build. FIPS mode may reject RIPEMD-160.
* Leaves Ox's default fallback code available.
### Install Selected Modules
Provider modules expose the regular Ox API alongside an `engine` factory. Use
this to install only the modules an application needs:
```ts twoslash
import { Engine } from 'ox'
import { Hash } from 'ox/wasm'
await Engine.install({
Hash: Hash.engine(),
})
const digest = Hash.sha256('0xdeadbeef')
```
`Engine.install` awaits all supplied slot promises together, then installs the
resolved modules atomically. `Hash.engine()` returns the raw `Hash` slot;
`Hash.sha256()` remains the normal formatted public API.
Install one Node module through the same core API:
```ts twoslash
import { Engine } from 'ox'
import { Hash } from 'ox/node'
await Engine.install({
Hash: Hash.engine(),
})
const digest = Hash.sha256('0xdeadbeef')
```
### Combine Node & WASM Modules
Select modules from different providers in one atomic installation:
```ts twoslash
import { Engine, Hash } from 'ox'
import { Hash as NodeHash } from 'ox/node'
import { Ed25519 as WasmEd25519 } from 'ox/wasm'
await Engine.install({
Ed25519: WasmEd25519.engine(),
Hash: NodeHash.engine(),
})
const digest = Hash.sha256('0xdeadbeef')
```
The factories begin initializing while the argument is evaluated, then
`Engine.install` awaits them together. If any factory rejects, none of the
resolved modules are installed.
Repeated installations merge primitives. Installing Node's `Hash` after WASM
keeps WASM-only BLAKE3 and Keccak256 installed while replacing the three
overlapping hashes. Reset the slot first when replacing it completely:
```ts twoslash
import { Engine } from 'ox'
import { Hash } from 'ox/node'
Engine.reset('Hash')
await Engine.install({ Hash: Hash.engine() })
```
### Build a Custom Engine
Install any subset of Ox's engine contract with
[`Engine.set`](/api/Engine/set):
```ts twoslash
import { Engine } from 'ox'
Engine.set({
Hash: {
keccak256: (input) => myKeccak256(input),
},
})
// ---cut-after---
declare function myKeccak256(input: Uint8Array): Uint8Array
```
Slots and primitives are optional, and repeated calls merge:
```ts twoslash
import { Engine } from 'ox'
// ---cut---
Engine.set({ Hash: { keccak256: myKeccak256 } })
Engine.set({ Secp256k1: mySecp256k1 })
// ---cut-after---
declare const myKeccak256: (input: Uint8Array) => Uint8Array
declare const mySecp256k1: NonNullable
```
Use `Engine.install` when one or more custom modules are asynchronous. Values
may be slots or promises of slots:
```ts twoslash
import { Engine } from 'ox'
await Engine.install({
Hash: Promise.resolve({ keccak256: myKeccak256 }),
})
// ---cut-after---
declare const myKeccak256: (input: Uint8Array) => Uint8Array
```
Binary values cross engine boundaries as raw `Uint8Array` values. Ox performs
`Hex` and `Bytes` conversion outside the engine boundary. Install explicitly
rather than relying on a side-effect import: Ox declares `sideEffects: false`,
so a bundler may drop an import that appears unused.
**Benefits**
* Supports synchronous native libraries and policy-required providers.
* Replaces one primitive without requiring a complete slot.
* Preserves Ox's public APIs and input/output conversion.
* Composes with the built-in Node and WASM engines.
**Trade-offs**
* The engine author owns algorithm semantics, output lengths, key formats, and
error behavior.
* Most engine functions are synchronous. Only explicitly asynchronous
contracts such as `scryptAsync` may return promises.
* Overrides are module-instance-global, so initialization order and concurrent
use matter.
* Installing an engine changes dispatch but does not remove defaults from the
bundle.
## Benchmarks
Run the engine comparison with:
```sh
pnpm bench:engines
```
The harness covers every engine slot and all 38 primitives in Ox's default
engine. The columns count the primitives each provider or reference supplies:
| Slot | Primitives | `ox` | `ox/node` | `ox/wasm` | C |
| ----------- | ---------- | ------ | --------- | --------- | ------ |
| `Bls` | 5 | 5 | n/a | n/a | n/a |
| `Ed25519` | 6 | 6 | 3 | 4 | 4 |
| `Hash` | 5 | 5 | 3 | 5 | 5 |
| `Keystore` | 6 | 6 | 4 | 2 | 2 |
| `MlDsa44` | 4 | 4 | n/a | 3 | 3 |
| `Mnemonic` | 1 | 1 | 1 | 1 | 1 |
| `P256` | 6 | 6 | 1 | n/a | n/a |
| `Secp256k1` | 6 | 6 | n/a | 5 | 5 |
| `X25519` | 3 | 3 | 2 | 2 | 2 |
| **Total** | **42** | **42** | **14** | **22** | **22** |
`n/a` means the provider does not implement a primitive in that slot. The
harness never times Ox's fallback under another engine's name.
The C reference compiles the same primitive wrappers, vendored sources, and
target configuration as `ox/wasm` for the host. C covers every primitive
supplied by WASM, but is not an Ox engine. The `ox/wasm` count includes the
opt-in Keystore scrypt provider.
Local runs on an Apple M4 Max with Node.js 25.9.0 and Apple Clang 21.0.0 used
50 ms warmups, 200 ms measurement budgets, and three repeats. The following
table shows the best-observed timings (lower is better). Speedup compares the
fastest Ox engine in each row with `ox`; C remains a reference only. The full
command prints every primitive and input size:
| Primitive and case | `ox` | `ox/node` | `ox/wasm` | C | Fastest Ox engine vs `ox` |
| -------------------------------------- | --------- | --------- | --------- | --------- | ------------------------- |
| `Bls.sign`, 32 B message | 15.70 ms | n/a | n/a | n/a | n/a |
| `Ed25519.getPublicKey`, 32 B key | 95.51 µs | 41.87 µs | 21.82 µs | 18.80 µs | 4.38× (wasm) |
| `Ed25519.sign`, 32 B message | 202.12 µs | 43.13 µs | 45.18 µs | 38.61 µs | 4.69× (node) |
| `Ed25519.verify`, 32 B message | 960.96 µs | n/a | 59.31 µs | 49.81 µs | 16.20× (wasm) |
| `Hash.blake3`, 32 B | 1.23 µs | n/a | 428 ns | 563 ns | 2.88× (wasm) |
| `Hash.blake3`, 1024 KiB | 11.30 ms | n/a | 1.08 ms | 875.06 µs | 10.50× (wasm) |
| `Hash.keccak256`, 32 B | 2.62 µs | n/a | 278 ns | 187 ns | 9.44× (wasm) |
| `Hash.keccak256`, 1024 KiB | 20.10 ms | n/a | 2.32 ms | 1.39 ms | 8.67× (wasm) |
| `Hash.sha256`, 1024 KiB | 3.95 ms | 368.29 µs | 3.25 ms | 2.48 ms | 10.72× (node) |
| `Keystore.aesCtrEncrypt`, 4 KiB | 32.02 µs | 2.92 µs | n/a | n/a | 10.95× (node) |
| `Keystore.pbkdf2Sha256`, 262,144 runs | 241.53 ms | 22.94 ms | 105.01 ms | 86.59 ms | 10.53× (node) |
| `Keystore.scrypt`, N=1,024, r=1, p=1 | 207.76 µs | n/a | 161.16 µs | 141.87 µs | 1.29× (wasm) |
| `Keystore.scrypt`, N=16,384, r=8, p=1 | 24.14 ms | n/a | 21.06 ms | 18.38 ms | 1.15× (wasm) |
| `Keystore.scrypt`, N=262,144, r=1, p=8 | 513.45 ms | n/a | 443.69 ms | 445.30 ms | 1.16× (wasm) |
| `Mnemonic.toSeed`, 12 words | 6.52 ms | 470.29 µs | 1.93 ms | 1.83 ms | 13.86× (node) |
| `P256.getPublicKey`, 32 B key | 142.41 µs | 11.03 µs | n/a | n/a | 12.91× (node) |
| `Secp256k1.getPublicKey`, 32 B key | 147.40 µs | n/a | 19.14 µs | 15.42 µs | 7.70× (wasm) |
| `Secp256k1.getSharedSecret`, 65 B key | 1.77 ms | n/a | 34.20 µs | 27.51 µs | 51.64× (wasm) |
| `Secp256k1.recoverPublicKey`, 32 B | 1.15 ms | n/a | 36.62 µs | 32.46 µs | 31.40× (wasm) |
| `Secp256k1.sign`, 32 B message | 183.76 µs | n/a | 25.03 µs | 19.86 µs | 7.34× (wasm) |
| `Secp256k1.verify`, 32 B message | 1.03 ms | n/a | 31.50 µs | 27.31 µs | 32.80× (wasm) |
| `X25519.getSharedSecret`, 32 B key | 627.61 µs | 48.74 µs | 41.32 µs | 33.69 µs | 15.19× (wasm) |
The benchmark initializes engines outside the timed loops and sends each Ox
call through the same engine resolver. It uses identical inputs, warmups,
budgets, and repeats, and reports the best-observed repeat as a peak-throughput
microbenchmark, not a latency distribution. It measures raw single-call
byte-array implementations, not Ox formatting or whole applications. Treat the
results as runtime-specific: Node/OpenSSL, CPU acceleration, the WASM runtime,
the C compiler, JIT state, and input size can all change the ranking.
## Testing
Reset the installed engine between tests:
```ts twoslash
import { Engine } from 'ox'
import { beforeEach } from 'vitest'
beforeEach(() => {
Engine.reset()
})
```
For differential tests, obtain an implementation with `engine`, then install it
for one synchronous call with [`Engine.with`](/api/Engine/with):
```ts twoslash
import { Engine, Hash } from 'ox'
import { Engine as WasmEngine } from 'ox/wasm'
const wasm = await WasmEngine.engine()
const digest = Engine.with(wasm, () => Hash.sha256('0xdeadbeef'))
```
`Engine.with` rejects asynchronous functions because concurrent work could
observe the module-instance-global override. `Engine.install`, `Engine.set`,
and `Engine.reset` clear Ox's derived cryptographic caches automatically.
Test custom implementations against published vectors, boundary-sized and
empty inputs, and an independent implementation. Verify exact digest,
signature, and key lengths rather than checking only that a call succeeds.
Ox's built-in engines add independent conformance coverage for NIST AES-CTR,
RFC 7914 PBKDF2, RFC 8032 Ed25519, all 196 ZIP-215 verification cases, RFC 7748
X25519, libsodium's low-order X25519 corpus, official BLAKE3 vectors, and
English and Japanese BIP-39 vectors. Differential fuzz tests also cover
subviews, input immutability, output ownership, interleaved providers, memory
growth, and boundary-sized inputs. WASM conformance runs in Chromium, Firefox,
and WebKit as well as Node.js.
## Security
Treat an engine as trusted code. Depending on the slot, it can receive HMAC
keys, private keys, passwords, mnemonic phrases, and plaintext keystore
material. `Engine.install` and `Engine.set` validate slot and primitive names,
but they cannot validate correctness, constant-time behavior, or key handling.
Ox's default engine uses audited cryptographic implementations. The WASM engine
does not promise protection from timing or cache side channels. WebAssembly has
[no constant-time execution guarantee](https://webassembly.org/docs/security/).
The WASM providers clear copied secret inputs, staged outputs, and explicit
workspaces from linear memory in `finally` blocks, including after recoverable
WebAssembly traps. They cannot clear caller-owned buffers, JavaScript strings,
runtime-managed state, or every compiler-created stack temporary. This does
not make the surrounding runtime side-channel resistant.
The WASM curve and mnemonic provider pins
[Monocypher 4.0.3](https://github.com/LoupVaillant/Monocypher/tree/4.0.3).
Its published Cure53 audit covered version 3.1.1, not the 4.x series, and 4.0.3
includes a fix recorded in Monocypher's
[security disclosures](https://monocypher.org/quality-assurance/disclosures).
The BLAKE3 provider pins the official portable C implementation and disables
architecture-specific SIMD and atomics.
The Node engine inherits the properties of the active Node and OpenSSL build.
Using `node:crypto` does not itself mean FIPS mode is enabled or that every
configured provider exposes RIPEMD-160.
For threats involving precise timing measurement or hostile same-process code,
use an OS keystore, hardware-backed signer, or isolated signing service.
## See More
# WASM KZG
## Overview
Ox provides an opt-in KZG implementation backed by
[`c-kzg-4844`](https://github.com/ethereum/c-kzg-4844). It implements the
existing [`Kzg.Kzg`](/api/Kzg) interface without changing the global
[`Engine`](/api/Engine) registry.
## Recipes
### Create an Instance
Supply the Ethereum trusted setup when creating an instance:
```ts twoslash
import { Blobs } from 'ox'
import { Setups } from 'ox/trusted-setups'
import { Kzg } from 'ox/wasm'
const kzg = await Kzg.create({ trustedSetup: Setups.mainnet })
try {
const blobs = Blobs.from('0xdeadbeef')
const commitments = Blobs.toCommitments(blobs, { kzg })
} finally {
kzg.dispose()
}
```
`Setups.mainnet` contains Ox's packed copy of the canonical Ethereum setup. You
can reuse the same value across factory calls because each call copies the
setup before asynchronous initialization.
Ox sources the setup from an explicit tagged `c-kzg-4844` release and records
both source and generated-data SHA-256 values. Release updates require an
explicit review and regeneration; they never follow a moving branch.
The factory also accepts custom setups with the standard `g1_lagrange`,
`g1_monomial`, and `g2_monomial` fields. Each field may contain hex points or
one packed byte array.
The instance implements all EIP-4844 and EIP-7594 operations in `Kzg.Kzg`:
* `blobToKzgCommitment`
* `computeCells`
* `computeCellsAndKzgProofs`
* `recoverCellsAndKzgProofs`
* `verifyCellKzgProofBatch`
Import `ox/wasm/crypto/Kzg` directly when only KZG is needed. The dedicated artifact
does not load through `ox`, another WASM module, or an `Engine` slot.
Import `ox/trusted-setups/Setups` directly when only setup data is needed. The
packed setup is not loaded by `ox`, `ox/wasm`, or `ox/trusted-setups/Paths`.
### Own & Dispose Instances
Each `create` call owns separate WASM memory and trusted-setup state, so release
an instance explicitly once its work is done.
```ts twoslash
import { Setups } from 'ox/trusted-setups'
import { Kzg } from 'ox/wasm'
const kzg = await Kzg.create({ trustedSetup: Setups.mainnet })
kzg.dispose()
kzg.dispose() // idempotent
```
Concurrent factory calls share only the compiled module, not mutable memory or
setup state.
Operations are synchronous and run to completion. Create one instance inside
each JavaScript worker that performs KZG operations.
`dispose` is idempotent. It frees c-kzg setup allocations, clears the module
reference, and makes later operations throw `Kzg.DisposedError`.
The JavaScript runtime controls when the underlying `WebAssembly.Memory` object
is collected. Drop other references to the instance so the runtime can reclaim
that memory.
Inputs are copied into linear memory. Scratch inputs and outputs are zeroed and
freed after each operation, including failed operations.
### Tune Memory & Precomputation
`precompute` selects c-kzg's fixed-base MSM window. The default `0` uses the
least memory. Larger windows trade memory for proof-generation performance.
```ts twoslash
import { Setups } from 'ox/trusted-setups'
import { Kzg } from 'ox/wasm'
const kzg = await Kzg.create({
trustedSetup: Setups.mainnet,
precompute: 4, // [!code hl]
})
```
The KZG artifact is 166.1 KiB raw, 221.4 KiB as embedded base64, and 51.4 KiB
gzip. The trusted setup contains 390.1 KiB of packed points, uses 520.1 KiB of
embedded base64, and produces a 395.6 KiB gzip standalone bundle.
Each KZG instance starts with 8 MiB and may grow to 128 MiB.
| `precompute` | Linear memory after initialization |
| ------------ | ---------------------------------- |
| 0 | 8 MiB |
| 1 | 8 MiB |
| 2 | 8 MiB |
| 3 | 8 MiB |
| 4 | 10.5 MiB |
| 5 | 16.5 MiB |
| 6 | 28.5 MiB |
| 7 | 52.5 MiB |
| 8 | 100.5 MiB |
These values measure WASM linear memory immediately after trusted-setup
initialization. Operation inputs and outputs may grow memory further, within the
128 MiB limit.
Use the smallest window that meets the target workload. Run
`pnpm bench src/wasm/crypto/Kzg.bench.ts --project core` on the deployment hardware to
compare initialization and every supported operation.
## See More
# Schemas & Validation
## Overview
Ox ships [Zod](https://zod.dev) schemas for Ethereum data structures via the
[`ox/zod`](/zod) entrypoint. Most schemas are codecs that convert between the JSON-RPC wire
format (hex-string quantities) and the ergonomic decoded format used in application code
(`bigint`/`number`), and every schema doubles as a validator for untrusted input.
```ts twoslash
import { z } from 'ox/zod'
const value = z.decode(z.Uint256, '0x2a')
// @log: 42n
```
# Validate with Zod
## Overview
Ox provides a set of [Zod](https://zod.dev) schemas for Ethereum data structures via the [`ox/zod`](/zod) entrypoint. These schemas are useful for **validating**, **decoding**, and **encoding** values that cross the JSON-RPC boundary (for example, parsing the result of an RPC call, or building a strongly-typed request).
Most schemas are [Zod codecs](https://zod.dev/codecs) that convert between two representations:
* **Input (RPC / wire format)** – the format used over JSON-RPC, where quantities are hex strings (e.g. `'0x1'`).
* **Output (decoded format)** – the ergonomic format used in application code, where quantities are `bigint`/`number` (e.g. `1n`).
`zod` ships as a dependency of Ox, so there is nothing extra to install.
## Recipes
### Import Schemas
Everything is available under the `z` namespace, which re-exports all of [`zod/mini`](https://zod.dev/packages/mini) alongside Ox's schema namespaces:
```ts twoslash
import { z } from 'ox/zod'
```
This gives you:
* All standard Zod utilities (`z.decode`, `z.encode`, `z.parse`, `z.safeParse`, `z.object`, the `z.input`/`z.output` type helpers, etc.).
* Module-scoped Ethereum schemas (`z.Address`, `z.Block`, `z.Transaction`, `z.Log`, …).
* Direct integer quantity schemas (`z.Uint256`, `z.Int256`, `z.Number`, `z.BigInt`, …).
* JSON-RPC method schemas (`z.RpcSchema`).
* Tempo schemas (`z.tempo`).
### Decode & Encode RPC Data
Use `z.decode` to convert an RPC value into its decoded form, and `z.encode` to convert it back.
```ts twoslash
import { z } from 'ox/zod'
// Decode an RPC hex quantity into a `bigint`.
const value = z.decode(z.Uint256, '0x2a')
// @log: 42n
// Encode it back into an RPC hex quantity.
const hex = z.encode(z.Uint256, value)
// @log: '0x2a'
```
Schemas compose, so you can decode an entire structure in one pass:
```ts twoslash
import { z } from 'ox/zod'
const signature = z.decode(z.Signature.Signature, {
r: '0x0000000000000000000000000000000000000000000000000000000000000001',
s: '0x0000000000000000000000000000000000000000000000000000000000000002',
yParity: '0x1',
})
// @log: { r: 1n, s: 2n, yParity: 1 }
```
### Validate Untrusted Input
Since these are Zod schemas, you can validate values with the usual `z.parse` and `z.safeParse` helpers:
```ts twoslash
import { z } from 'ox/zod'
const result = z.safeParse(z.Address.Address, '0xdeadbeef')
// @log: { success: false, error: [ZodError] }
```
### Decode Integer Quantities
Hex quantities can be decoded directly into `bigint` or `number` using sized integer schemas. Unsigned (`Uint`) and signed (`Int`) variants are available in 8-bit increments from `8` to `256`, in addition to the unsized `Uint`/`Int` and the `Number`/`BigInt` helpers.
```ts twoslash
import { z } from 'ox/zod'
z.decode(z.Uint8, '0xff') // 255 (number)
z.decode(z.Uint256, '0x2a') // 42n (bigint)
z.decode(z.Number, '0x1b4') // 436 (number)
z.decode(z.BigInt, '0x1b4') // 436n (bigint)
```
Schemas with a result that fits within 48 bits (e.g. `Uint8` … `Uint48`) decode to a `number`; larger schemas decode to a `bigint`.
### Use JSON-RPC Method Schemas
`z.RpcSchema` exposes per-method schemas for the `eth_` and `wallet_` namespaces, plus helpers to validate and decode requests, params, and results.
The namespaces are:
* `z.RpcSchema.Eth` – `eth_` methods.
* `z.RpcSchema.Wallet` – `wallet_` methods.
* `z.RpcSchema.Default` – the union of both.
Decode the `params` or `result` for a single method:
```ts twoslash
import { z } from 'ox/zod'
// Decode the `params` for a method.
const params = z.RpcSchema.decodeParams(
z.RpcSchema.Eth,
'eth_getBlockByNumber',
['0x1', true],
)
// Decode the `result` for a method.
const result = z.RpcSchema.decodeReturns(
z.RpcSchema.Eth,
'eth_blockNumber',
'0x1b4',
)
// @log: 436n
```
`z.RpcSchema.decodeRequest` (aliased as `z.RpcSchema.parse`) validates and decodes a full `{ method, params }` request, dispatching on `method`:
```ts twoslash
import { z } from 'ox/zod'
const request = z.RpcSchema.decodeRequest(z.RpcSchema.Eth, {
method: 'eth_getBlockByNumber',
params: ['0x1', true],
})
```
Use `z.RpcSchema.parseItem` to retrieve the schema for a single method (its `method`, `params`, `returns`, and `request` schemas):
```ts twoslash
import { z } from 'ox/zod'
const item = z.RpcSchema.parseItem(z.RpcSchema.Eth, 'eth_blockNumber')
```
If a method does not exist on the namespace, the helpers throw a `z.RpcSchema.MethodNotFoundError`.
### Define Custom Method Schemas
Use `z.RpcSchema.from` to define your own method schema:
```ts twoslash
import { z } from 'ox/zod'
const eth_blockNumber = z.RpcSchema.from({
method: 'eth_blockNumber',
params: z.tuple([]),
returns: z.Uint256,
})
```
## Tempo Schemas
Schemas for [Tempo](/tempo) data structures are available under `z.tempo` (e.g. `z.tempo.Transaction`, `z.tempo.TransactionReceipt`, `z.tempo.TxEnvelopeTempo`, `z.tempo.SignatureEnvelope`, `z.tempo.KeyAuthorization`, `z.tempo.RpcSchemaTempo`).
They work the same way as the core schemas:
```ts twoslash
import { z } from 'ox/zod'
type TransactionRpc = z.input
type Transaction = z.output
```
## Types
Use Zod's `z.input` and `z.output` type helpers to extract the RPC and decoded types from any schema:
```ts twoslash
import { z } from 'ox/zod'
type TransactionRpc = z.input
type Transaction = z.output
```
## Available Schemas
The `ox/zod` entrypoint includes schemas for:
* **Primitives**: `Address`, `Bytes`, `Hash`, `Hex`, `BigInt`, `Number`, `Int`, `Uint`
* **Accounts & State**: `AccountProof`, `StateOverrides`, `BlockOverrides`
* **Blocks & Logs**: `Block`, `Log`, `Filter`, `Withdrawal`
* **Fees & Access**: `Fee`, `AccessList`, `Authorization`
* **Transactions**: `Transaction`, `TransactionReceipt`, `TransactionRequest`, `TransactionEnvelope` (and per-type `TxEnvelopeLegacy`, `TxEnvelopeEip1559`, `TxEnvelopeEip2930`, `TxEnvelopeEip4844`, `TxEnvelopeEip7702`)
* **Signatures**: `Signature`
* **JSON-RPC**: `RpcResponse`, `RpcSchema`
* **Tempo**: `tempo.*`
## See More
# Transactions
## Overview
Ox provides protocol-level primitives for every Ethereum transaction envelope type — from legacy
transactions through [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) blobs and
[EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) delegations. The
[`TxEnvelope*`](/api/TransactionEnvelope) modules construct, sign, serialize, and deserialize
envelopes locally, with no client required. Recipes end at the network boundary — hand the
serialized payload to a JSON-RPC transport, or use a higher-level client like
[Viem](https://viem.sh) when an application also needs to fill and track transactions.
```ts twoslash
import { Secp256k1, TxEnvelopeEip1559, Value } from 'ox'
// 1. Construct the envelope.
const envelope = TxEnvelopeEip1559.from({
chainId: 1,
gas: 21_000n,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
nonce: 69n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1.5'),
})
// 2. Sign over the envelope.
const signature = Secp256k1.sign({
payload: TxEnvelopeEip1559.getSignPayload(envelope),
privateKey: '0x...',
})
// 3. Serialize it, ready for `eth_sendRawTransaction`.
const serialized = TxEnvelopeEip1559.serialize(envelope, { signature })
```
# Build, Sign & Send
## Overview
A transaction envelope is a structure that defines the properties of a transaction, and is
generally used to construct transactions to be broadcast to a network. This guide walks an
[`TxEnvelopeEip1559`](/api/TxEnvelopeEip1559) — the most commonly used envelope type — through
its full lifecycle with [`Secp256k1`](/api/Secp256k1) for signing and
[`RpcTransport`](/api/RpcTransport) for broadcasting.
Every envelope module shares the same lifecycle functions (`from`, `getSignPayload`,
`serialize`, `toRpc`), so these recipes apply to all five envelope types. See
[Choose an Envelope Type](/guides/transactions/envelope-types) for the others.
## Recipes
### Construct an EIP-1559 Envelope
Use [`TxEnvelopeEip1559.from`](/api/TxEnvelopeEip1559/from) to instantiate an envelope. Ox is
stateless — it does not query a node — so supply `nonce`, `gas`, and fee values yourself, or
[hand off to a wallet](#sign-remotely-wallets--signing-servers) that fills them.
```ts twoslash
import { TxEnvelopeEip1559, Value } from 'ox'
const envelope = TxEnvelopeEip1559.from({
chainId: 1,
gas: 21_000n,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
nonce: 69n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1.5'),
})
```
See [Estimate Fees & Access Lists](/guides/transactions/fees-access-lists) for deriving
`maxFeePerGas` from fee history.
### Compute the Sign Payload & Sign
Pass the result of [`TxEnvelopeEip1559.getSignPayload`](/api/TxEnvelopeEip1559/getSignPayload) —
the keccak256 hash of the presign serialization — to a signer such as
[`Secp256k1.sign`](/api/Secp256k1/sign).
```ts twoslash
import { Secp256k1, TxEnvelopeEip1559, Value } from 'ox'
const envelope = TxEnvelopeEip1559.from({
chainId: 1,
gas: 21_000n,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
nonce: 69n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1.5'),
})
const signature = Secp256k1.sign({
payload: TxEnvelopeEip1559.getSignPayload(envelope), // [!code hl]
privateKey: '0x...',
})
// @log: { r: '0x...', s: '0x...', yParity: 0 }
```
### Attach the Signature & Serialize
Attach the signature with `TxEnvelopeEip1559.from`, then serialize into RLP-encoded form with
[`TxEnvelopeEip1559.serialize`](/api/TxEnvelopeEip1559/serialize). `deserialize` reverses the
transformation.
```ts twoslash
import { Secp256k1, TxEnvelopeEip1559, Value } from 'ox'
const envelope = TxEnvelopeEip1559.from({
chainId: 1,
gas: 21_000n,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
nonce: 69n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1.5'),
})
const signature = Secp256k1.sign({
payload: TxEnvelopeEip1559.getSignPayload(envelope),
privateKey: '0x...',
})
// Attach the signature to the envelope.
// @log: { ..., r: '0x...', s: '0x...', yParity: 0 }
const signed = TxEnvelopeEip1559.from(envelope, { signature }) // [!code hl]
// Serialize the signed envelope.
// @log: '0x02f8730145843b9aca00...'
const serialized = TxEnvelopeEip1559.serialize(signed) // [!code hl]
// Deserialize it back into a typed envelope.
const deserialized = TxEnvelopeEip1559.deserialize(serialized)
```
### Broadcast via `eth_sendRawTransaction`
Serialize the envelope with its signature, then broadcast it over JSON-RPC. The example below
uses [`RpcTransport.fromHttp`](/api/RpcTransport/fromHttp) to send a `eth_sendRawTransaction`
request over HTTP.
```ts twoslash
import { RpcTransport, Secp256k1, TxEnvelopeEip1559, Value } from 'ox'
const envelope = TxEnvelopeEip1559.from({
chainId: 1,
gas: 21_000n,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
nonce: 69n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1.5'),
})
const signature = Secp256k1.sign({
payload: TxEnvelopeEip1559.getSignPayload(envelope),
privateKey: '0x...',
})
// Serialize the envelope with the signature.
const serialized = TxEnvelopeEip1559.serialize(envelope, { signature })
// Broadcast the envelope with `eth_sendRawTransaction`.
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const hash = await transport.request({
method: 'eth_sendRawTransaction', // [!code hl]
params: [serialized], // [!code hl]
})
```
If an application also needs to fill fields, wait for receipts, or retry, a client like
[Viem](https://viem.sh/docs/actions/wallet/sendRawTransaction) handles that on top of the same
primitives.
### Sign Remotely (Wallets & Signing Servers)
The recipes above manually fill and sign the transaction. When a wallet — or more generally an
entity responsible for filling and signing transactions — manages the account, skip that
ceremony with the `eth_sendTransaction` RPC method. The example below uses an
[EIP-1193 Provider](/api/Provider) to interact with a browser extension wallet; a
`RpcTransport.fromHttp` works the same way if a backend supports `eth_sendTransaction`.
```ts twoslash
import 'ox/window'
import { Provider, TxEnvelopeEip1559, Value } from 'ox'
// Construct the envelope. The wallet fills nonce, gas & fees.
const envelope = TxEnvelopeEip1559.from({
chainId: 1,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1.5'),
})
// Convert the envelope to an RPC-compatible format.
const envelope_rpc = TxEnvelopeEip1559.toRpc(envelope) // [!code hl]
// Broadcast the envelope with `eth_sendTransaction`.
const provider = Provider.from(window.ethereum)
const hash = await provider.request({
method: 'eth_sendTransaction',
params: [envelope_rpc],
})
```
## Best Practices
### Fill Every Field Before Signing
Ox never reads chain state. A transaction signed with a stale `nonce` or an underpriced
`maxFeePerGas` serializes fine but will be rejected or stall at broadcast. Fetch `nonce`
(`eth_getTransactionCount`), estimate `gas` (`eth_estimateGas`), and derive fees before signing.
### Always Sign the Sign Payload
`getSignPayload` hashes the type-prefixed presign serialization. Signing anything else — the
raw serialized bytes, or a hash computed by hand — produces a signature the network will
attribute to a different transaction (or no valid sender at all).
### Prefer `eth_sendTransaction` for Wallet-Managed Accounts
When the key lives in a wallet or signing server, send an RPC-formatted envelope with
`eth_sendTransaction` instead of exporting key material or replicating the wallet's
fee-filling logic.
## See More
# Choose an Envelope Type
## Overview
Ox supports the five core Ethereum transaction envelope types, each with a dedicated module.
They share the same lifecycle functions (`from`, `getSignPayload`, `serialize`, `toRpc`), so
switching types means changing which fields you supply. The generic
[`TransactionEnvelope`](/api/TransactionEnvelope) module dispatches to the right type
automatically, inferring it from the envelope's shape when `type` is omitted.
| Module | EIP | Type | Fee fields | Adds |
| --------------------------------------------- | --------------------------------------------------- | ------ | -------------------------------------- | --------------------------------- |
| [`TxEnvelopeLegacy`](/api/TxEnvelopeLegacy) | — | `0x00` | `gasPrice` | Original, pre-typed format |
| [`TxEnvelopeEip2930`](/api/TxEnvelopeEip2930) | [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) | `0x01` | `gasPrice` | `accessList` |
| [`TxEnvelopeEip1559`](/api/TxEnvelopeEip1559) | [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) | `0x02` | `maxFeePerGas`, `maxPriorityFeePerGas` | Dynamic fee market |
| [`TxEnvelopeEip4844`](/api/TxEnvelopeEip4844) | [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) | `0x03` | EIP-1559 fields + `maxFeePerBlobGas` | `blobVersionedHashes`, `sidecars` |
| [`TxEnvelopeEip7702`](/api/TxEnvelopeEip7702) | [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) | `0x04` | EIP-1559 fields | `authorizationList` |
## Recipes
### Send a Legacy Transaction
Use [`TxEnvelopeLegacy`](/api/TxEnvelopeLegacy) for chains or tooling that predate typed
transactions. Legacy envelopes price gas with a single `gasPrice` field.
```ts twoslash
import { TxEnvelopeLegacy, Value } from 'ox'
const envelope = TxEnvelopeLegacy.from({
chainId: 1,
gasPrice: Value.fromGwei('10'), // [!code hl]
nonce: 69n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1'),
})
```
Omitting `chainId` produces a pre-EIP-155 transaction that is replayable across chains — only
do that deliberately.
### Warm Storage with an EIP-2930 Access List
Use [`TxEnvelopeEip2930`](/api/TxEnvelopeEip2930) to declare the addresses and storage slots a
transaction will touch, pre-warming them at a discount.
```ts twoslash
import { TxEnvelopeEip2930, Value } from 'ox'
const envelope = TxEnvelopeEip2930.from({
// [!code hl:start]
accessList: [
{
address: '0x1e0049783f008a0085193e00003d00cd54003c71',
storageKeys: [
'0x0000000000000000000000000000000000000000000000000000000000000001',
],
},
],
// [!code hl:end]
chainId: 1,
gasPrice: Value.fromGwei('10'),
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1'),
})
```
EIP-1559, EIP-4844, and EIP-7702 envelopes also accept `accessList` — see
[Estimate Fees & Access Lists](/guides/transactions/fees-access-lists) for building them.
### Pay Dynamic Fees with EIP-1559
Use [`TxEnvelopeEip1559`](/api/TxEnvelopeEip1559) — the default choice on
post-London networks. The sender caps total spend with `maxFeePerGas` and tips the block
producer with `maxPriorityFeePerGas`.
```ts twoslash
import { TxEnvelopeEip1559, Value } from 'ox'
const envelope = TxEnvelopeEip1559.from({
chainId: 1,
maxFeePerGas: Value.fromGwei('10'), // [!code hl]
maxPriorityFeePerGas: Value.fromGwei('1'), // [!code hl]
nonce: 69n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1.5'),
})
```
See [Build, Sign & Send](/guides/transactions/build-sign-send) for the full lifecycle of this
envelope.
### Carry Blob Data with EIP-4844
Use [`TxEnvelopeEip4844`](/api/TxEnvelopeEip4844) to post data blobs (typically rollup batches).
The envelope commits to its blobs through `blobVersionedHashes` and prices blob space with a
separate `maxFeePerBlobGas` market.
```ts twoslash
import { TxEnvelopeEip4844, Value } from 'ox'
const envelope = TxEnvelopeEip4844.from({
// [!code hl:start]
blobVersionedHashes: [
'0x01a24709d3997e8b217fe5460aef10ee515513ceba0362bf2d02a3ba73d7cb09',
],
maxFeePerBlobGas: Value.fromGwei('3'),
// [!code hl:end]
chainId: 1,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
})
```
Computing versioned hashes and sidecars requires a KZG implementation — see
[Send Blob Transactions (EIP-4844)](/guides/transactions/blobs) for the complete flow.
### Delegate Code with EIP-7702
Use [`TxEnvelopeEip7702`](/api/TxEnvelopeEip7702) to set contract code on Externally Owned
Accounts via a signed `authorizationList`.
```ts twoslash
import { Authorization, Secp256k1, TxEnvelopeEip7702, Value } from 'ox'
// Sign an authorization over the delegate contract.
const authorization = Authorization.from({
address: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
chainId: 1,
nonce: 40n,
})
const signature = Secp256k1.sign({
payload: Authorization.getSignPayload(authorization),
privateKey: '0x...',
})
const envelope = TxEnvelopeEip7702.from({
authorizationList: [Authorization.from(authorization, { signature })], // [!code hl]
chainId: 1,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1'),
})
```
See [Delegate with EIP-7702](/guides/transactions/eip-7702) for authorization semantics and
RPC conversion.
## Best Practices
### Default to EIP-1559
Unless a transaction needs blobs, delegations, or targets a chain without the London fee
market, use `TxEnvelopeEip1559`. Legacy and EIP-2930 envelopes overpay whenever `gasPrice` is
set above the block's base fee plus a competitive tip.
### Let the Envelope Shape Pick the Type
When handling heterogeneous input, use the generic
[`TransactionEnvelope.from`](/api/TransactionEnvelope/from): it infers `eip1559` from
`maxFeePerGas`, `eip4844` from blob fields, `eip7702` from `authorizationList`, and so on —
no manual `type` bookkeeping.
## See More
# Delegate with EIP-7702
## Overview
[EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) lets an Externally Owned Account set
contract code for itself by signing an authorization over a delegate contract's address. The
[`Authorization`](/api/Authorization) module creates, signs, and converts authorization tuples;
[`TxEnvelopeEip7702`](/api/TxEnvelopeEip7702) carries a list of them in a type-4 transaction.
The account that signs an authorization (the authority) and the account that sends the
transaction (the sponsor) can be different — that is what enables gas sponsorship.
## Recipes
### Sign an Authorization
Construct the authorization with [`Authorization.from`](/api/Authorization/from), sign its
[`getSignPayload`](/api/Authorization/getSignPayload) —
`keccak256('0x05' || rlp([chain_id, address, nonce]))` — with the **authority's** private key,
then attach the signature.
```ts twoslash
import { Authorization, Secp256k1 } from 'ox'
// `address` is the delegate contract; `nonce` is the authority's
// nonce at execution time.
const authorization = Authorization.from({
address: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', // [!code hl]
chainId: 1,
nonce: 40n,
})
const signature = Secp256k1.sign({
payload: Authorization.getSignPayload(authorization),
privateKey: '0x...', // the authority's private key
})
const authorization_signed = Authorization.from(authorization, { signature })
// @log: { address: '0x7099...79c8', chainId: 1, nonce: 40n, r: '0x...', s: '0x...', yParity: 1 }
```
### Build a 7702 Envelope
Attach one or more signed authorizations to a
[`TxEnvelopeEip7702`](/api/TxEnvelopeEip7702), then sign and serialize the envelope with the
**sender's** key like any other transaction.
```ts twoslash
import { Authorization, Secp256k1, TxEnvelopeEip7702, Value } from 'ox'
const authorization = Authorization.from({
address: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
chainId: 1,
nonce: 40n,
})
const authorization_signed = Authorization.from(authorization, {
signature: Secp256k1.sign({
payload: Authorization.getSignPayload(authorization),
privateKey: '0x...', // authority
}),
})
const envelope = TxEnvelopeEip7702.from({
authorizationList: [authorization_signed], // [!code hl]
chainId: 1,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
nonce: 0n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
})
// Sign & serialize with the sender's key, ready for `eth_sendRawTransaction`.
const signature = Secp256k1.sign({
payload: TxEnvelopeEip7702.getSignPayload(envelope),
privateKey: '0x...', // sender (sponsor)
})
const serialized = TxEnvelopeEip7702.serialize(envelope, { signature })
```
See [Build, Sign & Send](/guides/transactions/build-sign-send) for broadcasting the serialized
envelope.
### Convert Authorization Lists for RPC
Wallet-facing flows exchange authorizations in hex-quantity RPC format. Use
[`Authorization.toRpcList`](/api/Authorization/toRpcList) before placing a list on an
`eth_sendTransaction` request, and
[`Authorization.fromRpcList`](/api/Authorization/fromRpcList) to restore typed values from RPC
transactions.
```ts twoslash
import { Authorization } from 'ox'
declare const authorizationList: Authorization.ListSigned
// Typed -> RPC (e.g. for `eth_sendTransaction` params).
// @log: [{ address: '0x...', chainId: '0x1', nonce: '0x28', r: '0x...', s: '0x...', yParity: '0x1' }]
const authorizationList_rpc = Authorization.toRpcList(authorizationList)
// RPC -> typed (e.g. from `eth_getTransactionByHash` results).
const authorizationList_typed = Authorization.fromRpcList(authorizationList_rpc)
// @log: [{ address: '0x...', chainId: 1, nonce: 40n, r: '0x...', s: '0x...', yParity: 1 }]
```
## Best Practices
### Mind the Authority's Nonce
An authorization is only valid while its `nonce` equals the authority's account nonce at
execution. When the authority sends its own delegation transaction, the transaction nonce is
consumed first — sign the authorization with the account nonce **plus one**.
### Scope Delegations by Chain
A `chainId` of `0` makes the authorization valid on every chain. Prefer an explicit chain ID
unless a cross-chain delegation is exactly what you intend.
### Revoke by Delegating to the Zero Address
Delegations persist until replaced. To clear an account's code, sign a new authorization whose
`address` is `0x0000000000000000000000000000000000000000`.
## See More
# Estimate Fees & Access Lists
## Overview
The [`Fee`](/api/Fee) module converts `eth_feeHistory` payloads and provides the fee math for
EIP-1559 transactions; [`AccessList`](/api/AccessList) converts access lists between their
object and serialized tuple forms. Both operate on plain data — pair them with an
[`RpcTransport`](/api/RpcTransport) when values come from a node.
## Recipes
### Compute the Effective Gas Price
Use [`Fee.effectiveGasPrice`](/api/Fee/effectiveGasPrice) to determine what an EIP-1559
transaction actually pays per gas:
`min(maxFeePerGas, baseFeePerGas + maxPriorityFeePerGas)`.
```ts twoslash
import { Fee, Value } from 'ox'
const effectiveGasPrice = Fee.effectiveGasPrice({
baseFeePerGas: Value.fromGwei('20'),
maxFeePerGas: Value.fromGwei('30'),
maxPriorityFeePerGas: Value.fromGwei('2'),
})
// @log: 22000000000n (22 gwei = base fee + tip, under the 30 gwei cap)
```
`maxFeePerGas` is a cap, not a price — the difference between the cap and the effective price
is refunded to the sender.
### Estimate `maxFeePerGas` from Fee History
Fetch recent blocks with `eth_feeHistory`, convert the payload with
[`Fee.fromHistoryRpc`](/api/Fee/fromHistoryRpc), then derive a cap with
[`Fee.estimateMaxFeePerGas`](/api/Fee/estimateMaxFeePerGas). The default multiplier doubles the
base fee for headroom against base-fee bumps.
```ts twoslash
import { Fee, RpcTransport, Value } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
// Fetch the last 5 blocks with the 20th-percentile priority fee.
const history = Fee.fromHistoryRpc(
await transport.request({
method: 'eth_feeHistory', // [!code hl]
params: ['0x5', 'latest', [20]],
}),
)
// `baseFeePerGas` includes the *next* block's base fee as its last element.
const baseFeePerGas = history.baseFeePerGas[history.baseFeePerGas.length - 1]!
// Tip at the sampled percentile of the most recent block.
const rewards = history.reward ?? []
const maxPriorityFeePerGas =
rewards[rewards.length - 1]?.[0] ?? Value.fromGwei('1')
const maxFeePerGas = Fee.estimateMaxFeePerGas({
baseFeePerGas,
maxPriorityFeePerGas,
})
// @log: baseFeePerGas * 2n + maxPriorityFeePerGas
```
Tune the headroom with `multiplierNumerator`/`multiplierDenominator` (e.g. `3n`/`2n` for 1.5x).
### Build & Serialize Access Lists
Attach an access list of addresses and storage keys directly to an envelope — `serialize`
converts it to tuple form automatically. Use
[`AccessList.toTupleList`](/api/AccessList/toTupleList) and
[`AccessList.fromTupleList`](/api/AccessList/fromTupleList) when working at the RLP boundary
yourself.
```ts twoslash
import { AccessList, TxEnvelopeEip1559, Value } from 'ox'
const envelope = TxEnvelopeEip1559.from({
// [!code hl:start]
accessList: [
{
address: '0x1e0049783f008a0085193e00003d00cd54003c71',
storageKeys: [
'0x0000000000000000000000000000000000000000000000000000000000000001',
],
},
],
// [!code hl:end]
chainId: 1,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
})
// Object form <-> serialized tuple form.
// @log: [['0x1e0049783f008a0085193e00003d00cd54003c71', ['0x0000...0001']]]
const tuples = AccessList.toTupleList(envelope.accessList)
const accessList = AccessList.fromTupleList(tuples)
```
Both directions validate address shape and enforce 32-byte storage keys, throwing
`AccessList.InvalidStorageKeySizeError` on malformed input.
## Best Practices
### Give the Base Fee Headroom
The base fee can rise 12.5% per block, and a transaction may not be included immediately. The
2x default multiplier in `Fee.estimateMaxFeePerGas` absorbs roughly six consecutive full
blocks; lower it only when inclusion time is not critical.
### Access Lists Only Pay Off When Used
Each listed address costs 2,400 gas and each storage key 1,900 gas up front. The discount only
nets out if the transaction actually touches the listed slots — measure with real workloads
before shipping EIP-2930-style lists.
## See More
# Parse & Inspect Transactions
## Overview
The generic [`TransactionEnvelope`](/api/TransactionEnvelope) module deserializes any raw
transaction, inferring the envelope type from its serialized prefix.
[`Transaction`](/api/Transaction), [`TransactionReceipt`](/api/TransactionReceipt), and
[`TransactionRequest`](/api/TransactionRequest) convert the hex-quantity payloads that JSON-RPC
returns into typed objects with `bigint` numerics — and back.
## Recipes
### Deserialize a Raw Transaction
Use [`TransactionEnvelope.deserialize`](/api/TransactionEnvelope/deserialize) on any raw
transaction — from a mempool feed, `eth_getRawTransactionByHash`, or a signing service — and
get back a typed envelope.
```ts twoslash
import { TransactionEnvelope } from 'ox'
const envelope = TransactionEnvelope.deserialize(
'0x02f8730145843b9aca008502540be4008252089470997970c51812dc3a010c7d01b50e0d17dc79c88814d1120d7b16000080c080a098ebfabbfbe83dfcdc039bd68cce49cb55bb3d32e58f5caef200d3cb6e10351ca07b39f98ad5f89675a2e5014331283c79f3744e857681a03f445a802023297de9',
)
// @log: {
// @log: chainId: 1,
// @log: gas: 21000n,
// @log: maxFeePerGas: 10000000000n,
// @log: maxPriorityFeePerGas: 1000000000n,
// @log: nonce: 69n,
// @log: to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
// @log: type: 'eip1559',
// @log: value: 1500000000000000000n,
// @log: r: '0x...', s: '0x...', yParity: 0,
// @log: }
```
Use [`TransactionEnvelope.validate`](/api/TransactionEnvelope/validate) first when the input is
untrusted and a `boolean` is preferable to a thrown error.
### Recover the Sender Address
Extract the signature from a signed envelope, then recover the signer of the envelope's sign
payload with [`Secp256k1.recoverAddress`](/api/Secp256k1/recoverAddress).
```ts twoslash
import { Secp256k1, Signature, TransactionEnvelope } from 'ox'
const envelope = TransactionEnvelope.deserialize(
'0x02f8730145843b9aca008502540be4008252089470997970c51812dc3a010c7d01b50e0d17dc79c88814d1120d7b16000080c080a098ebfabbfbe83dfcdc039bd68cce49cb55bb3d32e58f5caef200d3cb6e10351ca07b39f98ad5f89675a2e5014331283c79f3744e857681a03f445a802023297de9',
)
const signature = Signature.extract(envelope)
if (!signature) throw new Error('transaction is unsigned')
const sender = Secp256k1.recoverAddress({
payload: TransactionEnvelope.getSignPayload(envelope), // [!code hl]
signature,
})
// @log: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8'
```
### Convert RPC Transactions & Receipts
Pipe `eth_getTransactionByHash` and `eth_getTransactionReceipt` results through
[`Transaction.fromRpc`](/api/Transaction/fromRpc) and
[`TransactionReceipt.fromRpc`](/api/TransactionReceipt/fromRpc) to get typed objects — hex
quantities become `bigint`/`number`, `type` becomes `'eip1559'`-style strings, and `status`
becomes `'success' | 'reverted'`.
```ts twoslash
import { RpcTransport, Transaction, TransactionReceipt } from 'ox'
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const hash =
'0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0'
const transaction = await transport
.request({ method: 'eth_getTransactionByHash', params: [hash] })
// @log: { ..., gas: 278365n, type: 'eip1559', value: 700000000000000000n }
.then(Transaction.fromRpc) // [!code hl]
const receipt = await transport
.request({ method: 'eth_getTransactionReceipt', params: [hash] })
.then(TransactionReceipt.fromRpc) // [!code hl]
// @log: { ..., gasUsed: 175034n, status: 'success', type: 'eip1559' }
```
Both converters pass `null` through, so missing transactions stay `null` rather than throwing.
### Prepare a Transaction Request
Flatten an envelope into a [`TransactionRequest`](/api/TransactionRequest) with
[`TransactionEnvelope.toTransactionRequest`](/api/TransactionEnvelope/toTransactionRequest),
then serialize it to RPC form for methods like `eth_estimateGas`, `eth_call`, or
`eth_sendTransaction`.
```ts twoslash
import {
RpcTransport,
TransactionEnvelope,
TransactionRequest,
Value,
} from 'ox'
const envelope = TransactionEnvelope.from({
chainId: 1,
maxFeePerGas: Value.fromGwei('10'),
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('1.5'),
})
const request = TransactionRequest.toRpc(
TransactionEnvelope.toTransactionRequest(envelope), // [!code hl]
)
const transport = RpcTransport.fromHttp('https://1.rpc.thirdweb.com')
const gas = await transport.request({
method: 'eth_estimateGas',
params: [request],
})
// @log: '0x5208'
```
The reverse direction works too: normalize wallet input with
[`TransactionRequest.fromRpc`](/api/TransactionRequest/fromRpc), then promote it to a signable
envelope with [`TransactionRequest.toEnvelope`](/api/TransactionRequest/toEnvelope).
## Best Practices
### Validate Untrusted Payloads Before Use
Raw transactions from user input or third-party feeds may be truncated or carry an unknown type
prefix. Gate on `TransactionEnvelope.validate` (or catch
`TransactionEnvelope.InvalidSerializedError`) before acting on the decoded fields.
### Convert at the RPC Boundary Once
JSON-RPC encodes every quantity as hex strings. Run `fromRpc` converters immediately after each
request — and `toRpc` immediately before — so the rest of the application only ever handles
typed `bigint` values.
## See More
# Send Blob Transactions (EIP-4844)
## Overview
[EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) transactions carry data in blobs that are
committed to with KZG proofs and pruned after the availability window. The
[`Blobs`](/api/Blobs) module packs data into blobs and computes their commitments and proofs;
[`BlobCells`](/api/BlobCells) handles PeerDAS ([EIP-7594](https://eips.ethereum.org/EIPS/eip-7594))
cells; [`TxEnvelopeEip4844`](/api/TxEnvelopeEip4844) builds the type-3 envelope. KZG operations
use Ox's opt-in WASM implementation ([`Kzg`](/wasm/crypto/Kzg)) — see the
[WASM KZG guide](/guides/runtime/kzg) for setup, memory, and disposal details.
## Recipes
### Turn Data into Blobs
Use [`Blobs.from`](/api/Blobs/from) to pack arbitrary data into 131,072-byte blobs, and
[`Blobs.toHex`](/api/Blobs/toHex) to recover the original data. No KZG implementation is needed
for this step.
```ts twoslash
import { Blobs } from 'ox'
const blobs = Blobs.from('0xdeadbeef') // [!code hl]
// @log: ['0x00de00adbe...'] (one 131,072-byte blob)
const data = Blobs.toHex(blobs)
// @log: '0xdeadbeef'
```
A single transaction can carry up to six blobs (761,855 bytes of payload after field-element
encoding); `Blobs.from` throws `Blobs.BlobSizeTooLargeError` beyond that.
### Compute Commitments & Proofs
Create a KZG instance from the Ethereum trusted setup, then derive one commitment per blob with
[`Blobs.toCommitments`](/api/Blobs/toCommitments), 128 cell proofs per blob with
[`Blobs.toCellProofs`](/api/Blobs/toCellProofs), and the versioned hashes that anchor the
envelope with
[`Blobs.commitmentsToVersionedHashes`](/api/Blobs/commitmentsToVersionedHashes).
```ts twoslash
import { Blobs } from 'ox'
import { Setups } from 'ox/trusted-setups'
import { Kzg } from 'ox/wasm'
const kzg = await Kzg.create({ trustedSetup: Setups.mainnet })
const blobs = Blobs.from('0xdeadbeef')
const commitments = Blobs.toCommitments(blobs, { kzg }) // [!code hl]
// @log: 128 cell proofs per blob (EIP-7594)
const cellProofs = Blobs.toCellProofs(blobs, { kzg }) // [!code hl]
const blobVersionedHashes = Blobs.commitmentsToVersionedHashes(commitments)
// @log: ['0x01a24709d3997e8b217fe5460aef10ee515513ceba0362bf2d02a3ba73d7cb09']
kzg.dispose()
```
Only the versioned hashes go into the signed envelope; blobs, commitments, and cell proofs
travel alongside it as sidecars.
### Build a 4844 Envelope with Sidecars
Construct the envelope from the versioned hashes, sign it, then serialize with `sidecars` to
produce the 5-element `PooledTransactions` network wrapper that `eth_sendRawTransaction`
expects.
```ts twoslash
import { Blobs, Secp256k1, TxEnvelopeEip4844, Value } from 'ox'
import { Setups } from 'ox/trusted-setups'
import { Kzg } from 'ox/wasm'
const kzg = await Kzg.create({ trustedSetup: Setups.mainnet })
const blobs = Blobs.from('0xdeadbeef')
const envelope = TxEnvelopeEip4844.from({
blobVersionedHashes: Blobs.toVersionedHashes(blobs, { kzg }), // [!code hl]
chainId: 1,
gas: 21_000n,
maxFeePerBlobGas: Value.fromGwei('3'),
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
nonce: 0n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
})
const signature = Secp256k1.sign({
payload: TxEnvelopeEip4844.getSignPayload(envelope),
privateKey: '0x...',
})
// Serialize into the PeerDAS network wrapper, ready for `eth_sendRawTransaction`.
const serialized = TxEnvelopeEip4844.serialize(envelope, {
signature,
sidecars: {
// [!code hl:start]
blobs,
commitments: Blobs.toCommitments(blobs, { kzg }),
cellProofs: Blobs.toCellProofs(blobs, { kzg }),
// [!code hl:end]
},
})
kzg.dispose()
```
[`TxEnvelopeEip4844.hash`](/api/TxEnvelopeEip4844/hash) always operates on the bare envelope —
the transaction hash never includes the sidecar wrapper. See
[Build, Sign & Send](/guides/transactions/build-sign-send) for broadcasting.
### Verify Blob Cells (PeerDAS)
Split a blob into its 128 extended cells with
[`BlobCells.fromBlob`](/api/BlobCells/fromBlob), then check any subset of cells against the
blob's commitment with [`BlobCells.verify`](/api/BlobCells/verify).
```ts twoslash
import { BlobCells, Blobs } from 'ox'
import { Setups } from 'ox/trusted-setups'
import { Kzg } from 'ox/wasm'
const kzg = await Kzg.create({ trustedSetup: Setups.mainnet })
const [blob] = Blobs.from('0xdeadbeef')
const [commitment] = Blobs.toCommitments([blob], { kzg })
const { cells, proofs } = BlobCells.fromBlob(blob, { kzg }) // [!code hl]
// @log: 128 cells (2,048 bytes each), 128 proofs
const valid = BlobCells.verify({
cells,
cellIndices: cells.map((_, i) => i),
commitments: cells.map(() => commitment),
proofs,
kzg,
})
// @log: true
kzg.dispose()
```
Any 64 of the 128 cells are enough to reconstruct the rest with
[`BlobCells.recover`](/api/BlobCells/recover).
## Best Practices
### Reuse and Dispose KZG Instances
Each `Kzg.create` call owns separate WASM memory (8 MiB and up). Create one instance per worker,
reuse it across operations, and call `dispose` when done — see the
[WASM KZG guide](/guides/runtime/kzg) for ownership details.
### Blobs Are Not Permanent Storage
Blob data is pruned after the availability window and is never readable from the EVM — only the
versioned hashes remain on-chain. Persist the underlying data elsewhere if it must stay
retrievable.
### Budget Blob Gas Separately
`maxFeePerBlobGas` prices a fee market independent of execution gas. A transaction can be
priced competitively on one market and stall on the other, so derive both caps before signing.
## See More
# WebAuthn & Passkeys
## Overview
The [Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)
exposes P256 credentials held by authenticators such as [Passkeys](https://passkeys.dev) and
[YubiKeys](https://en.wikipedia.org/wiki/YubiKey), so users can sign transactions and arbitrary
payloads without handling a raw private key. Combined with Account Abstraction, Smart Contract
Accounts can verify these signatures onchain via mechanisms such as
[ERC-1271](https://eips.ethereum.org/EIPS/eip-1271).
The [`WebAuthn`](/api/WebAuthn) module covers the credential lifecycle end-to-end, while the
[`ox/webauthn` entrypoint](/webauthn) adds granular registration, authentication, and server-side
verification utilities.
```ts twoslash
import { WebAuthn } from 'ox'
// 1. Register a credential (ie. passkey).
const credential = await WebAuthn.createCredential({ name: 'Example' })
// 2. Sign a challenge with the credential.
const { metadata, signature } = await WebAuthn.sign({
challenge: '0xdeadbeef',
credentialId: credential.id,
})
// 3. Verify the signature.
const verified = WebAuthn.verify({
challenge: '0xdeadbeef',
metadata,
publicKey: credential.publicKey,
signature,
})
// @log: true
```
## Guides
# Derive Secrets with PRF
## Overview
The WebAuthn [PRF extension](https://w3c.github.io/webauthn/#prf-extension) evaluates a
pseudo-random function bound to a credential, returning a 32-byte output for a given input. The
same credential and input always reproduce the same output, which makes it usable as deterministic
key material.
The [`Prf`](/api/Prf) module builds PRF inputs ("tags"), [`WebAuthn`](/api/WebAuthn) requests
outputs from a credential, and [`Secp256k1`](/api/Secp256k1), [`Ed25519`](/api/Ed25519),
[`MlDsa44`](/api/MlDsa44), and [`AesGcm`](/api/AesGcm) each expose a `fromPrf` function that
derives an independent key from the same output using a fixed derivation domain.
:::warning
Treat PRF outputs and derived keys as secrets. Do not serialize or send the raw WebAuthn
credential or response.
PRF-derived keys are software keys. Code on any origin allowed to use the same RP ID can request
the same output after user verification.
:::
## Recipes
### Configure a PRF Tag & Request Outputs
Encode an application-owned PRF input with [`Prf.tag`](/api/Prf/tag) and pass it when creating or
requesting a credential. Using the same tag with the same credential reproduces the output.
```ts twoslash
import { Prf, WebAuthn } from 'ox'
// Register a credential with PRF evaluation enabled.
const credential = await WebAuthn.createCredential({
name: 'Example',
prf: Prf.tag('account.1'), // [!code hl]
})
// Later — reproduce the same 32-byte output from the stored credential.
const { prf } = await WebAuthn.getCredential({
credentialId: credential.id,
prf: Prf.tag('account.1'), // [!code hl]
})
```
Passing `prf: true` instead of a tag uses the stable default input `ox.webauthn.prf.v1`. Tags are
public identifiers — store them alongside the credential metadata, not as secrets.
### Sign Ethereum Transactions with a Passkey-Derived Key
Derive a secp256k1 private key with [`Secp256k1.fromPrf`](/api/Secp256k1/fromPrf) and use it like
any other Ethereum key — here, to sign an EIP-1559 transaction envelope.
```ts twoslash
import { Secp256k1, TxEnvelopeEip1559, Value, WebAuthn } from 'ox'
const { prf } = await WebAuthn.getCredential({
credentialId: 'oZ48...',
prf: true,
})
const privateKey = Secp256k1.fromPrf(prf) // [!code hl]
const envelope = TxEnvelopeEip1559.from({
chainId: 1,
gas: 21_000n,
maxFeePerGas: Value.fromGwei('10'),
maxPriorityFeePerGas: Value.fromGwei('1'),
nonce: 0n,
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: Value.fromEther('0.1'),
})
const signature = Secp256k1.sign({
payload: TxEnvelopeEip1559.getSignPayload(envelope),
privateKey,
})
const serialized = TxEnvelopeEip1559.serialize(envelope, { signature })
```
Broadcast `serialized` with `eth_sendRawTransaction` — see
[Build, Sign & Send](/guides/transactions/build-sign-send).
### Derive an Ed25519 Key
Derive an Ed25519 private key with [`Ed25519.fromPrf`](/api/Ed25519/fromPrf) for off-chain
signing (session tokens, sync payloads, non-EVM chains).
```ts twoslash
import { Ed25519, WebAuthn } from 'ox'
const { prf } = await WebAuthn.getCredential({
credentialId: 'oZ48...',
prf: true,
})
const privateKey = Ed25519.fromPrf(prf) // [!code hl]
const publicKey = Ed25519.getPublicKey({ privateKey })
const signature = Ed25519.sign({
payload: '0xdeadbeef',
privateKey,
})
```
### Derive a Post-Quantum Key
Derive an ML-DSA-44 (FIPS 204) private key with [`MlDsa44.fromPrf`](/api/MlDsa44/fromPrf) to sign
with a post-quantum scheme.
```ts twoslash
import { MlDsa44, WebAuthn } from 'ox'
const { prf } = await WebAuthn.getCredential({
credentialId: 'oZ48...',
prf: true,
})
const privateKey = MlDsa44.fromPrf(prf) // [!code hl]
const publicKey = MlDsa44.getPublicKey({ privateKey })
const signature = MlDsa44.sign({
payload: '0xdeadbeef',
privateKey,
})
const verified = MlDsa44.verify({
payload: '0xdeadbeef',
publicKey,
signature,
})
// @log: true
```
### Encrypt User Data
Derive an AES-256-GCM key with [`AesGcm.fromPrf`](/api/AesGcm/fromPrf) to encrypt data that only
the passkey holder can decrypt. Unlike the signing variants, `AesGcm.fromPrf` is **async** — it
returns a non-extractable Web Crypto `CryptoKey`.
```ts twoslash
import { AesGcm, Hex, WebAuthn } from 'ox'
const { prf } = await WebAuthn.getCredential({
credentialId: 'oZ48...',
prf: true,
})
const key = await AesGcm.fromPrf(prf) // [!code hl]
const secret = Hex.fromString('i am a secret message')
const encrypted = await AesGcm.encrypt(secret, key)
const decrypted = await AesGcm.decrypt(encrypted, key)
// @log: Hex.fromString('i am a secret message')
```
## Best Practices
### Namespace Tags per Purpose
Use one tag per account or feature (e.g. `account.1`, `backup.v2`) so keys stay independent and
rotatable. Each `fromPrf` module already applies its own derivation domain, so the same output
safely feeds different algorithms.
### Re-Derive Instead of Persisting
PRF outputs are reproducible on demand after user verification. Re-derive keys when needed rather
than storing private keys, and keep derived material out of logs, storage, and analytics.
### Plan for Credential Loss
A PRF output is bound to a single credential — losing the passkey loses every key derived from it.
Register a backup credential or escrow encrypted recovery material before deriving long-lived keys.
## See More
# Register & Authenticate Credentials
## Overview
A WebAuthn credential is created once (registration) and asserted many times (authentication).
The [`ox/webauthn` entrypoint](/webauthn) mirrors this split:
[`Registration`](/webauthn/webauthn/Registration) creates and verifies credentials,
[`Authentication`](/webauthn/webauthn/Authentication) requests and verifies assertions, and
[`Credential`](/webauthn/webauthn/Credential) serializes credentials for transport and storage.
[`Authenticator`](/webauthn/webauthn/Authenticator) constructs raw authenticator payloads (mostly for
testing), and [`CoseKey`](/api/CoseKey) converts the COSE-encoded public keys found in attestation
objects.
## Recipes
### Register a Credential
Create a credential with a server-issued challenge, then serialize it so it can be sent to the
server for verification and storage.
```ts twoslash
import { Credential, Registration } from 'ox/webauthn'
// Challenge generated and stored by the server for this registration.
const challenge = '0x69abb4b5a0de4bc62a2a201f8d25bae9'
const credential = await Registration.create({
challenge,
name: 'Example', // [!code hl]
})
// Serialize for transmission — `Credential.serialize` converts binary
// fields to base64url/hex strings.
const serialized = Credential.serialize(credential)
const body = JSON.stringify(serialized)
```
The returned `credential.id` and `credential.publicKey` identify the credential in later
ceremonies — persist them client-side if you plan to verify locally.
### Authenticate an Existing Credential
Request an assertion for a known credential ID with a fresh server-issued challenge, then check
it against the public key stored at registration.
```ts twoslash
import { PublicKey } from 'ox'
import { Authentication } from 'ox/webauthn'
// Public key stored by the server at registration.
declare const publicKey: PublicKey.PublicKey
// Challenge issued by the server for this login attempt.
const challenge = '0x1e0c4b8b5f14ec863da1e7f0d3a58b8a'
const response = await Authentication.sign({
challenge,
credentialId: 'oZ48...', // [!code hl]
})
const valid = Authentication.verify({
challenge,
metadata: response.metadata,
origin: 'https://example.com',
publicKey,
rpId: 'example.com',
signature: response.signature,
})
// @log: true
```
To verify on a server, send the assertion with
[`Authentication.serializeResponse`](/webauthn/webauthn/Authentication) and rehydrate it with
`Authentication.deserializeResponse` before calling `verify`.
### Verify Registration on the Server
Deserialize the credential received from the client and validate the whole registration ceremony —
challenge, origin, RP ID, authenticator flags, and attestation — with
[`Registration.verify`](/webauthn/webauthn/Registration).
```ts twoslash
import { Credential, Registration } from 'ox/webauthn'
// Request body received from the client.
declare const body: string
const credential = Credential.deserialize(JSON.parse(body))
const result = Registration.verify({
credential,
challenge: '0x69abb4b5a0de4bc62a2a201f8d25bae9', // [!code hl]
origin: 'https://example.com',
rpId: 'example.com',
})
// @log: {
// @log: credential: {
// @log: id: 'oZ48...',
// @log: publicKey: { prefix: 4, x: 51421...5123n, y: 12345...6789n },
// @log: },
// @log: counter: 0,
// @log: userVerified: true,
// @log: }
```
Store `result.credential.id`, `result.credential.publicKey`, and `result.counter` — they are the
inputs for verifying future authentication ceremonies.
## Best Practices
### Issue Challenges Server-Side
Generate a random, single-use challenge on the server for every ceremony and reject responses
whose challenge does not match. A client-chosen challenge defeats replay protection.
### Pin Origin and RP ID
Always pass `origin` and `rpId` when verifying on a server. They bind the ceremony to your site
and stop credentials phished on look-alike origins from validating.
### Never Ship the Raw Credential
Serialize with `Credential.serialize` rather than the native `toJSON()` — native output can
include client extension results (such as PRF outputs), which are secrets.
## See More
# Sign & Verify with Passkeys
## Overview
Once a credential is registered, it can sign arbitrary challenges — transaction hashes, message
digests, or login nonces. The [`WebAuthn`](/api/WebAuthn) module signs with
[`WebAuthn.sign`](/api/WebAuthn/sign) and verifies with [`WebAuthn.verify`](/api/WebAuthn/verify),
while [`PublicKey`](/api/PublicKey) serializes the credential's P256 public key for storage.
## Recipes
### Sign a Payload
Hash the payload into a 32-byte challenge and sign it with a stored credential. The response
contains the `signature` and the authenticator `metadata` required to verify it.
```ts twoslash
import { Hash, Hex, WebAuthn } from 'ox'
const credential = await WebAuthn.createCredential({ name: 'Example' })
const challenge = Hash.keccak256(Hex.fromString('hello world'))
const { metadata, signature } = await WebAuthn.sign({
challenge, // [!code hl]
credentialId: credential.id,
})
```
Omitting `credentialId` prompts the user to pick any credential previously registered for the
origin.
### Extract the Public Key
Serialize the credential's public key with [`PublicKey.toHex`](/api/PublicKey/toHex) so it can be
persisted (or registered with an onchain verifier), and rehydrate it when verifying.
```ts twoslash
import { PublicKey, WebAuthn } from 'ox'
const credential = await WebAuthn.createCredential({ name: 'Example' })
const publicKey = PublicKey.toHex(credential.publicKey) // [!code hl]
// @log: '0x04ab891400140fc4f8e941ce0ff90e419de9470acaca613bbd717a4775435031a7...'
// Rehydrate the stored key when verifying.
const restored = PublicKey.fromHex(publicKey)
```
### Verify a Signature
Verify the signature against the challenge, the credential's public key, and the authenticator
metadata returned by `WebAuthn.sign`.
```ts twoslash
import { WebAuthn } from 'ox'
const credential = await WebAuthn.createCredential({ name: 'Example' })
const { metadata, signature } = await WebAuthn.sign({
challenge: '0xdeadbeef',
credentialId: credential.id,
})
const verified = WebAuthn.verify({
challenge: '0xdeadbeef',
metadata,
publicKey: credential.publicKey,
signature,
})
// @log: true
```
When verifying on a server, also pass `origin` and `rpId` so the client data and relying party
binding are validated — see
[Register & Authenticate Credentials](/guides/webauthn/credentials).
## Best Practices
### Bind Challenges to Content
Derive the challenge from what is actually being authorized — e.g. `Hash.keccak256` of the
serialized transaction or message — so a signature cannot be replayed for a different action.
### Keep the Metadata with the Signature
`metadata` (authenticator data + client data JSON) is part of the signed material. Store and
transmit it alongside the signature; verification is impossible without it.
### Verify Onchain via ERC-1271
Smart Contract Accounts can validate WebAuthn P256 signatures with
[ERC-1271](https://eips.ethereum.org/EIPS/eip-1271)-style verifiers. Use
[`WebAuthn.getSignPayload`](/webauthn/webauthn/Authentication/getSignPayload) when a contract expects the raw P256
digest instead of the WebAuthn envelope.
## See More
# API Reference
| Module | Description |
| --- | --- |
| **ABI** | |
| [Abi](/api/Abi) | Utilities & types for working with [Application Binary Interfaces (ABIs)](https://docs.soliditylang.org/en/latest/abi-spec.html) |
| [AbiConstructor](/api/AbiConstructor) | Utilities & types for working with [Constructors](https://docs.soliditylang.org/en/latest/abi-spec.html#json) on ABIs. |
| [AbiError](/api/AbiError) | Utilities & types for working with [Errors](https://docs.soliditylang.org/en/latest/abi-spec.html#json) on ABIs. |
| [AbiEvent](/api/AbiEvent) | Utilities & types for working with [Events](https://docs.soliditylang.org/en/latest/abi-spec.html#json) on ABIs. |
| [AbiFunction](/api/AbiFunction) | Utilities & types for working with [Functions](https://docs.soliditylang.org/en/latest/abi-spec.html#json) on ABIs. |
| [AbiItem](/api/AbiItem) | Utilities & types for working with [ABI Items](https://docs.soliditylang.org/en/latest/abi-spec.html#json) |
| [AbiParameter](/api/AbiParameter) | Utilities & types for working with a single [ABI Parameter](https://docs.soliditylang.org/en/latest/abi-spec.html#types). |
| [AbiParameters](/api/AbiParameters) | Utilities & types for encoding, decoding, and working with [ABI Parameters](https://docs.soliditylang.org/en/latest/abi-spec.html#types) |
| **Addresses** | |
| [Address](/api/Address) | Utility functions for working with Ethereum addresses. |
| [ContractAddress](/api/ContractAddress) | Utility functions for computing Contract Addresses. |
| **Authorization (EIP-7702)** | |
| [Authorization](/api/Authorization) | Utility functions for working with [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization lists & tuples. |
| **Binary State Tree (EIP-7864)** | |
| [BinaryStateTree](/api/BinaryStateTree) | Utility functions for working with [EIP-7864](https://eips.ethereum.org/EIPS/eip-7864) Binary State Trees. |
| **Blobs (EIP-4844)** | |
| [Blobs](/api/Blobs) | Utility functions for working with [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) Blobs. |
| [Kzg](/api/Kzg) | Utility functions for working with KZG Commitments. |
| **Blobs (EIP-7594)** | |
| [BlobCells](/api/BlobCells) | Cell-level helpers for [PeerDAS (EIP-7594)](https://eips.ethereum.org/EIPS/eip-7594): deriving the 128 cells and cell KZG proofs of an extended blob, and verifying cell proofs against blob commitments. |
| **Crypto** | |
| [AesGcm](/api/AesGcm) | Utilities & types for working with AES-GCM encryption. Internally uses the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API). |
| [Bls](/api/Bls) | Utility functions for [BLS12-381](https://hackmd.io/@benjaminion/bls12-381) cryptography. |
| [BlsPoint](/api/BlsPoint) | Utility functions for working with BLS12-381 points. |
| [CoseKey](/api/CoseKey) | Utility functions for converting between COSE\_Key and P256 public keys. |
| [Ed25519](/api/Ed25519) | Utilities for working with Ed25519 signatures and key pairs. |
| [Engine](/api/Engine) | Functions for delegating ox's cryptography to a different implementation. |
| [Hash](/api/Hash) | Utility functions for hashing (keccak256, sha256, etc). |
| [HdKey](/api/HdKey) | Utility functions for generating and working with [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) HD Wallets. |
| [Keystore](/api/Keystore) | Utilities & types for working with [Keystores](https://ethereum.org/en/developers/docs/data-structures-and-encoding/web3-secret-storage). |
| [Mnemonic](/api/Mnemonic) | Utility functions for generating and working with [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonics. |
| [P256](/api/P256) | Utility functions for [NIST P256](https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-adalier-mehmet.pdf) ECDSA cryptography. |
| [Prf](/api/Prf) | Utilities for constructing credential-bound PRF configurations. |
| [PublicKey](/api/PublicKey) | Utility functions for working with ECDSA public keys. |
| [Secp256k1](/api/Secp256k1) | Utility functions for [secp256k1](https://www.secg.org/sec2-v2.pdf) ECDSA cryptography. |
| [Signature](/api/Signature) | Utility functions for working with ECDSA signatures. |
| [WebAuthn](/api/WebAuthn) | Utilities for WebAuthn credentials, credential-bound PRFs, and [NIST P256](https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-adalier-mehmet.pdf) signatures. |
| [WebCryptoP256](/api/WebCryptoP256) | Utility functions for [NIST P256](https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-adalier-mehmet.pdf) ECDSA cryptography using the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) |
| [X25519](/api/X25519) | Utilities for working with X25519 elliptic curve Diffie-Hellman key agreement. |
| **Data** | |
| [Base32](/api/Base32) | Utility functions for working with Base32 values using the [BIP-173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki) bech32 alphabet. |
| [Base58](/api/Base58) | Utility functions for working with [Base58](https://digitalbazaar.github.io/base58-spec/) values. |
| [Base64](/api/Base64) | Utility functions for working with [RFC-4648](https://datatracker.ietf.org/doc/html/rfc4648) Base64. |
| [Bech32m](/api/Bech32m) | Utility functions for [BIP-350](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki) bech32m encoding and decoding. |
| [Bytes](/api/Bytes) | A set of Ethereum-related utility functions for working with [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) instances. |
| [Cbor](/api/Cbor) | Functions for encoding and decoding CBOR (Concise Binary Object Representation) data. |
| [CompactSize](/api/CompactSize) | Utility functions for [Bitcoin's CompactSize](https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer) variable-length integer encoding. |
| [Hex](/api/Hex) | A set of Ethereum-related utility functions for working with hexadecimal string values (e.g. `"0xdeadbeef"`). |
| [Rlp](/api/Rlp) | Utility functions for encoding and decoding [Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/) structures. |
| [Value](/api/Value) | Utility functions for displaying and parsing Ethereum Values as defined under **2.1. Value** in the [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) |
| **ENS** | |
| [Ens](/api/Ens) | Utility functions for working with ENS names. |
| **Execution Spec** | |
| [AccessList](/api/AccessList) | Utilities & types for working with Access Lists as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/4140e528360fea53c34a766d86a000c6c039100e/src/schemas/transaction.yaml#L73) |
| [AccountProof](/api/AccountProof) | Utilities & types for working with Account Proofs as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/state.yaml) |
| [Block](/api/Block) | Utilities & types for working with Blocks as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/block.yaml) |
| [BlockOverrides](/api/BlockOverrides) | Utilities & types for working with **Block Overrides**. |
| [Bloom](/api/Bloom) | Utility functions for working with Bloom Filters as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/block.yaml) |
| [Fee](/api/Fee) | Utility types for working with Ethereum transaction fees and fee history. |
| [Filter](/api/Filter) | Utilities & types for working with Filters as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/filter.yaml) |
| [Log](/api/Log) | Utilities & types for working with Logs as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/receipt.yaml) |
| [StateOverrides](/api/StateOverrides) | Utilities & types for working with **State Overrides**. |
| [Transaction](/api/Transaction) | Utilities & types for working with **Transactions** as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/transaction.yaml) |
| [TransactionReceipt](/api/TransactionReceipt) | Utilities & types for working with **Transaction Receipts** as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/receipt.yaml) |
| [TransactionRequest](/api/TransactionRequest) | Utilities & types for working with **Transaction Requests** as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/4aca1d7a3e5aab24c8f6437131289ad386944eaa/src/schemas/transaction.yaml#L358-L423) |
| [Withdrawal](/api/Withdrawal) | Utilities & types for working with Withdrawals as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/withdrawal.yaml) |
| **JSON** | |
| [Json](/api/Json) | Utility functions for working with JSON (with support for `bigint`). |
| **JSON-RPC** | |
| [RpcRequest](/api/RpcRequest) | Utility types & functions for working with [JSON-RPC 2.0 Requests](https://www.jsonrpc.org/specification#request_object) and Ethereum JSON-RPC methods as defined on the [Ethereum API specification](https://github.com/ethereum/execution-apis) |
| [RpcResponse](/api/RpcResponse) | Utility types & functions for working with [JSON-RPC 2.0 Responses](https://www.jsonrpc.org/specification#response_object) |
| [RpcSchema](/api/RpcSchema) | Utility types for working with Ethereum JSON-RPC namespaces & schemas. |
| [RpcTransport](/api/RpcTransport) | Utility functions for working with JSON-RPC Transports. |
| **Post Quantum** | |
| [MlDsa44](/api/MlDsa44) | Utilities for working with ML-DSA-44 signatures and key pairs, as defined in [FIPS 204](https://csrc.nist.gov/pubs/fips/204/final). |
| **Providers (EIP-1193)** | |
| [Provider](/api/Provider) | Utilities & types for working with [EIP-1193 Providers](https://eips.ethereum.org/EIPS/eip-1193) |
| **Sign-In with Ethereum (EIP-4361)** | |
| [Siwe](/api/Siwe) | Utility functions for working with [EIP-4361: Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) |
| **Signed & Typed Data** | |
| [PersonalMessage](/api/PersonalMessage) | Utilities & types for working with [EIP-191 Personal Messages](https://eips.ethereum.org/EIPS/eip-191#version-0x45-e) |
| [TypedData](/api/TypedData) | Utility functions for working with [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) |
| [ValidatorData](/api/ValidatorData) | Utilities & types for working with [EIP-191 Validator Data](https://eips.ethereum.org/EIPS/eip-191#0x00) |
| **Transaction Envelopes** | |
| [TransactionEnvelope](/api/TransactionEnvelope) | Errors & Types for working with Transaction Envelopes. |
| [TxEnvelopeEip1559](/api/TxEnvelopeEip1559) | Utility functions for working with [EIP-1559 Typed Transaction Envelopes](https://eips.ethereum.org/EIPS/eip-1559) |
| [TxEnvelopeEip2930](/api/TxEnvelopeEip2930) | Utility functions for working with [EIP-2930 Typed Transaction Envelopes](https://eips.ethereum.org/EIPS/eip-2930) |
| [TxEnvelopeEip4844](/api/TxEnvelopeEip4844) | Utility functions for working with [EIP-4844 Typed Transaction Envelopes](https://eips.ethereum.org/EIPS/eip-4844) |
| [TxEnvelopeEip7702](/api/TxEnvelopeEip7702) | Utility functions for working with [EIP-7702 Typed Transaction Envelopes](https://eips.ethereum.org/EIPS/eip-7702) |
| [TxEnvelopeLegacy](/api/TxEnvelopeLegacy) | Utility functions for working with **Legacy Transaction Envelopes**. |
# API Reference
| Module | Description |
| --- | --- |
| **WebAuthn** | |
| [Authentication](/webauthn/webauthn/Authentication) | Utility functions and types for WebAuthn authentication ceremonies (signing and verification). |
| [Authenticator](/webauthn/webauthn/Authenticator) | Utility functions for constructing and parsing authenticator data and client data JSON. |
| [Credential](/webauthn/webauthn/Credential) | Utility functions and types for WebAuthn P256 credentials. |
| [Registration](/webauthn/webauthn/Registration) | Utility functions and types for WebAuthn registration ceremonies (credential creation and verification). |
# API Reference
| Module | Description |
| --- | --- |
| **ERC-4337** | |
| [EntryPoint](/ercs/erc4337/EntryPoint) | Utility functions and types for working with [ERC-4337 EntryPoints](https://eips.ethereum.org/EIPS/eip-4337). |
| [RpcSchema](/ercs/erc4337/RpcSchema) | Utility types for working with ERC-4337 JSON-RPC schemas. |
| [UserOperation](/ercs/erc4337/UserOperation) | Utility functions and types for working with [ERC-4337 User Operations](https://eips.ethereum.org/EIPS/eip-4337). |
| [UserOperationGas](/ercs/erc4337/UserOperationGas) | Utility functions and types for working with [ERC-4337 User Operation Gas](https://eips.ethereum.org/EIPS/eip-4337). |
| [UserOperationReceipt](/ercs/erc4337/UserOperationReceipt) | Utility functions and types for working with [ERC-4337 User Operation Receipts](https://eips.ethereum.org/EIPS/eip-4337). |
| **ERC-6492** | |
| [SignatureErc6492](/ercs/erc6492/SignatureErc6492) | Utility functions for working with [ERC-6492 wrapped signatures](https://eips.ethereum.org/EIPS/eip-6492#specification). |
| **ERC-7821** | |
| [Calls](/ercs/erc7821/Calls) | Utility functions for encoding and decoding [ERC-7821](https://eips.ethereum.org/EIPS/eip-7821) calls. |
| [Execute](/ercs/erc7821/Execute) | Utility functions for encoding and decoding [ERC-7821](https://eips.ethereum.org/EIPS/eip-7821) `execute` function data. |
| **ERC-8010** | |
| [SignatureErc8010](/ercs/erc8010/SignatureErc8010) | Utility functions for working with [ERC-8010 wrapped signatures](https://eips.ethereum.org/EIPS/eip-8010#specification). |
| **ERC-8021** | |
| [Attribution](/ercs/erc8021/Attribution) | Utility functions for working with [ERC-8021 Transaction Attribution](https://eip.tools/eip/8021). |
# Overview
Ox provides low-level, type-safe primitives for constructing, signing, serializing, and inspecting
Tempo protocol data. Explore the guides for common workflows, or browse the API reference for
individual modules.
## Guides
## API Reference
| Module | Description |
| --- | --- |
| **Reference** | |
| [AuthorizationTempo](/tempo/reference/AuthorizationTempo) | Utilities for Tempo-flavoured EIP-7702 authorizations. |
| [Channel](/tempo/reference/Channel) | TIP-20 channel reserve descriptor, constants, and deterministic hashing utilities. |
| [EarnShares](/tempo/reference/EarnShares) | Tempo Earn `VaultAdapter` share math: raw vault-share and venue-share conversions at the anchor rate, the dilution-correct fee-share formula, and the `minimumOutput` slippage floor. |
| [KeyAuthorization](/tempo/reference/KeyAuthorization) | Tempo key authorization utilities for provisioning and signing access keys. |
| [MultisigConfig](/tempo/reference/MultisigConfig) | Native multisig account utilities (TIP-1061). |
| [Period](/tempo/reference/Period) | Utilities for constructing period durations (in seconds) for recurring spending limits. |
| [PoolId](/tempo/reference/PoolId) | Pool ID utilities for computing pool identifiers from token pairs. |
| [ReceivePolicyReceipt](/tempo/reference/ReceivePolicyReceipt) | TIP-1028 receive-policy claim receipt utilities. |
| [RpcSchemaTempo](/tempo/reference/RpcSchemaTempo) | Union of all JSON-RPC Methods for the `tempo_` namespace. |
| [SignatureEnvelope](/tempo/reference/SignatureEnvelope) | Signature envelope utilities for secp256k1, P256, WebAuthn, and keychain signatures. |
| [Tick](/tempo/reference/Tick) | Tick-based pricing utilities for DEX price conversions. |
| [TokenRole](/tempo/reference/TokenRole) | Token role utilities for serializing role identifiers to keccak256 hashes. |
| [Transaction](/tempo/reference/Transaction) | Utilities for converting between RPC and structured transaction formats. |
| [TransactionReceipt](/tempo/reference/TransactionReceipt) | Utilities for working with Tempo transaction receipts. |
| [TransactionRequest](/tempo/reference/TransactionRequest) | Utilities for preparing RPC-formatted transaction requests. |
| [TxEnvelopeTempo](/tempo/reference/TxEnvelopeTempo) | Utilities for instantiating, serializing, and hashing Tempo transaction envelopes. |
| [VirtualAddress](/tempo/reference/VirtualAddress) | TIP-1022 virtual address encoding and parsing utilities. |
| [VirtualMaster](/tempo/reference/VirtualMaster) | TIP-1022 master registration utilities. |
| [WithdrawalSenderTag](/tempo/reference/WithdrawalSenderTag) | Utilities for deriving the sender tag that correlates a Zone withdrawal with its indexed parent-chain `WithdrawalProcessed` event. |
| [ZoneId](/tempo/reference/ZoneId) | Zone ID utilities for converting between zone IDs and zone chain IDs. |
| [ZoneRpcAuthentication](/tempo/reference/ZoneRpcAuthentication) | Zone RPC authentication token utilities for private zone RPC access. |
# API Reference
| Module | Description |
| --- | --- |
| **JSON-RPC** | |
| [z.RpcSchema](/zod/jsonrpc/RpcSchema) | z.RpcSchema schemas. |
| [z.RpcSchema.from](/zod/jsonrpc/from) | z.RpcSchema.from schemas. |
| **Schemas** | |
| [Integers](/zod/schemas/Integers) | Integer quantity schemas exported directly from `z`. |
| [z.Abi](/zod/schemas/Abi) | z.Abi schemas. |
| [z.AbiConstructor](/zod/schemas/AbiConstructor) | z.AbiConstructor schemas. |
| [z.AbiError](/zod/schemas/AbiError) | z.AbiError schemas. |
| [z.AbiEvent](/zod/schemas/AbiEvent) | z.AbiEvent schemas. |
| [z.AbiFallback](/zod/schemas/AbiFallback) | z.AbiFallback schemas. |
| [z.AbiFunction](/zod/schemas/AbiFunction) | z.AbiFunction schemas. |
| [z.AbiItem](/zod/schemas/AbiItem) | z.AbiItem schemas. |
| [z.AbiParameter](/zod/schemas/AbiParameter) | z.AbiParameter schemas. |
| [z.AbiParameters](/zod/schemas/AbiParameters) | z.AbiParameters schemas. |
| [z.AbiReceive](/zod/schemas/AbiReceive) | z.AbiReceive schemas. |
| [z.AccessList](/zod/schemas/AccessList) | z.AccessList schemas. |
| [z.AccountProof](/zod/schemas/AccountProof) | z.AccountProof schemas. |
| [z.Address](/zod/schemas/Address) | z.Address schemas. |
| [z.Authorization](/zod/schemas/Authorization) | z.Authorization schemas. |
| [z.Block](/zod/schemas/Block) | z.Block schemas. |
| [z.BlockOverrides](/zod/schemas/BlockOverrides) | z.BlockOverrides schemas. |
| [z.Bytes](/zod/schemas/Bytes) | z.Bytes schemas. |
| [z.Fee](/zod/schemas/Fee) | z.Fee schemas. |
| [z.Filter](/zod/schemas/Filter) | z.Filter schemas. |
| [z.Hash](/zod/schemas/Hash) | z.Hash schemas. |
| [z.Hex](/zod/schemas/Hex) | z.Hex schemas. |
| [z.Log](/zod/schemas/Log) | z.Log schemas. |
| [z.RpcResponse](/zod/schemas/RpcResponse) | z.RpcResponse schemas. |
| [z.Signature](/zod/schemas/Signature) | z.Signature schemas. |
| [z.Solidity](/zod/schemas/Solidity) | z.Solidity schemas. |
| [z.StateOverrides](/zod/schemas/StateOverrides) | z.StateOverrides schemas. |
| [z.Transaction](/zod/schemas/Transaction) | z.Transaction schemas. |
| [z.TransactionEnvelope](/zod/schemas/TransactionEnvelope) | z.TransactionEnvelope schemas. |
| [z.TransactionReceipt](/zod/schemas/TransactionReceipt) | z.TransactionReceipt schemas. |
| [z.TransactionRequest](/zod/schemas/TransactionRequest) | z.TransactionRequest schemas. |
| [z.TxEnvelopeEip1559](/zod/schemas/TxEnvelopeEip1559) | z.TxEnvelopeEip1559 schemas. |
| [z.TxEnvelopeEip2930](/zod/schemas/TxEnvelopeEip2930) | z.TxEnvelopeEip2930 schemas. |
| [z.TxEnvelopeEip4844](/zod/schemas/TxEnvelopeEip4844) | z.TxEnvelopeEip4844 schemas. |
| [z.TxEnvelopeEip7702](/zod/schemas/TxEnvelopeEip7702) | z.TxEnvelopeEip7702 schemas. |
| [z.TxEnvelopeLegacy](/zod/schemas/TxEnvelopeLegacy) | z.TxEnvelopeLegacy schemas. |
| [z.TypedData](/zod/schemas/TypedData) | z.TypedData schemas. |
| [z.Withdrawal](/zod/schemas/Withdrawal) | z.Withdrawal schemas. |
| **Tempo** | |
| [z.tempo.AuthorizationTempo](/zod/tempo/AuthorizationTempo) | z.tempo.AuthorizationTempo schemas. |
| [z.tempo.KeyAuthorization](/zod/tempo/KeyAuthorization) | z.tempo.KeyAuthorization schemas. |
| [z.tempo.MultisigConfig](/zod/tempo/MultisigConfig) | z.tempo.MultisigConfig schemas. |
| [z.tempo.PoolId](/zod/tempo/PoolId) | z.tempo.PoolId schemas. |
| [z.tempo.RpcSchemaTempo](/zod/tempo/RpcSchemaTempo) | z.tempo.RpcSchemaTempo schemas. |
| [z.tempo.SignatureEnvelope](/zod/tempo/SignatureEnvelope) | z.tempo.SignatureEnvelope schemas. |
| [z.tempo.Tick](/zod/tempo/Tick) | z.tempo.Tick schemas. |
| [z.tempo.TokenRole](/zod/tempo/TokenRole) | z.tempo.TokenRole schemas. |
| [z.tempo.Transaction](/zod/tempo/Transaction) | z.tempo.Transaction schemas. |
| [z.tempo.TransactionReceipt](/zod/tempo/TransactionReceipt) | z.tempo.TransactionReceipt schemas. |
| [z.tempo.TransactionRequest](/zod/tempo/TransactionRequest) | z.tempo.TransactionRequest schemas. |
| [z.tempo.TxEnvelopeTempo](/zod/tempo/TxEnvelopeTempo) | z.tempo.TxEnvelopeTempo schemas. |
| [z.tempo.VirtualAddress](/zod/tempo/VirtualAddress) | z.tempo.VirtualAddress schemas. |
| [z.tempo.ZoneId](/zod/tempo/ZoneId) | z.tempo.ZoneId schemas. |
| [z.tempo.ZoneRpcAuthentication](/zod/tempo/ZoneRpcAuthentication) | z.tempo.ZoneRpcAuthentication schemas. |
# Abi
Utilities & types for working with [Application Binary Interfaces (ABIs)](https://docs.soliditylang.org/en/latest/abi-spec.html)
:::note
If you are looking for ABI parameter **encoding** & **decoding** functions, see [`AbiParameters.encode`](/api/AbiParameters/encode) & [`AbiParameters.decode`](/api/AbiParameters/decode).
:::
## Examples
Below are some examples demonstrating common usages of the `Abi` module:
* [Instantiating JSON ABIs](#instantiating-json-abis)
* [Instantiating Human Readable ABIs](#instantiating-human-readable-abis)
* [Formatting ABIs](#formatting-abis)
### Instantiating JSON ABIs
An [`Abi.Abi`](/api/Abi/types#abi) can be instantiated from a JSON ABI by using [`Abi.from`](/api/Abi/from):
```ts twoslash
import { Abi } from 'ox'
const abi = Abi.from([
{
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
],
outputs: [{ type: 'bool' }]
}
])
abi
//^?
```
### Instantiating Human Readable ABIs
An [`Abi.Abi`](/api/Abi/types#abi) can be instantiated from a human-readable ABI by using [`Abi.from`](/api/Abi/from):
```ts twoslash
import { Abi } from 'ox'
const abi = Abi.from([
'function approve(address spender, uint256 amount) returns (bool)'
])
abi
//^?
```
### Formatting ABIs
An [`Abi.Abi`](/api/Abi/types#abi) can be formatted into a human-readable ABI by using [`Abi.format`](/api/Abi/format):
```ts twoslash
import { Abi } from 'ox'
const abi = Abi.from([
{
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
],
outputs: [{ type: 'bool' }]
}
])
//---cut---
const formatted = Abi.format(abi)
formatted
// ^?
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Abi.format`](/api/Abi/format) | Formats an [`Abi.Abi`](/api/Abi/types#abi) into a **Human Readable ABI**. |
| [`Abi.from`](/api/Abi/from) | Parses an arbitrary **JSON ABI** or **Human Readable ABI** into a typed [`Abi.Abi`](/api/Abi/types#abi). |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Abi.CircularReferenceError`](/api/Abi/errors#abicircularreferenceerror) | |
| [`Abi.InvalidSignatureError`](/api/Abi/errors#abiinvalidsignatureerror) | |
| [`Abi.InvalidStructSignatureError`](/api/Abi/errors#abiinvalidstructsignatureerror) | |
| [`Abi.UnknownSignatureError`](/api/Abi/errors#abiunknownsignatureerror) | |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Abi.Abi`](/api/Abi/types#abiabi) | Root type for an ABI. |
# Abi.format
Formats an [`Abi.Abi`](/api/Abi/types#abi) into a **Human Readable ABI**.
## Imports
:::code-group
```ts [Named]
import { Abi } from 'ox'
```
```ts [Entrypoint]
import * as Abi from 'ox/Abi'
```
:::
## Examples
```ts twoslash
import { Abi } from 'ox'
const formatted = Abi.format([
{
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
],
outputs: [{ type: 'bool' }]
}
])
formatted
// ^?
```
## Definition
```ts
function format(
abi: Abi | readonly unknown[],
): readonly string[]
```
**Source:** [src/core/Abi.ts](https://github.com/wevm/ox/blob/main/src/core/Abi.ts#L19)
## Parameters
### abi
* **Type:** `Abi | readonly unknown[]`
The ABI to format.
## Return Type
The formatted ABI.
`readonly string[]`
# Abi.from
Parses an arbitrary **JSON ABI** or **Human Readable ABI** into a typed [`Abi.Abi`](/api/Abi/types#abi).
## Imports
:::code-group
```ts [Named]
import { Abi } from 'ox'
```
```ts [Entrypoint]
import * as Abi from 'ox/Abi'
```
:::
## Examples
### JSON ABIs
```ts twoslash
import { Abi } from 'ox'
const abi = Abi.from([
{
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
],
outputs: [{ type: 'bool' }]
}
])
abi
//^?
```
### Human Readable ABIs
```ts twoslash
import { Abi } from 'ox'
const abi = Abi.from([
'function approve(address spender, uint256 amount) returns (bool)'
])
abi
//^?
```
## Definition
```ts
function from(
abi: Abi | readonly string[],
): Abi
```
**Source:** [src/core/Abi.ts](https://github.com/wevm/ox/blob/main/src/core/Abi.ts#L67)
## Parameters
### abi
* **Type:** `Abi | readonly string[]`
The ABI to parse.
## Return Type
The typed ABI.
`Abi.Abi`
# Abi Errors
## `Abi.CircularReferenceError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L197)
## `Abi.InvalidSignatureError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L145)
## `Abi.InvalidStructSignatureError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L171)
## `Abi.UnknownSignatureError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L161)
# Abi Types
## `Abi.Abi`
Root type for an ABI.
**Source:** [src/core/Abi.ts](https://github.com/wevm/ox/blob/main/src/core/Abi.ts#L9)
# AbiConstructor
Utilities & types for working with [Constructors](https://docs.soliditylang.org/en/latest/abi-spec.html#json) on ABIs.
`AbiConstructor` is a sub-type of [`AbiItem`](/api/AbiItem).
## Examples
Below are some examples demonstrating common usages of the `AbiConstructor` module:
* [Instantiating via JSON ABI](#instantiating-via-json-abi)
* [Instantiating via Human-Readable ABI Item](#instantiating-via-human-readable-abi-item)
* [Encoding to Deploy Data](#encoding-to-deploy-data)
### Instantiating via JSON ABI
An `AbiConstructor` can be instantiated from a JSON ABI by using [`AbiConstructor.fromAbi`](/api/AbiConstructor/fromAbi):
```ts twoslash
import { Abi, AbiConstructor } from 'ox'
const abi = Abi.from([
'constructor(address owner)',
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiConstructor.fromAbi(abi) // [!code focus]
// ^?
```
### Instantiating via Human-Readable ABI Item
An `AbiConstructor` can be instantiated from a human-readable ABI by using [`AbiConstructor.from`](/api/AbiConstructor/from):
```ts twoslash
import { AbiConstructor } from 'ox'
const constructor = AbiConstructor.from(
'constructor(address owner)'
)
constructor
//^?
```
### Encoding to Deploy Data
Constructor arguments can be ABI-encoded using [`AbiConstructor.encode`](/api/AbiConstructor/encode) (with bytecode) into deploy data. This data can then be passed to a transaction to deploy a contract.
```ts twoslash
import { AbiConstructor } from 'ox'
const constructor = AbiConstructor.from(
'constructor(address, uint256)'
)
const data = AbiConstructor.encode(constructor, {
// [!code focus]
bytecode: '0x...', // [!code focus]
args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n] // [!code focus]
}) // [!code focus]
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiConstructor.decode`](/api/AbiConstructor/decode) | ABI-decodes the provided constructor input (`inputs`). |
| [`AbiConstructor.encode`](/api/AbiConstructor/encode) | ABI-encodes the provided constructor input (`inputs`). |
| [`AbiConstructor.format`](/api/AbiConstructor/format) | Formats an [`AbiConstructor.AbiConstructor`](/api/AbiConstructor/types#abiconstructor) into a **Human Readable ABI Function**. |
| [`AbiConstructor.from`](/api/AbiConstructor/from) | Parses an arbitrary **JSON ABI Constructor** or **Human Readable ABI Constructor** into a typed [`AbiConstructor.AbiConstructor`](/api/AbiConstructor/types#abiconstructor). |
| [`AbiConstructor.fromAbi`](/api/AbiConstructor/fromAbi) | Extracts an [`AbiConstructor.AbiConstructor`](/api/AbiConstructor/types#abiconstructor) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments. |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiConstructor.BytecodeMismatchError`](/api/AbiConstructor/errors#abiconstructorbytecodemismatcherror) | Throws when the provided `data` does not begin with the provided `bytecode`. |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiConstructor.AbiConstructor`](/api/AbiConstructor/types#abiconstructorabiconstructor) | Root type for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) with a `constructor` type. |
# AbiConstructor.decode
ABI-decodes the provided constructor input (`inputs`).
## Imports
:::code-group
```ts [Named]
import { AbiConstructor } from 'ox'
```
```ts [Entrypoint]
import * as AbiConstructor from 'ox/AbiConstructor'
```
:::
## Examples
```ts twoslash
import { AbiConstructor } from 'ox'
const constructor = AbiConstructor.from(
'constructor(address, uint256)'
)
const bytecode = '0x...'
const data = AbiConstructor.encode(constructor, {
bytecode,
args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n]
})
const decoded = AbiConstructor.decode(constructor, {
// [!code focus]
bytecode, // [!code focus]
data // [!code focus]
}) // [!code focus]
```
### ABI-shorthand
You can also specify an entire ABI object as a parameter to `AbiConstructor.decode`.
```ts twoslash
// @noErrors
import { Abi, AbiConstructor } from 'ox'
const abi = Abi.from([...])
const data = AbiConstructor.encode(abi, {
bytecode: '0x...',
args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n],
})
const decoded = AbiConstructor.decode(abi, { // [!code focus]
bytecode: '0x...', // [!code focus]
data, // [!code focus]
}) // [!code focus]
```
## Definition
```ts
function decode(
abi: abi | Abi.Abi | readonly unknown[],
options: decode.Options,
): decode.ReturnType
```
**Source:** [src/core/AbiConstructor.ts](https://github.com/wevm/ox/blob/main/src/core/AbiConstructor.ts#L81)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### options
* **Type:** `decode.Options`
Decoding options.
## Return Type
The decoded constructor inputs.
`decode.ReturnType`
# AbiConstructor.encode
ABI-encodes the provided constructor input (`inputs`).
## Imports
:::code-group
```ts [Named]
import { AbiConstructor } from 'ox'
```
```ts [Entrypoint]
import * as AbiConstructor from 'ox/AbiConstructor'
```
:::
## Examples
```ts twoslash
import { AbiConstructor } from 'ox'
const constructor = AbiConstructor.from(
'constructor(address, uint256)'
)
const data = AbiConstructor.encode(constructor, {
bytecode: '0x...',
args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n]
})
```
### ABI-shorthand
You can also specify an entire ABI object as a parameter to `AbiConstructor.encode`.
```ts twoslash
// @noErrors
import { Abi, AbiConstructor } from 'ox'
const abi = Abi.from([...])
const data = AbiConstructor.encode(abi, { // [!code focus]
bytecode: '0x...', // [!code focus]
args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n], // [!code focus]
}) // [!code focus]
```
### End-to-end
Below is an end-to-end example of using `AbiConstructor.encode` to encode the constructor of a contract and deploy it.
```ts twoslash
import 'ox/window'
import { AbiConstructor, Hex } from 'ox'
// 1. Instantiate the ABI Constructor.
const constructor = AbiConstructor.from(
'constructor(address owner, uint256 amount)'
)
// 2. Encode the ABI Constructor.
const data = AbiConstructor.encode(constructor, {
bytecode: '0x...',
args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n]
})
// 3. Deploy the contract.
const hash = await window.ethereum!.request({
method: 'eth_sendTransaction',
params: [{ data }]
})
```
:::note
For simplicity, the above example uses `window.ethereum.request`, but you can use any type of JSON-RPC interface.
:::
## Definition
```ts
function encode(
abi: abi | Abi.Abi | readonly unknown[],
options: encode.Options,
): encode.ReturnType
```
**Source:** [src/core/AbiConstructor.ts](https://github.com/wevm/ox/blob/main/src/core/AbiConstructor.ts#L227)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### options
* **Type:** `encode.Options`
Encoding options.
#### options.args
* **Type:** `args`
The constructor arguments to encode.
#### options.bytecode
* **Type:** `0x${string}`
The bytecode of the contract.
## Return Type
The encoded constructor.
`encode.ReturnType`
# AbiConstructor.format
Formats an [`AbiConstructor.AbiConstructor`](/api/AbiConstructor/types#abiconstructor) into a **Human Readable ABI Function**.
## Imports
:::code-group
```ts [Named]
import { AbiConstructor } from 'ox'
```
```ts [Entrypoint]
import * as AbiConstructor from 'ox/AbiConstructor'
```
:::
## Examples
```ts twoslash
import { AbiConstructor } from 'ox'
const formatted = AbiConstructor.format({
inputs: [{ name: 'owner', type: 'address' }],
payable: false,
stateMutability: 'nonpayable',
type: 'constructor'
})
formatted
// ^?
```
## Definition
```ts
function format(
abiConstructor: AbiConstructor,
): string
```
**Source:** [src/core/AbiConstructor.ts](https://github.com/wevm/ox/blob/main/src/core/AbiConstructor.ts#L293)
## Parameters
### abiConstructor
* **Type:** `AbiConstructor`
The ABI Constructor to format.
## Return Type
The formatted ABI Constructor.
`string`
# AbiConstructor.from
Parses an arbitrary **JSON ABI Constructor** or **Human Readable ABI Constructor** into a typed [`AbiConstructor.AbiConstructor`](/api/AbiConstructor/types#abiconstructor).
## Imports
:::code-group
```ts [Named]
import { AbiConstructor } from 'ox'
```
```ts [Entrypoint]
import * as AbiConstructor from 'ox/AbiConstructor'
```
:::
## Examples
### JSON ABIs
```ts twoslash
import { AbiConstructor } from 'ox'
const constructor = AbiConstructor.from({
inputs: [{ name: 'owner', type: 'address' }],
payable: false,
stateMutability: 'nonpayable',
type: 'constructor'
})
constructor
//^?
```
### Human Readable ABIs
A Human Readable ABI can be parsed into a typed ABI object:
```ts twoslash
import { AbiConstructor } from 'ox'
const constructor = AbiConstructor.from(
'constructor(address owner)' // [!code hl]
)
constructor
//^?
```
It is possible to specify `struct`s along with your definitions:
```ts twoslash
import { AbiConstructor } from 'ox'
const constructor = AbiConstructor.from([
'struct Foo { address owner; uint256 amount; }', // [!code hl]
'constructor(Foo foo)'
])
constructor
//^?
```
## Definition
```ts
function from(
abiConstructor: AbiConstructor | string | readonly string[],
): AbiConstructor
```
**Source:** [src/core/AbiConstructor.ts](https://github.com/wevm/ox/blob/main/src/core/AbiConstructor.ts#L331)
## Parameters
### abiConstructor
* **Type:** `AbiConstructor | string | readonly string[]`
The ABI Constructor to parse.
## Return Type
Typed ABI Constructor.
`AbiConstructor`
# AbiConstructor.fromAbi
Extracts an [`AbiConstructor.AbiConstructor`](/api/AbiConstructor/types#abiconstructor) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments.
## Imports
:::code-group
```ts [Named]
import { AbiConstructor } from 'ox'
```
```ts [Entrypoint]
import * as AbiConstructor from 'ox/AbiConstructor'
```
:::
## Examples
### Extracting by Name
ABI Events can be extracted by their name using the `name` option:
```ts twoslash
import { Abi, AbiConstructor } from 'ox'
const abi = Abi.from([
'constructor(address owner)',
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiConstructor.fromAbi(abi) // [!code focus]
// ^?
```
## Definition
```ts
function fromAbi(
abi: Abi.Abi | readonly unknown[],
): AbiConstructor
```
**Source:** [src/core/AbiConstructor.ts](https://github.com/wevm/ox/blob/main/src/core/AbiConstructor.ts#L421)
## Parameters
### abi
* **Type:** `Abi.Abi | readonly unknown[]`
## Return Type
The ABI constructor.
`AbiConstructor`
# AbiConstructor Errors
## `AbiConstructor.BytecodeMismatchError`
Throws when the provided `data` does not begin with the provided `bytecode`.
### Examples
```ts twoslash
import { AbiConstructor } from 'ox'
AbiConstructor.decode(
AbiConstructor.from('constructor(address)'),
{ bytecode: '0x6080...', data: '0xdeadbeef' }
)
// @error: AbiConstructor.BytecodeMismatchError: Provided `data` does not start with the provided `bytecode`.
```
**Source:** [src/core/AbiConstructor.ts](https://github.com/wevm/ox/blob/main/src/core/AbiConstructor.ts#L479)
# AbiConstructor Types
## `AbiConstructor.AbiConstructor`
Root type for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) with a `constructor` type.
**Source:** [src/core/AbiConstructor.ts](https://github.com/wevm/ox/blob/main/src/core/AbiConstructor.ts#L12)
# AbiError
Utilities & types for working with [Errors](https://docs.soliditylang.org/en/latest/abi-spec.html#json) on ABIs.
`AbiError` is a sub-type of [`AbiItem`](/api/AbiItem).
## Examples
Below are some examples demonstrating common usages of the `AbiError` module:
* [Instantiating via JSON ABI](#instantiating-via-json-abi)
* [Instantiating via Human-Readable ABI Item](#instantiating-via-human-readable-abi-item)
* [Decoding Error Data](#decoding-error-data)
### Instantiating via JSON ABI
An `AbiError` can be instantiated from a JSON ABI by using [`AbiError.fromAbi`](/api/AbiError/fromAbi):
```ts twoslash
import { Abi, AbiError } from 'ox'
const abi = Abi.from([
'function foo()',
'error BadSignatureV(uint8 v)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiError.fromAbi(abi, 'BadSignatureV') // [!code focus]
// ^?
```
### Instantiating via Human-Readable ABI Item
An `AbiError` can be instantiated from a human-readable ABI by using [`AbiError.from`](/api/AbiError/from):
```ts twoslash
import { AbiError } from 'ox'
const error = AbiError.from('error BadSignatureV(uint8 v)')
error
//^?
```
### Decoding Error Data
Error data can be ABI-decoded using the [`AbiError.decode`](/api/AbiError/decode) function.
```ts twoslash
// @noErrors
import { Abi, AbiError } from 'ox'
const abi = Abi.from([...])
const error = AbiError.fromAbi(abi, 'InvalidSignature')
const value = AbiError.decode(error, '0xecde634900000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001') // [!code focus]
// @log: [420n, 69n, 1]
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiError.decode`](/api/AbiError/decode) | ABI-decodes the provided error input (`inputs`). |
| [`AbiError.encode`](/api/AbiError/encode) | ABI-encodes the provided error input (`inputs`), prefixed with the 4 byte error selector. |
| [`AbiError.extract`](/api/AbiError/extract) | Extracts an [`AbiError.AbiError`](/api/AbiError/types#abierror) from an [`Abi.Abi`](/api/Abi/types#abi) and decodes its arguments from error data. |
| [`AbiError.format`](/api/AbiError/format) | Formats an [`AbiError.AbiError`](/api/AbiError/types#abierror) into a **Human Readable ABI Error**. |
| [`AbiError.from`](/api/AbiError/from) | Parses an arbitrary **JSON ABI Error** or **Human Readable ABI Error** into a typed [`AbiError.AbiError`](/api/AbiError/types#abierror). |
| [`AbiError.fromAbi`](/api/AbiError/fromAbi) | Extracts an [`AbiError.AbiError`](/api/AbiError/types#abierror) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments. |
| [`AbiError.getSelector`](/api/AbiError/getSelector) | Computes the [4-byte selector](https://solidity-by-example.org/function-selector/) for an [`AbiError.AbiError`](/api/AbiError/types#abierror). |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiError.AbiError`](/api/AbiError/types#abierrorabierror) | Root type for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) with an `error` type. |
| [`AbiError.ExtractNames`](/api/AbiError/types#abierrorextractnames) | |
| [`AbiError.FromAbi`](/api/AbiError/types#abierrorfromabi) | Extracts an [`AbiError.AbiError`](/api/AbiError/types#abierror) item from an [`Abi.Abi`](/api/Abi/types#abi), given a name. |
| [`AbiError.Name`](/api/AbiError/types#abierrorname) | Extracts the names of all [`AbiError.AbiError`](/api/AbiError/types#abierror) items in an [`Abi.Abi`](/api/Abi/types#abi). |
# AbiError.decode
ABI-decodes the provided error input (`inputs`).
:::tip
This function is typically used to decode contract function reverts (e.g. a JSON-RPC error response).
See the [End-to-end Example](#end-to-end).
:::
## Imports
:::code-group
```ts [Named]
import { AbiError } from 'ox'
```
```ts [Entrypoint]
import * as AbiError from 'ox/AbiError'
```
:::
## Examples
```ts twoslash
import { AbiError } from 'ox'
const error = AbiError.from(
'error InvalidSignature(uint r, uint s, uint8 yParity)'
)
const value = AbiError.decode(
error,
'0xecde634900000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001'
)
// @log: [420n, 69n, 1]
```
You can extract an ABI Error from a JSON ABI with [`AbiError.fromAbi`](/api/AbiError/fromAbi):
```ts twoslash
// @noErrors
import { Abi, AbiError } from 'ox'
const abi = Abi.from([...]) // [!code hl]
const error = AbiError.fromAbi(abi, 'InvalidSignature') // [!code hl]
const value = AbiError.decode(error, '0xecde634900000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001')
// @log: [420n, 69n, 1]
```
You can pass the error `data` to the `name` property of [`AbiError.fromAbi`](/api/AbiError/fromAbi) to extract and infer the error by its 4-byte selector:
```ts twoslash
// @noErrors
import { Abi, AbiError } from 'ox'
const data = '0xecde634900000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001'
const abi = Abi.from([...])
const error = AbiError.fromAbi(abi, data) // [!code hl]
const value = AbiError.decode(error, data)
// @log: [420n, 69n, 1]
```
### ABI-shorthand
You can also specify an entire ABI object as a parameter to [`AbiError.decode`](/api/AbiError/decode):
```ts twoslash
// @noErrors
import { Abi, AbiError } from 'ox'
const abi = Abi.from([...])
const value = AbiError.decode(
abi, // [!code hl]
'InvalidSignature', // [!code hl]
'0x...'
)
// @log: [420n, 69n, 1]
```
### End-to-end
Below is an end-to-end example of using `AbiError.decode` to decode the revert error of an `approve` contract call on the [Wagmi Mint Example contract](https://etherscan.io/address/0xfba3912ca04dd458c843e2ee08967fc04f3579c2).
```ts twoslash
// @noErrors
import 'ox/window'
import { Abi, AbiError, AbiFunction } from 'ox'
// 1. Extract the Function from the Contract's ABI.
const abi = Abi.from([
// ...
{
inputs: [
{ name: 'to', type: 'address' },
{ name: 'tokenId', type: 'uint256' }
],
name: 'approve',
outputs: [],
stateMutability: 'nonpayable',
type: 'function'
}
// ...
])
const approve = AbiFunction.fromAbi(abi, 'approve')
// 2. Encode the Function Input.
const data = AbiFunction.encodeData(approve, [
'0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
69420n
])
try {
// 3. Attempt to perform the the Contract Call.
await window.ethereum!.request({
method: 'eth_call',
params: [
{
data,
to: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2'
}
]
})
} catch (e) {
// [!code focus]
// 4. Extract and decode the Error. // [!code focus]
const error = AbiError.fromAbi(abi, e.data) // [!code focus]
const value = AbiError.decode(error, e.data) // [!code focus]
console.error(`${error.name}(${value})`) // [!code focus]
// @error: Error(ERC721: approve caller is not owner nor approved for all)
} // [!code focus]
```
:::note
For simplicity, the above example uses `window.ethereum.request`, but you can use any type of JSON-RPC interface.
:::
## Definition
```ts
function decode(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
data: Hex.Hex,
options?: decode.Options,
): decode.ReturnType
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L19)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
### data
* **Type:** `Hex.Hex`
The error data.
### options
* **Type:** `decode.Options`
* **Optional**
Decoding options.
#### options.as
* **Type:** `as | "Array" | "Object"`
* **Optional**
Whether the decoded values should be returned as an `Object` or `Array`.
#### options.checksumAddress
* **Type:** `boolean`
* **Optional**
Whether decoded addresses should be checksummed.
## Return Type
The decoded error.
`decode.ReturnType`
# AbiError.encode
ABI-encodes the provided error input (`inputs`), prefixed with the 4 byte error selector.
## Imports
:::code-group
```ts [Named]
import { AbiError } from 'ox'
```
```ts [Entrypoint]
import * as AbiError from 'ox/AbiError'
```
:::
## Examples
```ts twoslash
import { AbiError } from 'ox'
const error = AbiError.from(
'error InvalidSignature(uint r, uint s, uint8 yParity)'
)
const data = AbiError.encode(
// [!code focus]
error, // [!code focus]
[1n, 2n, 0] // [!code focus]
) // [!code focus]
// @log: '0x095ea7b3000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000000000000010f2c'
```
### ABI-shorthand
You can also specify an entire ABI object and an error name as parameters to `AbiError.encode`.
```ts twoslash
// @noErrors
import { Abi, AbiError } from 'ox'
const abi = Abi.from([...])
const data = AbiError.encode(
abi, // [!code hl]
'InvalidSignature', // [!code hl]
[1n, 2n, 0]
)
```
## Definition
```ts
function encode(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
args: encode.Args,
): encode.ReturnType
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L410)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
### args
* **Type:** `encode.Args`
Error arguments
## Return Type
ABI-encoded error name and arguments
`encode.ReturnType`
# AbiError.extract
Extracts an [`AbiError.AbiError`](/api/AbiError/types#abierror) from an [`Abi.Abi`](/api/Abi/types#abi) and decodes its arguments from error data.
## Imports
:::code-group
```ts [Named]
import { AbiError } from 'ox'
```
```ts [Entrypoint]
import * as AbiError from 'ox/AbiError'
```
:::
## Examples
```ts twoslash
import { Abi, AbiError } from 'ox'
const abi = Abi.from([
'error InvalidSignature(uint r, uint s, uint8 yParity)'
])
const { error, args } = AbiError.extract(
abi,
'0xecde634900000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001'
)
// @log: {
// @log: error: { name: 'InvalidSignature', type: 'error', ... },
// @log: args: [420n, 69n, 1],
// @log: }
```
## Definition
```ts
function extract(
abi: abi | Abi.Abi | readonly unknown[],
data: Hex.Hex,
options?: extract.Options,
): extract.ReturnType, as>
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L306)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
The ABI to extract from.
### data
* **Type:** `Hex.Hex`
The error data.
### options
* **Type:** `extract.Options`
* **Optional**
Extraction options.
## Return Type
The extracted ABI Error and decoded arguments.
`extract.ReturnType, as>`
# AbiError.format
Formats an [`AbiError.AbiError`](/api/AbiError/types#abierror) into a **Human Readable ABI Error**.
## Imports
:::code-group
```ts [Named]
import { AbiError } from 'ox'
```
```ts [Entrypoint]
import * as AbiError from 'ox/AbiError'
```
:::
## Examples
```ts twoslash
import { AbiError } from 'ox'
const formatted = AbiError.format({
type: 'error',
name: 'Example',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
]
})
formatted
// ^?
```
## Definition
```ts
function format(
abiError: abiError | AbiError,
): format.ReturnType
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L512)
## Parameters
### abiError
* **Type:** `abiError | AbiError`
The ABI Error to format.
## Return Type
The formatted ABI Error.
`format.ReturnType`
# AbiError.from
Parses an arbitrary **JSON ABI Error** or **Human Readable ABI Error** into a typed [`AbiError.AbiError`](/api/AbiError/types#abierror).
## Imports
:::code-group
```ts [Named]
import { AbiError } from 'ox'
```
```ts [Entrypoint]
import * as AbiError from 'ox/AbiError'
```
:::
## Examples
### JSON ABIs
```ts twoslash
import { AbiError } from 'ox'
const badSignatureVError = AbiError.from({
inputs: [{ name: 'v', type: 'uint8' }],
name: 'BadSignatureV',
type: 'error'
})
badSignatureVError
//^?
```
### Human Readable ABIs
A Human Readable ABI can be parsed into a typed ABI object:
```ts twoslash
import { AbiError } from 'ox'
const badSignatureVError = AbiError.from(
'error BadSignatureV(uint8 v)' // [!code hl]
)
badSignatureVError
//^?
```
It is possible to specify `struct`s along with your definitions:
```ts twoslash
import { AbiError } from 'ox'
const badSignatureVError = AbiError.from([
'struct Signature { uint8 v; }', // [!code hl]
'error BadSignatureV(Signature signature)'
])
badSignatureVError
//^?
```
## Definition
```ts
function from(
abiError: (abiError | AbiError | string | readonly string[]) & ((abiError extends string ? internal.Signature : never) | (abiError extends readonly string[] ? internal.Signatures : never) | AbiError),
options?: from.Options,
): from.ReturnType
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L580)
## Parameters
### abiError
* **Type:** `(abiError | AbiError | string | readonly string[]) & ((abiError extends string ? internal.Signature : never) | (abiError extends readonly string[] ? internal.Signatures : never) | AbiError)`
The ABI Error to parse.
### options
* **Type:** `from.Options`
* **Optional**
#### options.prepare
* **Type:** `boolean`
* **Optional**
Whether or not to prepare the extracted function (optimization for encoding performance).
When `true`, the `hash` property is computed and included in the returned value.
## Return Type
Typed ABI Error.
`from.ReturnType`
# AbiError.fromAbi
Extracts an [`AbiError.AbiError`](/api/AbiError/types#abierror) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments.
## Imports
:::code-group
```ts [Named]
import { AbiError } from 'ox'
```
```ts [Entrypoint]
import * as AbiError from 'ox/AbiError'
```
:::
## Examples
### Extracting by Name
ABI Errors can be extracted by their name using the `name` option:
```ts twoslash
import { Abi, AbiError } from 'ox'
const abi = Abi.from([
'function foo()',
'error BadSignatureV(uint8 v)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiError.fromAbi(abi, 'BadSignatureV') // [!code focus]
// ^?
```
### Extracting by Selector
ABI Errors can be extract by their selector when [`Hex.Hex`](/api/Hex/types#hex) is provided to `name`.
```ts twoslash
import { Abi, AbiError } from 'ox'
const abi = Abi.from([
'function foo()',
'error BadSignatureV(uint8 v)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiError.fromAbi(abi, '0x095ea7b3') // [!code focus]
// ^?
```
:::note
Extracting via a hex selector is useful when extracting an ABI Error from JSON-RPC error data.
:::
## Definition
```ts
function fromAbi(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
options?: AbiItem.fromAbi.Options>,
): fromAbi.ReturnType
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L662)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
The ABI to extract from.
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
The name (or selector) of the ABI item to extract.
### options
* **Type:** `AbiItem.fromAbi.Options>`
* **Optional**
Extraction options.
#### options.args
* **Type:** `allArgs | (Widen & (args extends allArgs ? unknown : never))`
* **Optional**
#### options.prepare
* **Type:** `boolean`
* **Optional**
Whether or not to prepare the extracted item (optimization for encoding performance).
When `true`, the `hash` property is computed and included in the returned value.
## Return Type
The ABI item.
`fromAbi.ReturnType`
# AbiError.getSelector
Computes the [4-byte selector](https://solidity-by-example.org/function-selector/) for an [`AbiError.AbiError`](/api/AbiError/types#abierror).
## Imports
:::code-group
```ts [Named]
import { AbiError } from 'ox'
```
```ts [Entrypoint]
import * as AbiError from 'ox/AbiError'
```
:::
## Examples
```ts twoslash
import { AbiError } from 'ox'
const selector = AbiError.getSelector(
'error BadSignatureV(uint8 v)'
)
// @log: '0x6352211e'
```
```ts twoslash
import { AbiError } from 'ox'
const selector = AbiError.getSelector({
inputs: [{ name: 'v', type: 'uint8' }],
name: 'BadSignatureV',
type: 'error'
})
// @log: '0x6352211e'
```
## Definition
```ts
function getSelector(
abiItem: string | AbiError,
): Hex.Hex
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L746)
## Parameters
### abiItem
* **Type:** `string | AbiError`
The ABI item to compute the selector for.
#### abiItem.hash
* **Type:** `0x${string}`
* **Optional**
#### abiItem.overloads
* **Type:** `readonly any[]`
* **Optional**
## Return Type
The first 4 bytes of the [`Hash.keccak256`](/api/Hash/keccak256) hash of the error signature.
`Hex.Hex`
# AbiError Types
## `AbiError.AbiError`
Root type for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) with an `error` type.
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L13)
## `AbiError.ExtractNames`
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L833)
## `AbiError.FromAbi`
Extracts an [`AbiError.AbiError`](/api/AbiError/types#abierror) item from an [`Abi.Abi`](/api/Abi/types#abi), given a name.
### Examples
```ts twoslash
import { Abi, AbiError } from 'ox'
const abi = Abi.from([
'error Foo(string)',
'error Bar(uint256)'
])
type Foo = AbiError.FromAbi
// ^?
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L809)
## `AbiError.Name`
Extracts the names of all [`AbiError.AbiError`](/api/AbiError/types#abierror) items in an [`Abi.Abi`](/api/Abi/types#abi).
### Examples
```ts twoslash
import { Abi, AbiError } from 'ox'
const abi = Abi.from([
'error Foo(string)',
'error Bar(uint256)'
])
type names = AbiError.Name
// ^?
```
**Source:** [src/core/AbiError.ts](https://github.com/wevm/ox/blob/main/src/core/AbiError.ts#L830)
# AbiEvent
Utilities & types for working with [Events](https://docs.soliditylang.org/en/latest/abi-spec.html#json) on ABIs.
`AbiEvent` is a sub-type of [`AbiItem`](/api/AbiItem).
## Examples
Below are some examples demonstrating common usages of the `AbiEvent` module:
* [Instantiating via JSON ABI](#instantiating-via-json-abi)
* [Instantiating via Human-Readable ABI Item](#instantiating-via-human-readable-abi-item)
* [Encoding to Event Topics](#encoding-to-event-topics)
* [Decoding Event Topics and Data](#decoding-event-topics-and-data)
### Instantiating via JSON ABI
An `AbiEvent` can be instantiated from a JSON ABI by using [`AbiEvent.fromAbi`](/api/AbiEvent/fromAbi):
```ts twoslash
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiEvent.fromAbi(abi, 'Transfer') // [!code focus]
// ^?
```
### Instantiating via Human-Readable ABI Item
An `AbiEvent` can be instantiated from a human-readable ABI by using [`AbiEvent.from`](/api/AbiEvent/from):
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)' // [!code hl]
)
transfer
//^?
```
### Encoding to Event Topics
Encode an `AbiEvent` into topics using [`AbiEvent.encode`](/api/AbiEvent/encode):
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const { topics } = AbiEvent.encode(transfer, {
from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', // [!code hl]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' // [!code hl]
})
// @log: [
// @log: '0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
// @log: '0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
// @log: '0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
// @log: ]
```
### Decoding Event Topics and Data
Event topics and data can be decoded using [`AbiEvent.decode`](/api/AbiEvent/decode):
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const log = {
// ...
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac'
]
} as const
const decoded = AbiEvent.decode(transfer, log)
// @log: {
// @log: from: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
// @log: to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
// @log: value: 1n
// @log: }
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiEvent.assertArgs`](/api/AbiEvent/assertArgs) | Asserts that the provided arguments match the decoded log arguments. |
| [`AbiEvent.decode`](/api/AbiEvent/decode) | ABI-Decodes the provided [Log Topics and Data](https://info.etherscan.com/what-is-event-logs/) according to the ABI Event's parameter types (`input`). |
| [`AbiEvent.decodeLog`](/api/AbiEvent/decodeLog) | Extracts an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent) from an [`Abi.Abi`](/api/Abi/types#abi) and decodes its arguments from a Log. |
| [`AbiEvent.encode`](/api/AbiEvent/encode) | ABI-encodes the provided event input (`inputs`) into an array of [Event Topics](https://info.etherscan.com/what-is-event-logs/). |
| [`AbiEvent.extractLogs`](/api/AbiEvent/extractLogs) | Extracts and decodes Logs that match an ABI Event in an ABI. |
| [`AbiEvent.format`](/api/AbiEvent/format) | Formats an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent) into a **Human Readable ABI Error**. |
| [`AbiEvent.from`](/api/AbiEvent/from) | Parses an arbitrary **JSON ABI Event** or **Human Readable ABI Event** into a typed [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent). |
| [`AbiEvent.fromAbi`](/api/AbiEvent/fromAbi) | Extracts an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments. |
| [`AbiEvent.getSelector`](/api/AbiEvent/getSelector) | Computes the event selector (hash of event signature) for an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent). |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiEvent.ArgsMismatchError`](/api/AbiEvent/errors#abieventargsmismatcherror) | Thrown when the provided arguments do not match the expected arguments. |
| [`AbiEvent.DataMismatchError`](/api/AbiEvent/errors#abieventdatamismatcherror) | Thrown when the provided data size does not match the expected size from the non-indexed parameters. |
| [`AbiEvent.FilterTypeNotSupportedError`](/api/AbiEvent/errors#abieventfiltertypenotsupportederror) | Thrown when the provided filter type is not supported. |
| [`AbiEvent.InputNotFoundError`](/api/AbiEvent/errors#abieventinputnotfounderror) | Thrown when no argument was found on the event signature. |
| [`AbiEvent.SelectorTopicMismatchError`](/api/AbiEvent/errors#abieventselectortopicmismatcherror) | Thrown when the provided selector does not match the expected selector. |
| [`AbiEvent.SelectorTopicNotFoundError`](/api/AbiEvent/errors#abieventselectortopicnotfounderror) | Thrown when the selector topic is not found. |
| [`AbiEvent.TopicsMismatchError`](/api/AbiEvent/errors#abieventtopicsmismatcherror) | Thrown when the provided topics do not match the expected number of topics. |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abieventabievent) | Root type for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) with an `event` type. |
| [`AbiEvent.ExtractNames`](/api/AbiEvent/types#abieventextractnames) | |
| [`AbiEvent.FromAbi`](/api/AbiEvent/types#abieventfromabi) | Extracts an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent) item from an [`Abi.Abi`](/api/Abi/types#abi), given a name. |
| [`AbiEvent.Name`](/api/AbiEvent/types#abieventname) | Extracts the names of all [`AbiError.AbiError`](/api/AbiError/types#abierror) items in an [`Abi.Abi`](/api/Abi/types#abi). |
# AbiEvent.assertArgs
Asserts that the provided arguments match the decoded log arguments.
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
```ts twoslash
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac'
]
})
AbiEvent.assertArgs(abiEvent, args, {
from: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad',
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
value: 1n
})
// @error: AbiEvent.ArgsMismatchError: Given arguments to not match the arguments decoded from the log.
// @error: Event: event Transfer(address indexed from, address indexed to, uint256 value)
// @error: Expected Arguments:
// @error: from: 0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac
// @error: to: 0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad
// @error: value: 1
// @error: Given Arguments:
// @error: from: 0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad
// @error: to: 0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac
// @error: value: 1
```
## Definition
```ts
function assertArgs(
abiEvent: abiEvent | AbiEvent,
args: unknown,
matchArgs: IsNarrowable extends true ? abiEvent['inputs'] extends readonly [] ? never : internal.ParametersToPrimitiveTypes : unknown,
): void
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L200)
## Parameters
### abiEvent
* **Type:** `abiEvent | AbiEvent`
ABI Event to check.
### args
* **Type:** `unknown`
Decoded arguments.
### matchArgs
* **Type:** `IsNarrowable extends true ? abiEvent['inputs'] extends readonly [] ? never : internal.ParametersToPrimitiveTypes : unknown`
The arguments to check.
## Return Type
`void`
# AbiEvent.decode
ABI-Decodes the provided [Log Topics and Data](https://info.etherscan.com/what-is-event-logs/) according to the ABI Event's parameter types (`input`).
:::tip
This function is typically used to decode an [Event Log](https://info.etherscan.com/what-is-event-logs/) that may be returned from a Log Query (e.g. `eth_getLogs`) or Transaction Receipt.
See the [End-to-end Example](#end-to-end).
:::
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const log = {
// ...
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac'
]
} as const
const decoded = AbiEvent.decode(transfer, log)
// @log: {
// @log: from: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: value: 1n
// @log: }
```
### ABI-shorthand
You can also specify an entire ABI object and an event name as parameters to [`AbiEvent.decode`](/api/AbiEvent/decode):
```ts twoslash
// @noErrors
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([...])
const log = {
// ...
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
],
} as const
const decoded = AbiEvent.decode(
abi, // [!code focus]
'Transfer', // [!code focus]
log
)
// @log: {
// @log: from: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: value: 1n
// @log: }
```
### End-to-end
Below is an end-to-end example of using `AbiEvent.decode` to decode the topics of a `Transfer` event on the [Wagmi Mint Example contract](https://etherscan.io/address/0xfba3912ca04dd458c843e2ee08967fc04f3579c2).
```ts twoslash
import 'ox/window'
import { AbiEvent, Hex } from 'ox'
// 1. Instantiate the `Transfer` ABI Event.
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
// 2. Encode the ABI Event into Event Topics.
const { topics } = AbiEvent.encode(transfer)
// 3. Query for events matching the encoded Topics.
const logs = await window.ethereum!.request({
method: 'eth_getLogs',
params: [
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
fromBlock: Hex.fromNumber(19760235n),
toBlock: Hex.fromNumber(19760240n),
topics
}
]
})
// 4. Decode the Log. // [!code focus]
const decoded = AbiEvent.decode(transfer, logs[0]!) // [!code focus]
// @log: {
// @log: from: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: value: 603n
// @log: }
```
:::note
For simplicity, the above example uses `window.ethereum.request`, but you can use any type of JSON-RPC interface.
:::
## Definition
```ts
function decode(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
log: decode.Log,
options?: decode.Options,
): decode.ReturnType
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L417)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
### log
* **Type:** `decode.Log`
`topics` & `data` to decode.
#### log.data
* **Type:** `0x${string}`
* **Optional**
#### log.topics
* **Type:** `readonly 0x${string}[]`
### options
* **Type:** `decode.Options`
* **Optional**
Decoding options.
#### options.checksumAddress
* **Type:** `boolean`
* **Optional**
Whether decoded addresses should be checksummed.
## Return Type
The decoded event.
`decode.ReturnType`
# AbiEvent.decodeLog
Extracts an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent) from an [`Abi.Abi`](/api/Abi/types#abi) and decodes its arguments from a Log.
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
```ts twoslash
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([
'event Transfer(address indexed from, address indexed to, uint256 value)'
])
const decoded = AbiEvent.decodeLog(abi, {
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac'
]
})
// @log: {
// @log: event: { name: 'Transfer', type: 'event', ... },
// @log: args: {
// @log: from: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: value: 1n,
// @log: },
// @log: }
```
## Definition
```ts
function decodeLog(
abi: abi | Abi.Abi | readonly unknown[],
log: decodeLog.Log,
options?: decodeLog.Options,
): decodeLog.ReturnType>
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L650)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
The ABI to extract an event from.
### log
* **Type:** `decodeLog.Log`
`topics` & `data` to decode.
### options
* **Type:** `decodeLog.Options`
* **Optional**
Decoding options.
## Return Type
The decoded event and arguments.
`decodeLog.ReturnType>`
# AbiEvent.encode
ABI-encodes the provided event input (`inputs`) into an array of [Event Topics](https://info.etherscan.com/what-is-event-logs/).
:::tip
This function is typically used to encode event arguments into [Event Topics](https://info.etherscan.com/what-is-event-logs/).
See the [End-to-end Example](#end-to-end).
:::
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const { topics } = AbiEvent.encode(transfer)
// @log: ['0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0']
```
### Passing Arguments
You can pass `indexed` parameter values to `AbiEvent.encode`.
TypeScript types will be inferred from the ABI Event, to guard you from inserting the wrong values.
For example, the `Transfer` event below accepts an `address` type for the `from` and `to` attributes.
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const { topics } = AbiEvent.encode(transfer, {
from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', // [!code hl]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' // [!code hl]
})
// @log: [
// @log: '0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
// @log: '0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
// @log: '0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
// @log: ]
```
### ABI-shorthand
You can also specify an entire ABI object and an event name as parameters to [`AbiEvent.encode`](/api/AbiEvent/encode):
```ts twoslash
// @noErrors
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([...])
const { topics } = AbiEvent.encode(
abi, // [!code focus]
'Transfer', // [!code focus]
{
from: '0xf39fd6e51aad88f6f4ce6ab882779cfffb92266', // [!code focus]
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
}
)
// @log: [
// @log: '0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
// @log: '0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
// @log: '0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
// @log: ]
```
### End-to-end
Below is an end-to-end example of using `AbiEvent.encode` to encode the topics of a `Transfer` event and query for events matching the encoded topics on the [Wagmi Mint Example contract](https://etherscan.io/address/0xfba3912ca04dd458c843e2ee08967fc04f3579c2).
```ts twoslash
import 'ox/window'
import { AbiEvent, Hex } from 'ox'
// 1. Instantiate the `Transfer` ABI Event.
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
// 2. Encode the ABI Event into Event Topics.
const { topics } = AbiEvent.encode(transfer)
// 3. Query for events matching the encoded Topics.
const logs = await window.ethereum!.request({
method: 'eth_getLogs',
params: [
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
fromBlock: Hex.fromNumber(19760235n),
toBlock: Hex.fromNumber(19760240n),
topics
}
]
})
// @log: [
// @log: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
// @log: "0x0000000000000000000000000000000000000000000000000000000000000000",
// @log: "0x0000000000000000000000000c04d9e9278ec5e4d424476d3ebec70cb5d648d1",
// @log: "0x000000000000000000000000000000000000000000000000000000000000025b",
// @log: ]
```
:::note
For simplicity, the above example uses `window.ethereum.request`, but you can use any type of JSON-RPC interface.
:::
## Definition
```ts
function encode(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
[args]: encode.Args,
): encode.ReturnType
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1180)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
### \[args]
* **Type:** `encode.Args`
## Return Type
The encoded event topics.
`encode.ReturnType`
# AbiEvent.extractLogs
Extracts and decodes Logs that match an ABI Event in an ABI.
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
```ts twoslash
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([
'event Transfer(address indexed from, address indexed to, uint256 value)'
])
const logs = AbiEvent.extractLogs(abi, [
{
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac'
]
}
])
// @log: [{
// @log: eventName: 'Transfer',
// @log: args: {
// @log: from: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
// @log: value: 1n,
// @log: },
// @log: topics: [...],
// @log: data: '0x...',
// @log: }]
```
## Definition
```ts
function extractLogs(
abi: abi | Abi.Abi | readonly unknown[],
logs: logs | readonly extractLogs.Log[],
options?: extractLogs.Options,
): extractLogs.ReturnType, logs[number], strict>[]
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L722)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
The ABI to extract events from.
### logs
* **Type:** `logs | readonly extractLogs.Log[]`
Logs to extract.
### options
* **Type:** `extractLogs.Options`
* **Optional**
Extraction options.
#### options.args
* **Type:** `abiEvent["inputs"] extends readonly [] ? never : ParametersToPrimitiveTypes`
* **Optional**
Arguments to match against decoded event arguments.
#### options.checksumAddress
* **Type:** `boolean`
* **Optional**
Whether decoded addresses should be checksummed.
#### options.eventName
* **Type:** `eventName | Name[]`
* **Optional**
Event name, or event names, to extract.
#### options.strict
* **Type:** `boolean | strict`
* **Optional**
Whether to strictly decode log topics and data.
## Return Type
The extracted logs.
`extractLogs.ReturnType, logs[number], strict>[]`
# AbiEvent.format
Formats an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent) into a **Human Readable ABI Error**.
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
```ts twoslash
import { AbiEvent } from 'ox'
const formatted = AbiEvent.format({
type: 'event',
name: 'Transfer',
inputs: [
{ name: 'from', type: 'address', indexed: true },
{ name: 'to', type: 'address', indexed: true },
{ name: 'value', type: 'uint256' }
]
})
formatted
// ^?
```
## Definition
```ts
function format(
abiEvent: abiEvent | AbiEvent,
): format.ReturnType
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1336)
## Parameters
### abiEvent
* **Type:** `abiEvent | AbiEvent`
The ABI Event to format.
## Return Type
The formatted ABI Event.
`format.ReturnType`
# AbiEvent.from
Parses an arbitrary **JSON ABI Event** or **Human Readable ABI Event** into a typed [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent).
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
### JSON ABIs
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from({
name: 'Transfer',
type: 'event',
inputs: [
{ name: 'from', type: 'address', indexed: true },
{ name: 'to', type: 'address', indexed: true },
{ name: 'value', type: 'uint256' }
]
})
transfer
//^?
```
### Human Readable ABIs
A Human Readable ABI can be parsed into a typed ABI object:
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)' // [!code hl]
)
transfer
//^?
```
## Definition
```ts
function from(
abiEvent: (abiEvent | AbiEvent | string | readonly string[]) & ((abiEvent extends string ? internal.Signature : never) | (abiEvent extends readonly string[] ? internal.Signatures : never) | AbiEvent),
options?: from.Options,
): from.ReturnType
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1391)
## Parameters
### abiEvent
* **Type:** `(abiEvent | AbiEvent | string | readonly string[]) & ((abiEvent extends string ? internal.Signature : never) | (abiEvent extends readonly string[] ? internal.Signatures : never) | AbiEvent)`
The ABI Event to parse.
### options
* **Type:** `from.Options`
* **Optional**
#### options.prepare
* **Type:** `boolean`
* **Optional**
Whether or not to prepare the extracted event (optimization for encoding performance).
When `true`, the `hash` property is computed and included in the returned value.
## Return Type
Typed ABI Event.
`from.ReturnType`
# AbiEvent.fromAbi
Extracts an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments.
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
### Extracting by Name
ABI Events can be extracted by their name using the `name` option:
```ts twoslash
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiEvent.fromAbi(abi, 'Transfer') // [!code focus]
// ^?
```
### Extracting by Selector
ABI Events can be extract by their selector when [`Hex.Hex`](/api/Hex/types#hex) is provided to `name`.
```ts twoslash
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const selector =
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
const item = AbiEvent.fromAbi(abi, selector) // [!code focus]
// ^?
```
:::note
Extracting via a hex selector is useful when extracting an ABI Event from the first topic of a Log.
:::
## Definition
```ts
function fromAbi(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
options?: AbiItem.fromAbi.Options>,
): AbiItem.fromAbi.ReturnType
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1475)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
The ABI to extract from.
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
The name (or selector) of the ABI item to extract.
### options
* **Type:** `AbiItem.fromAbi.Options>`
* **Optional**
Extraction options.
#### options.args
* **Type:** `allArgs | (Widen & (args extends allArgs ? unknown : never))`
* **Optional**
#### options.prepare
* **Type:** `boolean`
* **Optional**
Whether or not to prepare the extracted item (optimization for encoding performance).
When `true`, the `hash` property is computed and included in the returned value.
## Return Type
The ABI item.
`AbiItem.fromAbi.ReturnType`
# AbiEvent.getSelector
Computes the event selector (hash of event signature) for an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent).
## Imports
:::code-group
```ts [Named]
import { AbiEvent } from 'ox'
```
```ts [Entrypoint]
import * as AbiEvent from 'ox/AbiEvent'
```
:::
## Examples
```ts twoslash
import { AbiEvent } from 'ox'
const selector = AbiEvent.getSelector(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
// @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f556a2'
```
```ts twoslash
import { AbiEvent } from 'ox'
const selector = AbiEvent.getSelector({
name: 'Transfer',
type: 'event',
inputs: [
{ name: 'from', type: 'address', indexed: true },
{ name: 'to', type: 'address', indexed: true },
{ name: 'value', type: 'uint256' }
]
})
// @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f556a2'
```
## Definition
```ts
function getSelector(
abiItem: string | AbiEvent,
): Hex.Hex
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1534)
## Parameters
### abiItem
* **Type:** `string | AbiEvent`
The ABI event to compute the selector for.
#### abiItem.hash
* **Type:** `0x${string}`
* **Optional**
#### abiItem.overloads
* **Type:** `readonly any[]`
* **Optional**
## Return Type
The [`Hash.keccak256`](/api/Hash/keccak256) hash of the event signature.
`Hex.Hex`
# AbiEvent Errors
## `AbiEvent.ArgsMismatchError`
Thrown when the provided arguments do not match the expected arguments.
### Examples
```ts twoslash
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ad'
]
})
AbiEvent.assertArgs(abiEvent, args, {
from: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad',
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
value: 1n
})
// @error: AbiEvent.ArgsMismatchError: Given arguments do not match the expected arguments.
// @error: Event: event Transfer(address indexed from, address indexed to, uint256 value)
// @error: Expected Arguments:
// @error: from: 0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac
// @error: to: 0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad
// @error: value: 1
// @error: Given Arguments:
// @error: from: 0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad
// @error: to: 0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac
// @error: value: 1
```
### Solution
The provided arguments need to match the expected arguments.
```ts twoslash
// @noErrors
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ad'
]
})
AbiEvent.assertArgs(abiEvent, args, {
from: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad', // [!code --]
from: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac', // [!code ++]
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac', // [!code --]
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad', // [!code ++]
value: 1n
})
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1609)
## `AbiEvent.DataMismatchError`
Thrown when the provided data size does not match the expected size from the non-indexed parameters.
### Examples
```ts twoslash
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address to, uint256 value)'
// ↑ 32 bytes + ↑ 32 bytes = 64 bytes
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0000000000000000000000000000000000000000000000000000000023c34600',
// ↑ 32 bytes ❌
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266'
]
})
// @error: AbiEvent.DataMismatchError: Data size of 32 bytes is too small for non-indexed event parameters.
// @error: Non-indexed Parameters: (address to, uint256 value)
// @error: Data: 0x0000000000000000000000000000000000000000000000000000000023c34600 (32 bytes)
```
### Solution
Ensure that the data size matches the expected size.
```ts twoslash
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address to, uint256 value)'
// ↑ 32 bytes + ↑ 32 bytes = 64 bytes
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000023c34600',
// ↑ 64 bytes ✅
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266'
]
})
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1747)
## `AbiEvent.FilterTypeNotSupportedError`
Thrown when the provided filter type is not supported.
### Examples
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer((string) indexed a, string b)'
)
AbiEvent.encode(transfer, {
a: ['hello']
})
// @error: AbiEvent.FilterTypeNotSupportedError: Filter type "tuple" is not supported.
```
### Solution
Provide a valid event input type.
```ts twoslash
// @noErrors
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer((string) indexed a, string b)'
) // [!code --]
const transfer = AbiEvent.from(
'event Transfer(string indexed a, string b)'
) // [!code ++]
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1975)
## `AbiEvent.InputNotFoundError`
Thrown when no argument was found on the event signature.
### Examples
```ts twoslash
// @noErrors
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ad'
]
})
AbiEvent.assertArgs(abiEvent, args, {
a: 'b',
from: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad',
value: 1n
})
// @error: AbiEvent.InputNotFoundError: Parameter "a" not found on `event Transfer(address indexed from, address indexed to, uint256 value)`.
```
### Solution
Ensure the arguments match the event signature.
```ts twoslash
// @noErrors
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ad'
]
})
AbiEvent.assertArgs(abiEvent, args, {
a: 'b', // [!code --]
from: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad',
value: 1n
})
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1692)
## `AbiEvent.SelectorTopicMismatchError`
Thrown when the provided selector does not match the expected selector.
### Examples
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, bool sender)'
)
AbiEvent.decode(transfer, {
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266'
]
})
// @error: AbiEvent.SelectorTopicMismatchError: topics[0]="0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" does not match the expected topics[0]="0x3da3cd3cf420c78f8981e7afeefa0eab1f0de0eb56e78ad9ba918ed01c0b402f".
// @error: Event: event Transfer(address indexed from, address indexed to, bool sender)
// @error: Selector: 0x3da3cd3cf420c78f8981e7afeefa0eab1f0de0eb56e78ad9ba918ed01c0b402f
```
### Solution
Ensure that the provided selector matches the selector of the event signature.
```ts twoslash
import { AbiEvent } from 'ox'
const transfer = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, bool sender)'
)
AbiEvent.decode(transfer, {
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', // [!code --]
'0x3da3cd3cf420c78f8981e7afeefa0eab1f0de0eb56e78ad9ba918ed01c0b402f', // [!code ++]
'0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266'
]
})
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1896)
## `AbiEvent.SelectorTopicNotFoundError`
Thrown when the selector topic is not found.
### Examples
```ts twoslash
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([
'event Transfer(address indexed from)'
])
AbiEvent.decodeLog(abi, { topics: [], data: '0x' })
// @error: AbiEvent.SelectorTopicNotFoundError: Selector topic not found.
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1932)
## `AbiEvent.TopicsMismatchError`
Thrown when the provided topics do not match the expected number of topics.
### Examples
```ts twoslash
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac'
]
})
// @error: AbiEvent.TopicsMismatchError: Expected a topic for indexed event parameter "to" for "event Transfer(address indexed from, address indexed to, uint256 value)".
```
### Solution
Ensure that the topics match the expected number of topics.
```ts twoslash
import { AbiEvent } from 'ox'
const abiEvent = AbiEvent.from(
'event Transfer(address indexed from, address indexed to, uint256 value)'
)
const args = AbiEvent.decode(abiEvent, {
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266' // [!code ++]
]
})
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L1828)
# AbiEvent Types
## `AbiEvent.AbiEvent`
Root type for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) with an `event` type.
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L18)
## `AbiEvent.ExtractNames`
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L155)
## `AbiEvent.FromAbi`
Extracts an [`AbiEvent.AbiEvent`](/api/AbiEvent/types#abievent) item from an [`Abi.Abi`](/api/Abi/types#abi), given a name.
### Examples
```ts twoslash
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([
'event Foo(string)',
'event Bar(uint256)'
])
type Foo = AbiEvent.FromAbi
// ^?
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L131)
## `AbiEvent.Name`
Extracts the names of all [`AbiError.AbiError`](/api/AbiError/types#abierror) items in an [`Abi.Abi`](/api/Abi/types#abi).
### Examples
```ts twoslash
import { Abi, AbiEvent } from 'ox'
const abi = Abi.from([
'event Foo(string)',
'event Bar(uint256)'
])
type names = AbiEvent.Name
// ^?
```
**Source:** [src/core/AbiEvent.ts](https://github.com/wevm/ox/blob/main/src/core/AbiEvent.ts#L152)
# AbiFunction
Utilities & types for working with [Functions](https://docs.soliditylang.org/en/latest/abi-spec.html#json) on ABIs.
`AbiFunction` is a sub-type of [`AbiItem`](/api/AbiItem).
## Examples
Below are some examples demonstrating common usages of the `AbiFunction` module:
* [Instantiating via JSON ABI](#instantiating-via-json-abi)
* [Instantiating via Human-Readable ABI Item](#instantiating-via-human-readable-abi-item)
* [Encoding to Function Data](#encoding-to-function-data)
* [Decoding a Function's Result](#decoding-a-function's-result)
### Instantiating via JSON ABI
An `AbiFunction` can be instantiated from a JSON ABI by using [`AbiFunction.fromAbi`](/api/AbiFunction/fromAbi):
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiFunction.fromAbi(abi, 'bar') // [!code focus]
// ^?
```
### Instantiating via Human-Readable ABI Item
An `AbiFunction` can be instantiated from a human-readable ABI by using [`AbiFunction.from`](/api/AbiFunction/from):
```ts twoslash
import { AbiFunction } from 'ox'
const bar = AbiFunction.from(
'function bar(string a) returns (uint256 x)'
)
bar
//^?
```
### Encoding to Function Data
A Function and its arguments can be ABI-encoded into data using the [`AbiFunction.encodeData`](/api/AbiFunction/encodeData) function. The output of this function can then be passed to `eth_sendTransaction` or `eth_call` as the `data` parameter.
```ts twoslash
import { AbiFunction } from 'ox'
const approve = AbiFunction.from(
'function approve(address, uint256)'
)
const data = AbiFunction.encodeData(
// [!code focus]
approve, // [!code focus]
['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 69420n] // [!code focus]
) // [!code focus]
// @log: '0x095ea7b3000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000000000000010f2c'
```
### Decoding a Function's Result
A Function's result can be ABI-decoded using the [`AbiFunction.decodeResult`](/api/AbiFunction/decodeResult) function.
```ts twoslash
import { AbiFunction } from 'ox'
const data =
'0x000000000000000000000000000000000000000000000000000000000000002a'
// ↑ Example data that could be returned from a contract call via `eth_call`.
const totalSupply = AbiFunction.from(
'function totalSupply() returns (uint256)'
)
const output = AbiFunction.decodeResult(totalSupply, data) // [!code focus]
// @log: 42n
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiFunction.decodeData`](/api/AbiFunction/decodeData) | ABI-decodes function arguments according to the ABI Item's input types (`inputs`). |
| [`AbiFunction.decodeResult`](/api/AbiFunction/decodeResult) | ABI-decodes a function's result according to the ABI Item's output types (`outputs`). |
| [`AbiFunction.encodeData`](/api/AbiFunction/encodeData) | ABI-encodes function arguments (`inputs`), prefixed with the 4 byte function selector. |
| [`AbiFunction.encodeResult`](/api/AbiFunction/encodeResult) | ABI-encodes a function's result (`outputs`). |
| [`AbiFunction.format`](/api/AbiFunction/format) | Formats an [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction) into a **Human Readable ABI Function**. |
| [`AbiFunction.from`](/api/AbiFunction/from) | Parses an arbitrary **JSON ABI Function** or **Human Readable ABI Function** into a typed [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction). |
| [`AbiFunction.fromAbi`](/api/AbiFunction/fromAbi) | Extracts an [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments. |
| [`AbiFunction.getSelector`](/api/AbiFunction/getSelector) | Computes the [4-byte selector](https://solidity-by-example.org/function-selector/) for an [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction). |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunctionabifunction) | Root type for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) with a `function` type. |
| [`AbiFunction.ExtractNames`](/api/AbiFunction/types#abifunctionextractnames) | |
| [`AbiFunction.FromAbi`](/api/AbiFunction/types#abifunctionfromabi) | Extracts an [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction) item from an [`Abi.Abi`](/api/Abi/types#abi), given a name. |
| [`AbiFunction.Name`](/api/AbiFunction/types#abifunctionname) | Extracts the names of all [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction) items in an [`Abi.Abi`](/api/Abi/types#abi). |
# AbiFunction.decodeData
ABI-decodes function arguments according to the ABI Item's input types (`inputs`).
## Imports
:::code-group
```ts [Named]
import { AbiFunction } from 'ox'
```
```ts [Entrypoint]
import * as AbiFunction from 'ox/AbiFunction'
```
:::
## Examples
```ts twoslash
import { AbiFunction } from 'ox'
const approve = AbiFunction.from(
'function approve(address, uint256)'
)
const data = AbiFunction.encodeData(approve, [
'0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
69420n
])
// '0x095ea7b3000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000000000000010f2c'
const input = AbiFunction.decodeData(approve, data) // [!code focus]
// @log: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', 69420n]
```
### ABI-shorthand
You can also specify an entire ABI object and a function name as parameters to [`AbiFunction.decodeData`](/api/AbiFunction/decodeData):
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([...])
const data = '0x...
const input = AbiFunction.decodeData(
abi, // [!code focus]
'approve', // [!code focus]
data
)
// @log: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', 69420n]
```
### ABI selector shorthand
You can also specify an entire ABI object and calldata. The ABI Function is extracted from the 4-byte selector:
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([...])
const data = '0x095ea7b3...
const input = AbiFunction.decodeData(
abi, // [!code focus]
data // [!code focus]
)
// @log: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', 69420n]
```
## Definition
```ts
function decodeData(
abi: abi | Abi.Abi | readonly unknown[],
data: Hex.Hex,
options?: decodeData.Options,
): decodeData.ReturnType
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L129)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### data
* **Type:** `Hex.Hex`
The data to decode.
### options
* **Type:** `decodeData.Options`
* **Optional**
Decoding options.
#### options.checksumAddress
* **Type:** `boolean`
* **Optional**
Whether decoded addresses should be checksummed.
## Return Type
`decodeData.ReturnType>`
# AbiFunction.decodeResult
ABI-decodes a function's result according to the ABI Item's output types (`outputs`).
:::tip
This function is typically used to decode contract function return values (e.g. the response of an `eth_call` or the `input` property of a Transaction).
See the [End-to-end Example](#end-to-end).
:::
## Imports
:::code-group
```ts [Named]
import { AbiFunction } from 'ox'
```
```ts [Entrypoint]
import * as AbiFunction from 'ox/AbiFunction'
```
:::
## Examples
```ts twoslash
import { AbiFunction } from 'ox'
const data =
'0x000000000000000000000000000000000000000000000000000000000000002a'
const totalSupply = AbiFunction.from(
'function totalSupply() returns (uint256)'
)
const output = AbiFunction.decodeResult(totalSupply, data)
// @log: 42n
```
You can extract an ABI Function from a JSON ABI with [`AbiFunction.fromAbi`](/api/AbiFunction/fromAbi):
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const data = '0x000000000000000000000000000000000000000000000000000000000000002a'
const erc20Abi = Abi.from([...]) // [!code hl]
const totalSupply = AbiFunction.fromAbi(erc20Abi, 'totalSupply') // [!code hl]
const output = AbiFunction.decodeResult(totalSupply, data)
// @log: 42n
```
### ABI-shorthand
You can also specify an entire ABI object and a function name as parameters to [`AbiFunction.decodeResult`](/api/AbiFunction/decodeResult):
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const data = '0x000000000000000000000000000000000000000000000000000000000000002a'
const erc20Abi = Abi.from([...])
const output = AbiFunction.decodeResult(
erc20Abi, // [!code focus]
'totalSupply', // [!code focus]
data
)
// @log: 42n
```
### End-to-end
Below is an end-to-end example of using `AbiFunction.decodeResult` to decode the result of a `balanceOf` contract call on the [Wagmi Mint Example contract](https://etherscan.io/address/0xfba3912ca04dd458c843e2ee08967fc04f3579c2).
```ts twoslash
import 'ox/window'
import { Abi, AbiFunction } from 'ox'
// 1. Extract the Function from the Contract's ABI.
const abi = Abi.from([
// ...
{
name: 'balanceOf',
type: 'function',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ name: 'balance', type: 'uint256' }],
stateMutability: 'view'
}
// ...
])
const balanceOf = AbiFunction.fromAbi(abi, 'balanceOf')
// 2. Encode the Function Input.
const data = AbiFunction.encodeData(balanceOf, [
'0xd2135CfB216b74109775236E36d4b433F1DF507B'
])
// 3. Perform the Contract Call.
const response = await window.ethereum!.request({
method: 'eth_call',
params: [
{
data,
to: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2'
}
]
})
// 4. Decode the Function Output. // [!code focus]
const balance = AbiFunction.decodeResult(
balanceOf,
response
) // [!code focus]
// @log: 42n
```
:::note
For simplicity, the above example uses `window.ethereum.request`, but you can use any type of JSON-RPC interface.
:::
## Definition
```ts
function decodeResult(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
data: Hex.Hex,
options?: decodeResult.Options,
): decodeResult.ReturnType
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L383)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
### data
* **Type:** `Hex.Hex`
ABI-encoded function output
### options
* **Type:** `decodeResult.Options`
* **Optional**
Decoding options
#### options.as
* **Type:** `"Array" | "Object" | as`
* **Optional**
Whether the decoded values should be returned as an `Object` or `Array`.
#### options.checksumAddress
* **Type:** `boolean`
* **Optional**
Whether decoded addresses should be checksummed.
## Return Type
Decoded function output
`decodeResult.ReturnType`
# AbiFunction.encodeData
ABI-encodes function arguments (`inputs`), prefixed with the 4 byte function selector.
:::tip
This function is typically used to encode a contract function and its arguments for contract calls (e.g. `data` parameter of an `eth_call` or `eth_sendTransaction`).
See the [End-to-end Example](#end-to-end).
:::
## Imports
:::code-group
```ts [Named]
import { AbiFunction } from 'ox'
```
```ts [Entrypoint]
import * as AbiFunction from 'ox/AbiFunction'
```
:::
## Examples
```ts twoslash
import { AbiFunction } from 'ox'
const approve = AbiFunction.from(
'function approve(address, uint256)'
)
const data = AbiFunction.encodeData(
// [!code focus]
approve, // [!code focus]
['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 69420n] // [!code focus]
) // [!code focus]
// @log: '0x095ea7b3000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000000000000010f2c'
```
You can extract an ABI Function from a JSON ABI with [`AbiFunction.fromAbi`](/api/AbiFunction/fromAbi):
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const erc20Abi = Abi.from([...]) // [!code hl]
const approve = AbiFunction.fromAbi(erc20Abi, 'approve') // [!code hl]
const data = AbiFunction.encodeData(
approve,
['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 69420n]
)
// @log: '0x095ea7b3000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000000000000010f2c'
```
### ABI-shorthand
You can specify an entire ABI object and a function name as parameters to [`AbiFunction.encodeData`](/api/AbiFunction/encodeData):
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const erc20Abi = Abi.from([...])
const data = AbiFunction.encodeData(
erc20Abi, // [!code focus]
'approve', // [!code focus]
['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 69420n]
)
```
### End-to-end
Below is an end-to-end example of using `AbiFunction.encodeData` to encode the input of a `balanceOf` contract call on the [Wagmi Mint Example contract](https://etherscan.io/address/0xfba3912ca04dd458c843e2ee08967fc04f3579c2).
```ts twoslash
import 'ox/window'
import { Abi, AbiFunction } from 'ox'
// 1. Extract the Function from the Contract's ABI.
const abi = Abi.from([
// ...
{
name: 'balanceOf',
type: 'function',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ name: 'balance', type: 'uint256' }],
stateMutability: 'view'
}
// ...
])
const balanceOf = AbiFunction.fromAbi(abi, 'balanceOf')
// 2. Encode the Function Input. // [!code focus]
const data = AbiFunction.encodeData(
// [!code focus]
balanceOf, // [!code focus]
['0xd2135CfB216b74109775236E36d4b433F1DF507B'] // [!code focus]
) // [!code focus]
// 3. Perform the Contract Call.
const response = await window.ethereum!.request({
method: 'eth_call',
params: [
{
data,
to: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2'
}
]
})
// 4. Decode the Function Output.
const balance = AbiFunction.decodeResult(
balanceOf,
response
)
```
:::note
For simplicity, the above example uses `window.ethereum.request`, but you can use any type of JSON-RPC interface.
:::
## Definition
```ts
function encodeData(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
args: encodeData.Args,
): Hex.Hex
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L615)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
### args
* **Type:** `encodeData.Args`
Function arguments
## Return Type
ABI-encoded function name and arguments
`Hex.Hex`
# AbiFunction.encodeResult
ABI-encodes a function's result (`outputs`).
## Imports
:::code-group
```ts [Named]
import { AbiFunction } from 'ox'
```
```ts [Entrypoint]
import * as AbiFunction from 'ox/AbiFunction'
```
:::
## Examples
```ts twoslash
import { AbiFunction } from 'ox'
const totalSupply = AbiFunction.from(
'function totalSupply() returns (uint256)'
)
const output = AbiFunction.decodeResult(
totalSupply,
'0x000000000000000000000000000000000000000000000000000000000000002a'
)
// 42n
const data = AbiFunction.encodeResult(totalSupply, 42n) // [!code focus]
// @log: '0x000000000000000000000000000000000000000000000000000000000000002a'
```
### ABI-shorthand
You can also specify an entire ABI object and a function name as parameters to [`AbiFunction.encodeResult`](/api/AbiFunction/encodeResult):
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([...])
const data = AbiFunction.encodeResult(
abi, // [!code focus]
'totalSupply', // [!code focus]
42n
)
// @log: '0x000000000000000000000000000000000000000000000000000000000000002a'
```
## Definition
```ts
function encodeResult(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
output: encodeResult.Output,
options?: encodeResult.Options,
): Hex.Hex
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L744)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
### output
* **Type:** `encodeResult.Output`
The function output to encode.
### options
* **Type:** `encodeResult.Options`
* **Optional**
Encoding options.
#### options.as
* **Type:** `"Array" | "Object" | as`
* **Optional**
## Return Type
The encoded function output.
`Hex.Hex`
# AbiFunction.format
Formats an [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction) into a **Human Readable ABI Function**.
## Imports
:::code-group
```ts [Named]
import { AbiFunction } from 'ox'
```
```ts [Entrypoint]
import * as AbiFunction from 'ox/AbiFunction'
```
:::
## Examples
```ts twoslash
import { AbiFunction } from 'ox'
const formatted = AbiFunction.format({
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
],
outputs: [{ type: 'bool' }]
})
formatted
// ^?
```
## Definition
```ts
function format(
abiFunction: abiFunction | AbiFunction,
): format.ReturnType
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L866)
## Parameters
### abiFunction
* **Type:** `abiFunction | AbiFunction`
The ABI Function to format.
## Return Type
The formatted ABI Function.
`format.ReturnType`
# AbiFunction.from
Parses an arbitrary **JSON ABI Function** or **Human Readable ABI Function** into a typed [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction).
## Imports
:::code-group
```ts [Named]
import { AbiFunction } from 'ox'
```
```ts [Entrypoint]
import * as AbiFunction from 'ox/AbiFunction'
```
:::
## Examples
### JSON ABIs
```ts twoslash
import { AbiFunction } from 'ox'
const approve = AbiFunction.from({
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
],
outputs: [{ type: 'bool' }]
})
approve
//^?
```
### Human Readable ABIs
A Human Readable ABI can be parsed into a typed ABI object:
```ts twoslash
import { AbiFunction } from 'ox'
const approve = AbiFunction.from(
'function approve(address spender, uint256 amount) returns (bool)' // [!code hl]
)
approve
//^?
```
It is possible to specify `struct`s along with your definitions:
```ts twoslash
import { AbiFunction } from 'ox'
const approve = AbiFunction.from([
'struct Foo { address spender; uint256 amount; }', // [!code hl]
'function approve(Foo foo) returns (bool)'
])
approve
//^?
```
## Definition
```ts
function from(
abiFunction: (abiFunction | AbiFunction | string | readonly string[]) & ((abiFunction extends string ? internal.Signature : never) | (abiFunction extends readonly string[] ? internal.Signatures : never) | AbiFunction),
options?: from.Options,
): from.ReturnType
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L945)
## Parameters
### abiFunction
* **Type:** `(abiFunction | AbiFunction | string | readonly string[]) & ((abiFunction extends string ? internal.Signature : never) | (abiFunction extends readonly string[] ? internal.Signatures : never) | AbiFunction)`
The ABI Function to parse.
### options
* **Type:** `from.Options`
* **Optional**
#### options.prepare
* **Type:** `boolean`
* **Optional**
Whether or not to prepare the extracted function (optimization for encoding performance).
When `true`, the `hash` property is computed and included in the returned value.
## Return Type
Typed ABI Function.
`from.ReturnType`
# AbiFunction.fromAbi
Extracts an [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments.
## Imports
:::code-group
```ts [Named]
import { AbiFunction } from 'ox'
```
```ts [Entrypoint]
import * as AbiFunction from 'ox/AbiFunction'
```
:::
## Examples
### Extracting by Name
ABI Functions can be extracted by their name using the `name` option:
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiFunction.fromAbi(abi, 'foo') // [!code focus]
// ^?
```
### Extracting by Selector
ABI Functions can be extract by their selector when [`Hex.Hex`](/api/Hex/types#hex) is provided to `name`.
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiFunction.fromAbi(abi, '0x095ea7b3') // [!code focus]
// ^?
```
:::note
Extracting via a hex selector is useful when extracting an ABI Function from an `eth_call` RPC response or from a Transaction `input`.
:::
## Definition
```ts
function fromAbi(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
options?: AbiItem.fromAbi.Options>,
): AbiItem.fromAbi.ReturnType
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L1029)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
The ABI to extract from.
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
The name (or selector) of the ABI item to extract.
### options
* **Type:** `AbiItem.fromAbi.Options>`
* **Optional**
Extraction options.
#### options.args
* **Type:** `allArgs | (Widen & (args extends allArgs ? unknown : never))`
* **Optional**
#### options.prepare
* **Type:** `boolean`
* **Optional**
Whether or not to prepare the extracted item (optimization for encoding performance).
When `true`, the `hash` property is computed and included in the returned value.
## Return Type
The ABI item.
`AbiItem.fromAbi.ReturnType`
# AbiFunction.getSelector
Computes the [4-byte selector](https://solidity-by-example.org/function-selector/) for an [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction).
Useful for computing function selectors for calldata.
## Imports
:::code-group
```ts [Named]
import { AbiFunction } from 'ox'
```
```ts [Entrypoint]
import * as AbiFunction from 'ox/AbiFunction'
```
:::
## Examples
```ts twoslash
import { AbiFunction } from 'ox'
const selector = AbiFunction.getSelector(
'function ownerOf(uint256 tokenId)'
)
// @log: '0x6352211e'
```
```ts twoslash
import { AbiFunction } from 'ox'
const selector = AbiFunction.getSelector({
inputs: [{ type: 'uint256' }],
name: 'ownerOf',
outputs: [],
stateMutability: 'view',
type: 'function'
})
// @log: '0x6352211e'
```
## Definition
```ts
function getSelector(
abiItem: string | AbiFunction,
): Hex.Hex
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L1088)
## Parameters
### abiItem
* **Type:** `string | AbiFunction`
The ABI item to compute the selector for.
#### abiItem.hash
* **Type:** `0x${string}`
* **Optional**
#### abiItem.overloads
* **Type:** `readonly any[]`
* **Optional**
## Return Type
The first 4 bytes of the [`Hash.keccak256`](/api/Hash/keccak256) hash of the function signature.
`Hex.Hex`
# AbiFunction Types
## `AbiFunction.AbiFunction`
Root type for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) with a `function` type.
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L14)
## `AbiFunction.ExtractNames`
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L59)
## `AbiFunction.FromAbi`
Extracts an [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction) item from an [`Abi.Abi`](/api/Abi/types#abi), given a name.
### Examples
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([
'function foo(string)',
'function bar(uint256)'
])
type Foo = AbiFunction.FromAbi
// ^?
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L35)
## `AbiFunction.Name`
Extracts the names of all [`AbiFunction.AbiFunction`](/api/AbiFunction/types#abifunction) items in an [`Abi.Abi`](/api/Abi/types#abi).
### Examples
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const abi = Abi.from([
'function foo(string)',
'function bar(uint256)'
])
type names = AbiFunction.Name
// ^?
```
**Source:** [src/core/AbiFunction.ts](https://github.com/wevm/ox/blob/main/src/core/AbiFunction.ts#L56)
# AbiItem
Utilities & types for working with [ABI Items](https://docs.soliditylang.org/en/latest/abi-spec.html#json)
The `AbiItem` type is a super-type of:
* [`AbiConstructor`](/api/AbiConstructor)
* [`AbiFunction`](/api/AbiFunction)
* [`AbiEvent`](/api/AbiEvent)
* [`AbiError`](/api/AbiError)
## Examples
Below are some examples demonstrating common usages of the `AbiItem` module:
* [Instantiating via JSON ABI](#instantiating-via-json-abi)
* [Instantiating via Human-Readable ABI Item](#instantiating-via-human-readable-abi-item)
* [Formatting ABI Items](#formatting-abi-items)
### Instantiating via JSON ABI
An `AbiItem` can be instantiated from a JSON ABI by using [`AbiItem.fromAbi`](/api/AbiItem/fromAbi):
```ts twoslash
import { Abi, AbiItem } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiItem.fromAbi(abi, 'Transfer') // [!code focus]
// ^?
```
### Instantiating via Human-Readable ABI Item
A Human Readable ABI can be parsed into a typed ABI object:
```ts twoslash
import { AbiItem } from 'ox'
const abiItem = AbiItem.from(
'function approve(address spender, uint256 amount) returns (bool)'
)
abiItem
//^?
```
### Formatting ABI Items
An `AbiItem` can be formatted into a human-readable ABI Item by using [`AbiItem.format`](/api/AbiItem/format):
```ts twoslash
import { AbiItem } from 'ox'
const abiItem = AbiItem.from(
'function approve(address spender, uint256 amount) returns (bool)'
)
const formatted = AbiItem.format(abiItem)
// @log: 'function approve(address spender, uint256 amount) returns (bool)'
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiItem.format`](/api/AbiItem/format) | Formats an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) into a **Human Readable ABI Item**. |
| [`AbiItem.from`](/api/AbiItem/from) | Parses an arbitrary **JSON ABI Item** or **Human Readable ABI Item** into a typed [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem). |
| [`AbiItem.fromAbi`](/api/AbiItem/fromAbi) | Extracts an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments. |
| [`AbiItem.getSelector`](/api/AbiItem/getSelector) | Computes the [4-byte selector](https://solidity-by-example.org/function-selector/) for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem). |
| [`AbiItem.getSignature`](/api/AbiItem/getSignature) | Computes the stringified signature for a given [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem). |
| [`AbiItem.getSignatureHash`](/api/AbiItem/getSignatureHash) | Computes the signature hash for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem). |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiItem.AmbiguityError`](/api/AbiItem/errors#abiitemambiguityerror) | Throws when ambiguous types are found on overloaded ABI items. |
| [`AbiItem.InvalidAbiItemError`](/api/AbiItem/errors#abiiteminvalidabiitemerror) | |
| [`AbiItem.InvalidSelectorSizeError`](/api/AbiItem/errors#abiiteminvalidselectorsizeerror) | Throws when the selector size is invalid. |
| [`AbiItem.NotFoundError`](/api/AbiItem/errors#abiitemnotfounderror) | Throws when an ABI item is not found in the ABI. |
| [`AbiItem.UnknownSolidityTypeError`](/api/AbiItem/errors#abiitemunknownsoliditytypeerror) | |
| [`AbiItem.UnknownTypeError`](/api/AbiItem/errors#abiitemunknowntypeerror) | |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiItem.AbiItem`](/api/AbiItem/types#abiitemabiitem) | Root type for an item on an [`Abi.Abi`](/api/Abi/types#abi). |
| [`AbiItem.ExtractNames`](/api/AbiItem/types#abiitemextractnames) | |
| [`AbiItem.FromAbi`](/api/AbiItem/types#abiitemfromabi) | Extracts an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) item from an [`Abi.Abi`](/api/Abi/types#abi), given a name. |
| [`AbiItem.Name`](/api/AbiItem/types#abiitemname) | Extracts the names of all [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) items in an [`Abi.Abi`](/api/Abi/types#abi). |
# AbiItem.format
Formats an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) into a **Human Readable ABI Item**.
## Imports
:::code-group
```ts [Named]
import { AbiItem } from 'ox'
```
```ts [Entrypoint]
import * as AbiItem from 'ox/AbiItem'
```
:::
## Examples
```ts twoslash
import { AbiItem } from 'ox'
const formatted = AbiItem.format({
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
],
outputs: [{ type: 'bool' }]
})
formatted
// ^?
```
## Definition
```ts
function format(
abiItem: abiItem | AbiItem,
): format.ReturnType
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L97)
## Parameters
### abiItem
* **Type:** `abiItem | AbiItem`
The ABI Item to format.
## Return Type
The formatted ABI Item .
`format.ReturnType`
# AbiItem.from
Parses an arbitrary **JSON ABI Item** or **Human Readable ABI Item** into a typed [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem).
## Imports
:::code-group
```ts [Named]
import { AbiItem } from 'ox'
```
```ts [Entrypoint]
import * as AbiItem from 'ox/AbiItem'
```
:::
## Examples
### JSON ABIs
```ts twoslash
import { AbiItem } from 'ox'
const abiItem = AbiItem.from({
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
],
outputs: [{ type: 'bool' }]
})
abiItem
//^?
```
### Human Readable ABIs
A Human Readable ABI can be parsed into a typed ABI object:
```ts twoslash
import { AbiItem } from 'ox'
const abiItem = AbiItem.from(
'function approve(address spender, uint256 amount) returns (bool)' // [!code hl]
)
abiItem
//^?
```
It is possible to specify `struct`s along with your definitions:
```ts twoslash
import { AbiItem } from 'ox'
const abiItem = AbiItem.from([
'struct Foo { address spender; uint256 amount; }', // [!code hl]
'function approve(Foo foo) returns (bool)'
])
abiItem
//^?
```
## Definition
```ts
function from(
abiItem: (abiItem | AbiItem | string | readonly string[]) & ((abiItem extends string ? internal.Signature : never) | (abiItem extends readonly string[] ? internal.Signatures : never) | AbiItem),
options?: from.Options,
): from.ReturnType
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L176)
## Parameters
### abiItem
* **Type:** `(abiItem | AbiItem | string | readonly string[]) & ((abiItem extends string ? internal.Signature : never) | (abiItem extends readonly string[] ? internal.Signatures : never) | AbiItem)`
The ABI Item to parse.
### options
* **Type:** `from.Options`
* **Optional**
#### options.prepare
* **Type:** `boolean`
* **Optional**
Whether or not to prepare the extracted item (optimization for encoding performance).
When `true`, the `hash` property is computed and included in the returned value.
## Return Type
The typed ABI Item.
`from.ReturnType`
# AbiItem.fromAbi
Extracts an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) from an [`Abi.Abi`](/api/Abi/types#abi) given a name and optional arguments.
## Imports
:::code-group
```ts [Named]
import { AbiItem } from 'ox'
```
```ts [Entrypoint]
import * as AbiItem from 'ox/AbiItem'
```
:::
## Examples
ABI Items can be extracted by their name using the `name` option:
```ts twoslash
import { Abi, AbiItem } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiItem.fromAbi(abi, 'Transfer') // [!code focus]
// ^?
```
### Extracting by Selector
ABI Items can be extract by their selector when [`Hex.Hex`](/api/Hex/types#hex) is provided to `name`.
```ts twoslash
import { Abi, AbiItem } from 'ox'
const abi = Abi.from([
'function foo()',
'event Transfer(address owner, address to, uint256 tokenId)',
'function bar(string a) returns (uint256 x)'
])
const item = AbiItem.fromAbi(abi, '0x095ea7b3') // [!code focus]
// ^?
```
:::note
Extracting via a hex selector is useful when extracting an ABI Item from an `eth_call` RPC response, a Transaction `input`, or from Event Log `topics`.
:::
## Definition
```ts
function fromAbi(
abi: abi | Abi.Abi | readonly unknown[],
name: Hex.Hex | (name extends allNames ? name : never),
options?: fromAbi.Options,
): fromAbi.ReturnType
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L271)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
The ABI to extract from.
### name
* **Type:** `Hex.Hex | (name extends allNames ? name : never)`
The name (or selector) of the ABI item to extract.
### options
* **Type:** `fromAbi.Options`
* **Optional**
Extraction options.
#### options.args
* **Type:** `allArgs | (Widen & (args extends allArgs ? unknown : never))`
* **Optional**
#### options.prepare
* **Type:** `boolean`
* **Optional**
Whether or not to prepare the extracted item (optimization for encoding performance).
When `true`, the `hash` property is computed and included in the returned value.
## Return Type
The ABI item.
`fromAbi.ReturnType`
# AbiItem.getSelector
Computes the [4-byte selector](https://solidity-by-example.org/function-selector/) for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem).
Useful for computing function selectors for calldata.
## Imports
:::code-group
```ts [Named]
import { AbiItem } from 'ox'
```
```ts [Entrypoint]
import * as AbiItem from 'ox/AbiItem'
```
:::
## Examples
```ts twoslash
import { AbiItem } from 'ox'
const selector = AbiItem.getSelector(
'function ownerOf(uint256 tokenId)'
)
// @log: '0x6352211e'
```
```ts twoslash
// @noErrors
import { Abi, AbiItem } from 'ox'
const erc20Abi = Abi.from([...])
const selector = AbiItem.getSelector(erc20Abi, 'ownerOf')
// @log: '0x6352211e'
```
```ts twoslash
import { AbiItem } from 'ox'
const selector = AbiItem.getSelector({
inputs: [{ type: 'uint256' }],
name: 'ownerOf',
outputs: [],
stateMutability: 'view',
type: 'function'
})
// @log: '0x6352211e'
```
## Definition
```ts
function getSelector(
abi: abi | Abi.Abi | readonly unknown[],
name: name,
): Hex.Hex
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L478)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `name`
## Return Type
The first 4 bytes of the [`Hash.keccak256`](/api/Hash/keccak256) hash of the function signature.
`Hex.Hex`
# AbiItem.getSignature
Computes the stringified signature for a given [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem).
## Imports
:::code-group
```ts [Named]
import { AbiItem } from 'ox'
```
```ts [Entrypoint]
import * as AbiItem from 'ox/AbiItem'
```
:::
## Examples
```ts twoslash
import { AbiItem } from 'ox'
const signature = AbiItem.getSignature(
'function ownerOf(uint256 tokenId)'
)
// @log: 'ownerOf(uint256)'
```
```ts twoslash
// @noErrors
import { Abi, AbiItem } from 'ox'
const erc20Abi = Abi.from([...])
const signature = AbiItem.getSignature(erc20Abi, 'ownerOf')
// @log: 'ownerOf(uint256)'
```
```ts twoslash
import { AbiItem } from 'ox'
const signature = AbiItem.getSignature({
name: 'ownerOf',
type: 'function',
inputs: [{ name: 'tokenId', type: 'uint256' }],
outputs: [],
stateMutability: 'view'
})
// @log: 'ownerOf(uint256)'
```
## Definition
```ts
function getSignature(
abi: abi | Abi.Abi | readonly unknown[],
name: name,
): string
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L547)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `name`
## Return Type
The stringified signature of the ABI Item.
`string`
# AbiItem.getSignatureHash
Computes the signature hash for an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem).
Useful for computing Event Topic values.
## Imports
:::code-group
```ts [Named]
import { AbiItem } from 'ox'
```
```ts [Entrypoint]
import * as AbiItem from 'ox/AbiItem'
```
:::
## Examples
```ts twoslash
import { AbiItem } from 'ox'
const hash = AbiItem.getSignatureHash(
'event Transfer(address indexed from, address indexed to, uint256 amount)'
)
// @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
```
```ts twoslash
// @noErrors
import { Abi, AbiItem } from 'ox'
const erc20Abi = Abi.from([...])
const hash = AbiItem.getSignatureHash(erc20Abi, 'Transfer')
// @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
```
```ts twoslash
import { AbiItem } from 'ox'
const hash = AbiItem.getSignatureHash({
name: 'Transfer',
type: 'event',
inputs: [
{ name: 'from', type: 'address', indexed: true },
{ name: 'to', type: 'address', indexed: true },
{ name: 'amount', type: 'uint256', indexed: false }
]
})
// @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
```
## Definition
```ts
function getSignatureHash(
abi: abi | Abi.Abi | readonly unknown[],
name: name,
): Hex.Hex
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L623)
## Parameters
### abi
* **Type:** `abi | Abi.Abi | readonly unknown[]`
### name
* **Type:** `name`
## Return Type
The [`Hash.keccak256`](/api/Hash/keccak256) hash of the ABI item's signature.
`Hex.Hex`
# AbiItem Errors
## `AbiItem.AmbiguityError`
Throws when ambiguous types are found on overloaded ABI items.
### Examples
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const foo = Abi.from([
'function foo(address)',
'function foo(bytes20)'
])
AbiFunction.fromAbi(foo, 'foo', {
args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']
})
// @error: AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items.
// @error: `bytes20` in `foo(bytes20)`, and
// @error: `address` in `foo(address)`
// @error: These types encode differently and cannot be distinguished at runtime.
// @error: Remove one of the ambiguous items in the ABI.
```
### Solution
Remove one of the ambiguous types from the ABI.
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const foo = Abi.from([
'function foo(address)',
'function foo(bytes20)' // [!code --]
])
AbiFunction.fromAbi(foo, 'foo', {
args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']
})
// @error: AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items.
// @error: `bytes20` in `foo(bytes20)`, and
// @error: `address` in `foo(address)`
// @error: These types encode differently and cannot be distinguished at runtime.
// @error: Remove one of the ambiguous items in the ABI.
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L696)
## `AbiItem.InvalidAbiItemError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L5)
## `AbiItem.InvalidSelectorSizeError`
Throws when the selector size is invalid.
### Examples
```ts twoslash
import { Abi, AbiFunction } from 'ox'
const foo = Abi.from([
'function foo(address)',
'function bar(uint)'
])
AbiFunction.fromAbi(foo, '0xaaa')
// @error: AbiItem.InvalidSelectorSizeError: Selector size is invalid. Expected 4 bytes. Received 2 bytes ("0xaaa").
```
### Solution
Ensure the selector size is 4 bytes.
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const foo = Abi.from([
'function foo(address)',
'function bar(uint)'
])
AbiFunction.fromAbi(foo, '0x7af82b1a')
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L797)
## `AbiItem.NotFoundError`
Throws when an ABI item is not found in the ABI.
### Examples
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const foo = Abi.from([
'function foo(address)',
'function bar(uint)'
])
AbiFunction.fromAbi(foo, 'baz')
// @error: AbiItem.NotFoundError: ABI function with name "baz" not found.
```
### Solution
Ensure the ABI item exists on the ABI.
```ts twoslash
// @noErrors
import { Abi, AbiFunction } from 'ox'
const foo = Abi.from([
'function foo(address)',
'function bar(uint)',
'function baz(bool)' // [!code ++]
])
AbiFunction.fromAbi(foo, 'baz')
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L747)
## `AbiItem.UnknownSolidityTypeError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L28)
## `AbiItem.UnknownTypeError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L16)
# AbiItem Types
## `AbiItem.AbiItem`
Root type for an item on an [`Abi.Abi`](/api/Abi/types#abi).
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L11)
## `AbiItem.ExtractNames`
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L61)
## `AbiItem.FromAbi`
Extracts an [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) item from an [`Abi.Abi`](/api/Abi/types#abi), given a name.
### Examples
```ts twoslash
import { Abi, AbiItem } from 'ox'
const abi = Abi.from([
'error Foo(string)',
'function foo(string)',
'event Bar(uint256)'
])
type Foo = AbiItem.FromAbi
// ^?
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L36)
## `AbiItem.Name`
Extracts the names of all [`AbiItem.AbiItem`](/api/AbiItem/types#abiitem) items in an [`Abi.Abi`](/api/Abi/types#abi).
### Examples
```ts twoslash
import { Abi, AbiItem } from 'ox'
const abi = Abi.from([
'error Foo(string)',
'function foo(string)',
'event Bar(uint256)'
])
type names = AbiItem.Name
// ^?
```
**Source:** [src/core/AbiItem.ts](https://github.com/wevm/ox/blob/main/src/core/AbiItem.ts#L58)
# AbiParameter
Utilities & types for working with a single [ABI Parameter](https://docs.soliditylang.org/en/latest/abi-spec.html#types).
## Examples
Below are some examples demonstrating common usages of the `AbiParameter` module:
* [Instantiating Human Readable ABI Parameters](#instantiating-human-readable-abi-parameters)
* [Formatting ABI Parameters](#formatting-abi-parameters)
### Instantiating Human Readable ABI Parameters
A Human Readable ABI Parameter can be instantiated by using [`AbiParameter.from`](/api/AbiParameter/from):
```ts twoslash
import { AbiParameter } from 'ox'
const parameter = AbiParameter.from('address spender')
parameter
//^?
```
### Formatting ABI Parameters
An ABI Parameter can be formatted into a human-readable ABI Parameter by using [`AbiParameter.format`](/api/AbiParameter/format):
```ts twoslash
import { AbiParameter } from 'ox'
const formatted = AbiParameter.format({
name: 'spender',
type: 'address'
})
formatted
// ^?
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiParameter.format`](/api/AbiParameter/format) | Formats an [`AbiParameter.AbiParameter`](/api/AbiParameter/types#abiparameter) into a **Human Readable ABI Parameter**. |
| [`AbiParameter.from`](/api/AbiParameter/from) | Parses an arbitrary **JSON ABI Parameter** or **Human Readable ABI Parameter** into a typed [`AbiParameter.AbiParameter`](/api/AbiParameter/types#abiparameter). |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiParameter.InvalidAbiParameterError`](/api/AbiParameter/errors#abiparameterinvalidabiparametererror) | |
| [`AbiParameter.InvalidAbiTypeParameterError`](/api/AbiParameter/errors#abiparameterinvalidabitypeparametererror) | |
| [`AbiParameter.InvalidFunctionModifierError`](/api/AbiParameter/errors#abiparameterinvalidfunctionmodifiererror) | |
| [`AbiParameter.InvalidModifierError`](/api/AbiParameter/errors#abiparameterinvalidmodifiererror) | |
| [`AbiParameter.InvalidParameterError`](/api/AbiParameter/errors#abiparameterinvalidparametererror) | |
| [`AbiParameter.InvalidParenthesisError`](/api/AbiParameter/errors#abiparameterinvalidparenthesiserror) | |
| [`AbiParameter.SolidityProtectedKeywordError`](/api/AbiParameter/errors#abiparametersolidityprotectedkeyworderror) | |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiParameter.AbiEventParameter`](/api/AbiParameter/types#abiparameterabieventparameter) | A parameter on an ABI event. |
| [`AbiParameter.AbiParameter`](/api/AbiParameter/types#abiparameterabiparameter) | Root type for an ABI parameter. |
# AbiParameter.format
Formats an [`AbiParameter.AbiParameter`](/api/AbiParameter/types#abiparameter) into a **Human Readable ABI Parameter**.
## Imports
:::code-group
```ts [Named]
import { AbiParameter } from 'ox'
```
```ts [Entrypoint]
import * as AbiParameter from 'ox/AbiParameter'
```
:::
## Examples
```ts twoslash
import { AbiParameter } from 'ox'
const formatted = AbiParameter.format({
name: 'spender',
type: 'address'
})
formatted
// ^?
```
## Definition
```ts
function format(
parameter: parameter | AbiParameter | AbiEventParameter,
): format.ReturnType
```
**Source:** [src/core/AbiParameter.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameter.ts#L41)
## Parameters
### parameter
* **Type:** `parameter | AbiParameter | AbiEventParameter`
The ABI Parameter to format.
## Return Type
The formatted ABI Parameter.
`format.ReturnType`
# AbiParameter.from
Parses an arbitrary **JSON ABI Parameter** or **Human Readable ABI Parameter** into a typed [`AbiParameter.AbiParameter`](/api/AbiParameter/types#abiparameter).
## Imports
:::code-group
```ts [Named]
import { AbiParameter } from 'ox'
```
```ts [Entrypoint]
import * as AbiParameter from 'ox/AbiParameter'
```
:::
## Examples
### JSON Parameters
```ts twoslash
import { AbiParameter } from 'ox'
const parameter = AbiParameter.from({
name: 'spender',
type: 'address'
})
parameter
//^?
```
### Human Readable Parameters
```ts twoslash
import { AbiParameter } from 'ox'
const parameter = AbiParameter.from('address spender')
parameter
//^?
```
It is possible to specify `struct`s along with your definition:
```ts twoslash
import { AbiParameter } from 'ox'
const parameter = AbiParameter.from([
'struct Foo { address spender; uint256 amount; }',
'Foo foo'
])
parameter
//^?
```
## Definition
```ts
function from(
parameter: parameter | AbiParameter | string | readonly string[],
): from.ReturnType
```
**Source:** [src/core/AbiParameter.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameter.ts#L105)
## Parameters
### parameter
* **Type:** `parameter | AbiParameter | string | readonly string[]`
The ABI Parameter to parse.
## Return Type
The typed ABI Parameter.
`from.ReturnType`
# AbiParameter Errors
## `AbiParameter.InvalidAbiParameterError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L38)
## `AbiParameter.InvalidAbiTypeParameterError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L130)
## `AbiParameter.InvalidFunctionModifierError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L106)
## `AbiParameter.InvalidModifierError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L83)
## `AbiParameter.InvalidParameterError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L60)
## `AbiParameter.InvalidParenthesisError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L182)
## `AbiParameter.SolidityProtectedKeywordError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L70)
# AbiParameter Types
## `AbiParameter.AbiEventParameter`
A parameter on an ABI event.
**Source:** [src/core/AbiParameter.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameter.ts#L10)
## `AbiParameter.AbiParameter`
Root type for an ABI parameter.
**Source:** [src/core/AbiParameter.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameter.ts#L7)
# AbiParameters
Utilities & types for encoding, decoding, and working with [ABI Parameters](https://docs.soliditylang.org/en/latest/abi-spec.html#types)
## Examples
Below are some examples demonstrating common usages of the `AbiParameters` module:
* [Encoding ABI Parameters](#encoding-abi-parameters)
* [Decoding ABI Parameters](#decoding-abi-parameters)
* [JSON-ABI Parameters](#json-abi-parameters)
* [Human Readable ABI Parameters](#human-readable-abi-parameters)
### Encoding ABI Parameters
ABI Parameters can be ABI-encoded as per the [Application Binary Interface (ABI) Specification](https://docs.soliditylang.org/en/latest/abi-spec) using [`AbiParameters.encode`](/api/AbiParameters/encode):
```ts twoslash
import { AbiParameters } from 'ox'
const data = AbiParameters.encode(
AbiParameters.from('string, uint, bool'),
['wagmi', 420n, true]
)
```
:::tip
The example above uses [`AbiParameters.from`](/api/AbiParameters/from) to specify human-readable ABI Parameters.
However, you can also pass JSON-ABI Parameters:
```ts
import { AbiParameters } from 'ox'
const data = AbiParameters.encode(
[{ type: 'string' }, { type: 'uint' }, { type: 'bool' }],
['wagmi', 420n, true]
)
```
:::
### Decoding ABI Parameters
ABI-encoded data can be decoded using [`AbiParameters.decode`](/api/AbiParameters/decode):
```ts twoslash
import { AbiParameters } from 'ox'
const data = AbiParameters.decode(
AbiParameters.from('string, uint, bool'),
'0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000'
)
// @log: ['wagmi', 420n, true]
```
### JSON-ABI Parameters
JSON-ABI Parameters can be instantiated using [`AbiParameters.from`](/api/AbiParameters/from):
```ts twoslash
import { AbiParameters } from 'ox'
const parameters = AbiParameters.from([
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
])
parameters
//^?
```
### Human Readable ABI Parameters
Human Readable ABI Parameters can be instantiated using [`AbiParameters.from`](/api/AbiParameters/from):
```ts twoslash
import { AbiParameters } from 'ox'
const parameters = AbiParameters.from(
'address spender, uint256 amount'
)
parameters
//^?
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiParameters.decode`](/api/AbiParameters/decode) | Decodes ABI-encoded data into its respective primitive values based on ABI Parameters. |
| [`AbiParameters.encode`](/api/AbiParameters/encode) | Encodes primitive values into ABI encoded data as per the [Application Binary Interface (ABI) Specification](https://docs.soliditylang.org/en/latest/abi-spec). |
| [`AbiParameters.encodePacked`](/api/AbiParameters/encodePacked) | Encodes an array of primitive values to a [packed ABI encoding](https://docs.soliditylang.org/en/latest/abi-spec.html#non-standard-packed-mode). |
| [`AbiParameters.format`](/api/AbiParameters/format) | Formats [`AbiParameters.AbiParameters`](/api/AbiParameters/types#abiparameters) into **Human Readable ABI Parameters**. |
| [`AbiParameters.from`](/api/AbiParameters/from) | Parses arbitrary **JSON ABI Parameters** or **Human Readable ABI Parameters** into typed [`AbiParameters.AbiParameters`](/api/AbiParameters/types#abiparameters). |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiParameters.ArrayLengthMismatchError`](/api/AbiParameters/errors#abiparametersarraylengthmismatcherror) | The length of the array value does not match the length specified in the corresponding ABI parameter. |
| [`AbiParameters.BytesSizeMismatchError`](/api/AbiParameters/errors#abiparametersbytessizemismatcherror) | The size of the bytes value does not match the size specified in the corresponding ABI parameter. |
| [`AbiParameters.DataSizeTooSmallError`](/api/AbiParameters/errors#abiparametersdatasizetoosmallerror) | Throws when the data size is too small for the given parameters. |
| [`AbiParameters.InvalidAbiParametersError`](/api/AbiParameters/errors#abiparametersinvalidabiparameterserror) | |
| [`AbiParameters.InvalidAbiTypeParameterError`](/api/AbiParameters/errors#abiparametersinvalidabitypeparametererror) | |
| [`AbiParameters.InvalidArrayError`](/api/AbiParameters/errors#abiparametersinvalidarrayerror) | The value provided is not a valid array as specified in the corresponding ABI parameter. |
| [`AbiParameters.InvalidFunctionModifierError`](/api/AbiParameters/errors#abiparametersinvalidfunctionmodifiererror) | |
| [`AbiParameters.InvalidModifierError`](/api/AbiParameters/errors#abiparametersinvalidmodifiererror) | |
| [`AbiParameters.InvalidParameterError`](/api/AbiParameters/errors#abiparametersinvalidparametererror) | |
| [`AbiParameters.InvalidParenthesisError`](/api/AbiParameters/errors#abiparametersinvalidparenthesiserror) | |
| [`AbiParameters.InvalidTypeError`](/api/AbiParameters/errors#abiparametersinvalidtypeerror) | Throws when the ABI parameter type is invalid. |
| [`AbiParameters.LengthMismatchError`](/api/AbiParameters/errors#abiparameterslengthmismatcherror) | The length of the values to encode does not match the length of the ABI parameters. |
| [`AbiParameters.SolidityProtectedKeywordError`](/api/AbiParameters/errors#abiparameterssolidityprotectedkeyworderror) | |
| [`AbiParameters.ZeroDataError`](/api/AbiParameters/errors#abiparameterszerodataerror) | Throws when zero data is provided, but data is expected. |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AbiParameters.AbiParameters`](/api/AbiParameters/types#abiparametersabiparameters) | Root type for ABI parameters. |
| [`AbiParameters.PackedAbiType`](/api/AbiParameters/types#abiparameterspackedabitype) | A packed ABI type. |
| [`AbiParameters.Parameter`](/api/AbiParameters/types#abiparametersparameter) | A parameter on an [`AbiParameters.AbiParameters`](/api/AbiParameters/types#abiparameters). |
# AbiParameters.decode
Decodes ABI-encoded data into its respective primitive values based on ABI Parameters.
## Imports
:::code-group
```ts [Named]
import { AbiParameters } from 'ox'
```
```ts [Entrypoint]
import * as AbiParameters from 'ox/AbiParameters'
```
:::
## Examples
```ts twoslash
import { AbiParameters } from 'ox'
const data = AbiParameters.decode(
AbiParameters.from(['string', 'uint', 'bool']),
'0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000'
)
// @log: ['wagmi', 420n, true]
```
### JSON Parameters
You can pass **JSON ABI** Parameters:
```ts twoslash
import { AbiParameters } from 'ox'
const data = AbiParameters.decode(
[
{ name: 'x', type: 'string' },
{ name: 'y', type: 'uint' },
{ name: 'z', type: 'bool' }
],
'0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000'
)
// @log: ['wagmi', 420n, true]
```
## Definition
```ts
function decode(
parameters: parameters,
data: Bytes.Bytes | Hex.Hex,
options?: decode.Options,
): decode.ReturnType
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L75)
## Parameters
### parameters
* **Type:** `parameters`
The set of ABI parameters to decode, in the shape of the `inputs` or `outputs` attribute of an ABI Item. These parameters must include valid [ABI types](https://docs.soliditylang.org/en/latest/types.html).
### data
* **Type:** `Bytes.Bytes | Hex.Hex`
ABI encoded data.
### options
* **Type:** `decode.Options`
* **Optional**
Decoding options.
#### options.as
* **Type:** `"Array" | "Object" | as`
* **Optional**
Whether the decoded values should be returned as an `Object` or `Array`.
#### options.checksumAddress
* **Type:** `boolean`
* **Optional**
Whether decoded addresses should be checksummed.
## Return Type
Array of decoded values.
`decode.ReturnType`
# AbiParameters.encode
Encodes primitive values into ABI encoded data as per the [Application Binary Interface (ABI) Specification](https://docs.soliditylang.org/en/latest/abi-spec).
## Imports
:::code-group
```ts [Named]
import { AbiParameters } from 'ox'
```
```ts [Entrypoint]
import * as AbiParameters from 'ox/AbiParameters'
```
:::
## Examples
```ts twoslash
import { AbiParameters } from 'ox'
const data = AbiParameters.encode(
AbiParameters.from(['string', 'uint', 'bool']),
['wagmi', 420n, true]
)
```
### JSON Parameters
Specify **JSON ABI** Parameters as schema:
```ts twoslash
import { AbiParameters } from 'ox'
const data = AbiParameters.encode(
[
{ type: 'string', name: 'name' },
{ type: 'uint', name: 'age' },
{ type: 'bool', name: 'isOwner' }
],
['wagmi', 420n, true]
)
```
## Definition
```ts
function encode(
parameters: parameters,
values: parameters extends AbiParameters ? internal.ToPrimitiveTypes : never,
options?: encode.Options,
): Hex.Hex
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L205)
## Parameters
### parameters
* **Type:** `parameters`
The set of ABI parameters to encode, in the shape of the `inputs` or `outputs` attribute of an ABI Item. These parameters must include valid [ABI types](https://docs.soliditylang.org/en/latest/types.html).
### values
* **Type:** `parameters extends AbiParameters ? internal.ToPrimitiveTypes : never`
The set of primitive values that correspond to the ABI types defined in `parameters`.
### options
* **Type:** `encode.Options`
* **Optional**
#### options.checksumAddress
* **Type:** `boolean`
* **Optional**
Whether addresses should be checked against their checksum.
## Return Type
ABI encoded data.
`Hex.Hex`
# AbiParameters.encodePacked
Encodes an array of primitive values to a [packed ABI encoding](https://docs.soliditylang.org/en/latest/abi-spec.html#non-standard-packed-mode).
## Imports
:::code-group
```ts [Named]
import { AbiParameters } from 'ox'
```
```ts [Entrypoint]
import * as AbiParameters from 'ox/AbiParameters'
```
:::
## Examples
```ts twoslash
import { AbiParameters } from 'ox'
const encoded = AbiParameters.encodePacked(
['address', 'string'],
[
'0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
'hello world'
]
)
// @log: '0xd8da6bf26964af9d7eed9e03e53415d37aa9604568656c6c6f20776f726c64'
```
## Definition
```ts
function encodePacked(
types: packedAbiTypes,
values: encodePacked.Values,
): Hex.Hex
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L258)
## Parameters
### types
* **Type:** `packedAbiTypes`
Set of ABI types to pack encode.
### values
* **Type:** `encodePacked.Values`
The set of primitive values that correspond to the ABI types defined in `types`.
#### values.type
* **Type:** `packedAbiTypes[key]`
## Return Type
The encoded packed data.
`Hex.Hex`
# AbiParameters.format
Formats [`AbiParameters.AbiParameters`](/api/AbiParameters/types#abiparameters) into **Human Readable ABI Parameters**.
## Imports
:::code-group
```ts [Named]
import { AbiParameters } from 'ox'
```
```ts [Entrypoint]
import * as AbiParameters from 'ox/AbiParameters'
```
:::
## Examples
```ts twoslash
import { AbiParameters } from 'ox'
const formatted = AbiParameters.format([
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
])
formatted
// ^?
```
## Definition
```ts
function format(
parameters: parameters | readonly [
Parameter | abitype.AbiEventParameter,
...(readonly (Parameter | abitype.AbiEventParameter)[])
],
): format.ReturnType
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L379)
## Parameters
### parameters
* **Type:** `parameters | readonly [
Parameter | abitype.AbiEventParameter,
...(readonly (Parameter | abitype.AbiEventParameter)[])
]`
The ABI Parameters to format.
## Return Type
The formatted ABI Parameters .
`format.ReturnType`
# AbiParameters.from
Parses arbitrary **JSON ABI Parameters** or **Human Readable ABI Parameters** into typed [`AbiParameters.AbiParameters`](/api/AbiParameters/types#abiparameters).
## Imports
:::code-group
```ts [Named]
import { AbiParameters } from 'ox'
```
```ts [Entrypoint]
import * as AbiParameters from 'ox/AbiParameters'
```
:::
## Examples
### JSON Parameters
```ts twoslash
import { AbiParameters } from 'ox'
const parameters = AbiParameters.from([
{
name: 'spender',
type: 'address'
},
{
name: 'amount',
type: 'uint256'
}
])
parameters
//^?
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
```
### Human Readable Parameters
Human Readable ABI Parameters can be parsed into a typed [`AbiParameters.AbiParameters`](/api/AbiParameters/types#abiparameters):
```ts twoslash
import { AbiParameters } from 'ox'
const parameters = AbiParameters.from(
'address spender, uint256 amount'
)
parameters
//^?
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
```
It is possible to specify `struct`s along with your definitions:
```ts twoslash
import { AbiParameters } from 'ox'
const parameters = AbiParameters.from([
'struct Foo { address spender; uint256 amount; }', // [!code hl]
'Foo foo, address bar'
])
parameters
//^?
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
```
## Definition
```ts
function from(
parameters: parameters | AbiParameters | string | readonly string[],
): from.ReturnType
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L514)
## Parameters
### parameters
* **Type:** `parameters | AbiParameters | string | readonly string[]`
The ABI Parameters to parse.
## Return Type
The typed ABI Parameters.
`from.ReturnType`
# AbiParameters Errors
## `AbiParameters.ArrayLengthMismatchError`
The length of the array value does not match the length specified in the corresponding ABI parameter.
### Example
```ts twoslash
// @noErrors
import { AbiParameters } from 'ox'
// ---cut---
AbiParameters.encode(AbiParameters.from('uint256[3]'), [
[69n, 420n]
])
// ↑ expected: 3 ↑ ❌ length: 2
// @error: AbiParameters.ArrayLengthMismatchError: ABI encoding array length mismatch
// @error: for type `uint256[3]`. Expected: `3`. Given: `2`.
```
### Solution
Pass an array of the correct length.
```ts twoslash
import { AbiParameters } from 'ox'
// ---cut---
AbiParameters.encode(AbiParameters.from(['uint256[3]']), [
[69n, 420n, 69n]
])
// ↑ ✅ length: 3
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L651)
## `AbiParameters.BytesSizeMismatchError`
The size of the bytes value does not match the size specified in the corresponding ABI parameter.
### Example
```ts twoslash
// @noErrors
import { AbiParameters } from 'ox'
// ---cut---
AbiParameters.encode(AbiParameters.from('bytes8'), [
['0xdeadbeefdeadbeefdeadbeef']
])
// ↑ expected: 8 bytes ↑ ❌ size: 12 bytes
// @error: BytesSizeMismatchError: Size of bytes "0xdeadbeefdeadbeefdeadbeef"
// @error: (bytes12) does not match expected size (bytes8).
```
### Solution
Pass a bytes value of the correct size.
```ts twoslash
import { AbiParameters } from 'ox'
// ---cut---
AbiParameters.encode(AbiParameters.from(['bytes8']), [
'0xdeadbeefdeadbeef'
])
// ↑ ✅ size: 8 bytes
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L698)
## `AbiParameters.DataSizeTooSmallError`
Throws when the data size is too small for the given parameters.
### Examples
```ts twoslash
import { AbiParameters } from 'ox'
AbiParameters.decode([{ type: 'uint256' }], '0x010f')
// ↑ ❌ 2 bytes
// @error: AbiParameters.DataSizeTooSmallError: Data size of 2 bytes is too small for given parameters.
// @error: Params: (uint256)
// @error: Data: 0x010f (2 bytes)
```
### Solution
Pass a valid data size.
```ts twoslash
import { AbiParameters } from 'ox'
AbiParameters.decode(
[{ type: 'uint256' }],
'0x00000000000000000000000000000000000000000000000000000000000010f'
)
// ↑ ✅ 32 bytes
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L566)
## `AbiParameters.InvalidAbiParametersError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L49)
## `AbiParameters.InvalidAbiTypeParameterError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L130)
## `AbiParameters.InvalidArrayError`
The value provided is not a valid array as specified in the corresponding ABI parameter.
### Example
```ts twoslash
// @noErrors
import { AbiParameters } from 'ox'
// ---cut---
AbiParameters.encode(
AbiParameters.from(['uint256[3]']),
[69]
)
```
### Solution
Pass an array value.
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L779)
## `AbiParameters.InvalidFunctionModifierError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L106)
## `AbiParameters.InvalidModifierError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L83)
## `AbiParameters.InvalidParameterError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L60)
## `AbiParameters.InvalidParenthesisError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L182)
## `AbiParameters.InvalidTypeError`
Throws when the ABI parameter type is invalid.
### Examples
```ts twoslash
import { AbiParameters } from 'ox'
AbiParameters.decode(
[{ type: 'lol' }],
'0x00000000000000000000000000000000000000000000000000000000000010f'
)
// ↑ ❌ invalid type
// @error: AbiParameters.InvalidTypeError: Type `lol` is not a valid ABI Type.
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L801)
## `AbiParameters.LengthMismatchError`
The length of the values to encode does not match the length of the ABI parameters.
### Example
```ts twoslash
// @noErrors
import { AbiParameters } from 'ox'
// ---cut---
AbiParameters.encode(
AbiParameters.from(['string', 'uint256']),
['hello']
)
// @error: LengthMismatchError: ABI encoding params/values length mismatch.
// @error: Expected length (params): 2
// @error: Given length (values): 1
```
### Solution
Pass the correct number of values to encode.
### Solution
Pass a [valid ABI type](https://docs.soliditylang.org/en/develop/abi-spec.html#types).
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L741)
## `AbiParameters.SolidityProtectedKeywordError`
**Source:** [src/core/internal/human-readable/errors.ts](https://github.com/wevm/ox/blob/main/src/core/internal/human-readable/errors.ts#L70)
## `AbiParameters.ZeroDataError`
Throws when zero data is provided, but data is expected.
### Examples
```ts twoslash
import { AbiParameters } from 'ox'
AbiParameters.decode([{ type: 'uint256' }], '0x')
// ↑ ❌ zero data
// @error: AbiParameters.DataSizeTooSmallError: Data size of 2 bytes is too small for given parameters.
// @error: Params: (uint256)
// @error: Data: 0x010f (2 bytes)
```
### Solution
Pass valid data.
```ts twoslash
import { AbiParameters } from 'ox'
AbiParameters.decode(
[{ type: 'uint256' }],
'0x00000000000000000000000000000000000000000000000000000000000010f'
)
// ↑ ✅ 32 bytes
```
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L614)
# AbiParameters Types
## `AbiParameters.AbiParameters`
Root type for ABI parameters.
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L13)
## `AbiParameters.PackedAbiType`
A packed ABI type.
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L29)
## `AbiParameters.Parameter`
A parameter on an [`AbiParameters.AbiParameters`](/api/AbiParameters/types#abiparameters).
**Source:** [src/core/AbiParameters.ts](https://github.com/wevm/ox/blob/main/src/core/AbiParameters.ts#L16)
# Address
Utility functions for working with Ethereum addresses.
## Examples
Below are some examples demonstrating common usages of the `Address` module:
* [Instantiating Addresses](#instantiating-addresses)
* [Validating Addresses](#validating-addresses)
* [Addresses from ECDSA Public Keys](#addresses-from-ecdsa-public-keys)
### Instantiating Addresses
An [`Address.Address`](/api/Address/types#address) can be instantiated from a hex string using [`Address.from`](/api/Address/from):
```ts twoslash
import { Address } from 'ox'
const address = Address.from(
'0xa0cf798816d4b9b9866b5330eea46a18382f251e'
)
// @log: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
```
### Validating Addresses
The [`Address.validate`](/api/Address/validate) function will return `true` if the address is valid, and `false` otherwise:
```ts twoslash
import { Address } from 'ox'
const valid = Address.validate(
'0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
)
// @log: true
```
The [`Address.assert`](/api/Address/assert) function will throw an error if the address is invalid:
```ts twoslash
import { Address } from 'ox'
Address.assert('0xdeadbeef')
// @error: InvalidAddressError: Address "0xdeadbeef" is invalid.
```
### Addresses from ECDSA Public Keys
An [`Address.Address`](/api/Address/types#address) can be computed from an ECDSA public key using [`Address.fromPublicKey`](/api/Address/fromPublicKey):
```ts twoslash
import { Address, Secp256k1 } from 'ox'
const privateKey = Secp256k1.randomPrivateKey()
const publicKey = Secp256k1.getPublicKey({ privateKey })
const address = Address.fromPublicKey(publicKey)
// @log: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Address.assert`](/api/Address/assert) | Asserts that the given value is a valid [`Address.Address`](/api/Address/types#address). |
| [`Address.checksum`](/api/Address/checksum) | Computes the checksum address for the given [`Address.Address`](/api/Address/types#address). |
| [`Address.from`](/api/Address/from) | Converts a stringified address to a typed (optionally checksummed) [`Address.Address`](/api/Address/types#address). |
| [`Address.fromPublicKey`](/api/Address/fromPublicKey) | Converts an ECDSA public key to an [`Address.Address`](/api/Address/types#address). |
| [`Address.isEqual`](/api/Address/isEqual) | Checks if two [`Address.Address`](/api/Address/types#address) are equal. |
| [`Address.validate`](/api/Address/validate) | Checks if the given address is a valid [`Address.Address`](/api/Address/types#address). |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Address.InvalidAddressError`](/api/Address/errors#addressinvalidaddresserror) | Thrown when an address is invalid. |
| [`Address.InvalidChecksumError`](/api/Address/errors#addressinvalidchecksumerror) | Thrown when an address does not match its checksum counterpart. |
| [`Address.InvalidInputError`](/api/Address/errors#addressinvalidinputerror) | Thrown when an address is not a 20 byte (40 hexadecimal character) value. |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Address.Address`](/api/Address/types#addressaddress) | Root type for Address. |
# Address.assert
Asserts that the given value is a valid [`Address.Address`](/api/Address/types#address).
## Imports
:::code-group
```ts [Named]
import { Address } from 'ox'
```
```ts [Entrypoint]
import * as Address from 'ox/Address'
```
:::
## Examples
```ts twoslash
import { Address } from 'ox'
Address.assert('0xA0Cf798816D4b9b9866b5330EEa46a18382f251e')
```
```ts twoslash
import { Address } from 'ox'
Address.assert('0xdeadbeef')
// @error: InvalidAddressError: Address "0xdeadbeef" is invalid.
```
## Definition
```ts
function assert(
value: string,
options?: assert.Options,
): asserts value is Address
```
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L33)
## Parameters
### value
* **Type:** `string`
Value to assert if it is a valid address.
### options
* **Type:** `assert.Options`
* **Optional**
Assertion options.
#### options.strict
* **Type:** `boolean`
* **Optional**
Enables strict mode. Whether or not to compare the address against its checksum.
# Address.checksum
Computes the checksum address for the given [`Address.Address`](/api/Address/types#address).
## Imports
:::code-group
```ts [Named]
import { Address } from 'ox'
```
```ts [Entrypoint]
import * as Address from 'ox/Address'
```
:::
## Examples
```ts twoslash
import { Address } from 'ox'
Address.checksum(
'0xa0cf798816d4b9b9866b5330eea46a18382f251e'
)
// @log: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
```
## Definition
```ts
function checksum(
address: string,
): Address
```
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L83)
## Parameters
### address
* **Type:** `string`
The address to compute the checksum for.
## Return Type
The checksummed address.
`Address`
# Address.from
Converts a stringified address to a typed (optionally checksummed) [`Address.Address`](/api/Address/types#address).
## Imports
:::code-group
```ts [Named]
import { Address } from 'ox'
```
```ts [Entrypoint]
import * as Address from 'ox/Address'
```
:::
## Examples
```ts twoslash
import { Address } from 'ox'
Address.from('0xa0cf798816d4b9b9866b5330eea46a18382f251e')
// @log: '0xa0cf798816d4b9b9866b5330eea46a18382f251e'
```
```ts twoslash
import { Address } from 'ox'
Address.from('0xa0cf798816d4b9b9866b5330eea46a18382f251e', {
checksum: true
})
// @log: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
```
```ts twoslash
import { Address } from 'ox'
Address.from('hello')
// @error: InvalidAddressError: Address "0xa" is invalid.
```
## Definition
```ts
function from(
address: string,
options?: from.Options,
): Address
```
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L170)
## Parameters
### address
* **Type:** `string`
An address string to convert to a typed Address.
### options
* **Type:** `from.Options`
* **Optional**
Conversion options.
#### options.checksum
* **Type:** `boolean`
* **Optional**
Whether to checksum the address.
## Return Type
The typed Address.
`Address`
# Address.fromPublicKey
Converts an ECDSA public key to an [`Address.Address`](/api/Address/types#address).
## Imports
:::code-group
```ts [Named]
import { Address } from 'ox'
```
```ts [Entrypoint]
import * as Address from 'ox/Address'
```
:::
## Examples
```ts twoslash
import { Address, PublicKey } from 'ox'
const publicKey = PublicKey.from(
'0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5'
)
const address = Address.fromPublicKey(publicKey)
// @log: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
```
## Definition
```ts
function fromPublicKey(
publicKey: PublicKey.PublicKey,
options?: fromPublicKey.Options,
): Address
```
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L211)
## Parameters
### publicKey
* **Type:** `PublicKey.PublicKey`
The ECDSA public key to convert to an [`Address.Address`](/api/Address/types#address).
#### publicKey.prefix
* **Type:** `numberType`
#### publicKey.x
* **Type:** `0x${string}`
#### publicKey.y
* **Type:** `0x${string}`
### options
* **Type:** `fromPublicKey.Options`
* **Optional**
Conversion options.
#### options.checksum
* **Type:** `boolean`
* **Optional**
Whether to checksum the address.
## Return Type
The [`Address.Address`](/api/Address/types#address) corresponding to the public key.
`Address`
# Address.isEqual
Checks if two [`Address.Address`](/api/Address/types#address) are equal.
## Imports
:::code-group
```ts [Named]
import { Address } from 'ox'
```
```ts [Entrypoint]
import * as Address from 'ox/Address'
```
:::
## Examples
```ts twoslash
import { Address } from 'ox'
Address.isEqual(
'0xa0cf798816d4b9b9866b5330eea46a18382f251e',
'0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
)
// @log: true
```
```ts twoslash
import { Address } from 'ox'
Address.isEqual(
'0xa0cf798816d4b9b9866b5330eea46a18382f251e',
'0xA0Cf798816D4b9b9866b5330EEa46a18382f251f'
)
// @log: false
```
## Definition
```ts
function isEqual(
addressA: Address,
addressB: Address,
): boolean
```
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L266)
## Parameters
### addressA
* **Type:** `Address`
The first address to compare.
### addressB
* **Type:** `Address`
The second address to compare.
## Return Type
Whether the addresses are equal.
`boolean`
# Address.validate
Checks if the given address is a valid [`Address.Address`](/api/Address/types#address).
## Imports
:::code-group
```ts [Named]
import { Address } from 'ox'
```
```ts [Entrypoint]
import * as Address from 'ox/Address'
```
:::
## Examples
```ts twoslash
import { Address } from 'ox'
Address.validate(
'0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
)
// @log: true
```
```ts twoslash
import { Address } from 'ox'
Address.validate('0xdeadbeef')
// @log: false
```
## Definition
```ts
function validate(
address: string,
options?: validate.Options,
): address is Address
```
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L310)
## Parameters
### address
* **Type:** `string`
Value to check if it is a valid address.
### options
* **Type:** `validate.Options`
* **Optional**
Check options.
#### options.strict
* **Type:** `boolean`
* **Optional**
Enables strict mode. Whether or not to compare the address against its checksum.
## Return Type
Whether the address is a valid address.
`address is Address`
# Address Errors
## `Address.InvalidAddressError`
Thrown when an address is invalid.
### Examples
```ts twoslash
import { Address } from 'ox'
Address.from('0x123')
// @error: Address.InvalidAddressError: Address `0x123` is invalid.
```
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L343)
## `Address.InvalidChecksumError`
Thrown when an address does not match its checksum counterpart.
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L367)
## `Address.InvalidInputError`
Thrown when an address is not a 20 byte (40 hexadecimal character) value.
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L358)
# Address Types
## `Address.Address`
Root type for Address.
**Source:** [src/core/Address.ts](https://github.com/wevm/ox/blob/main/src/core/Address.ts#L10)
# ContractAddress
Utility functions for computing Contract Addresses.
## Examples
Below are some examples demonstrating common usages of the `ContractAddress` module:
* [Computing Contract Addresses (CREATE)](#computing-contract-addresses-\(create\))
* [Computing Contract Addresses (CREATE2)](#computing-contract-addresses-\(create2\))
### Computing Contract Addresses (CREATE)
A Contract Address that was instantiated using the `CREATE` opcode can be computed using [`ContractAddress.fromCreate`](/api/ContractAddress/fromCreate):
```ts twoslash
import { ContractAddress } from 'ox'
ContractAddress.fromCreate({
from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6',
nonce: 0n
})
// @log: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2'
```
### Computing Contract Addresses (CREATE2)
A Contract Address that was instantiated using the `CREATE2` opcode can be computed using [`ContractAddress.fromCreate2`](/api/ContractAddress/fromCreate2):
```ts twoslash
import { Bytes, ContractAddress, Hex } from 'ox'
ContractAddress.fromCreate2({
from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6',
bytecode: Bytes.from(
'0x6394198df16000526103ff60206004601c335afa6040516060f3'
),
salt: Hex.fromString('hello world')
})
// @log: '0x59fbB593ABe27Cb193b6ee5C5DC7bbde312290aB'
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`ContractAddress.from`](/api/ContractAddress/from) | Computes Contract Address generated by the [CREATE](https://ethereum.stackexchange.com/questions/68943/create-opcode-what-does-it-really-do/68945#68945) or [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode. |
| [`ContractAddress.fromCreate`](/api/ContractAddress/fromCreate) | Computes contract address via [CREATE](https://ethereum.stackexchange.com/questions/68943/create-opcode-what-does-it-really-do/68945#68945) opcode. |
| [`ContractAddress.fromCreate2`](/api/ContractAddress/fromCreate2) | Computes contract address via [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode. |
# ContractAddress.from
Computes Contract Address generated by the [CREATE](https://ethereum.stackexchange.com/questions/68943/create-opcode-what-does-it-really-do/68945#68945) or [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode.
## Imports
:::code-group
```ts [Named]
import { ContractAddress } from 'ox'
```
```ts [Entrypoint]
import * as ContractAddress from 'ox/ContractAddress'
```
:::
## Examples
### CREATE
Computes via the [CREATE](https://ethereum.stackexchange.com/questions/68943/create-opcode-what-does-it-really-do/68945#68945) opcode. Shorthand for [`ContractAddress.fromCreate`](/api/ContractAddress/fromCreate).
```ts twoslash
import { ContractAddress } from 'ox'
ContractAddress.from({
from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6',
nonce: 0n
})
// @log: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2'
```
### CREATE2
Computes via the [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode. Shorthand for [`ContractAddress.fromCreate2`](/api/ContractAddress/fromCreate2).
```ts twoslash
import { ContractAddress, Hex } from 'ox'
ContractAddress.from({
from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6',
bytecode:
'0x6394198df16000526103ff60206004601c335afa6040516060f3',
salt: Hex.fromString('hello world')
})
// @log: '0x59fbB593ABe27Cb193b6ee5C5DC7bbde312290aB'
```
## Definition
```ts
function from(
options: from.Options,
): Address.Address
```
**Source:** [src/core/ContractAddress.ts](https://github.com/wevm/ox/blob/main/src/core/ContractAddress.ts#L45)
## Parameters
### options
* **Type:** `from.Options`
Options.
#### options.bytecode
* **Type:** `0x${string} | Uint8Array`
#### options.bytecodeHash
* **Type:** `0x${string} | Uint8Array`
#### options.from
* **Type:** `abitype_Address`
#### options.nonce
* **Type:** `bigint`
The nonce of the transaction which deployed the contract.
#### options.salt
* **Type:** `0x${string} | Uint8Array`
## Return Type
Contract Address.
`Address.Address`
# ContractAddress.fromCreate
Computes contract address via [CREATE](https://ethereum.stackexchange.com/questions/68943/create-opcode-what-does-it-really-do/68945#68945) opcode.
## Imports
:::code-group
```ts [Named]
import { ContractAddress } from 'ox'
```
```ts [Entrypoint]
import * as ContractAddress from 'ox/ContractAddress'
```
:::
## Examples
```ts twoslash
import { ContractAddress } from 'ox'
ContractAddress.fromCreate({
from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6',
nonce: 0n
})
// @log: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2'
```
## Definition
```ts
function fromCreate(
options: fromCreate.Options,
): Address.Address
```
**Source:** [src/core/ContractAddress.ts](https://github.com/wevm/ox/blob/main/src/core/ContractAddress.ts#L76)
## Parameters
### options
* **Type:** `fromCreate.Options`
Options for retrieving address.
#### options.from
* **Type:** `abitype_Address`
The address the contract was deployed from.
#### options.nonce
* **Type:** `bigint`
The nonce of the transaction which deployed the contract.
## Return Type
Contract Address.
`Address.Address`
# ContractAddress.fromCreate2
Computes contract address via [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) opcode.
## Imports
:::code-group
```ts [Named]
import { ContractAddress } from 'ox'
```
```ts [Entrypoint]
import * as ContractAddress from 'ox/ContractAddress'
```
:::
## Examples
```ts twoslash
import { ContractAddress, Hex } from 'ox'
ContractAddress.fromCreate2({
from: '0x1a1e021a302c237453d3d45c7b82b19ceeb7e2e6',
bytecode:
'0x6394198df16000526103ff60206004601c335afa6040516060f3',
salt: Hex.fromString('hello world')
})
// @log: '0x59fbB593ABe27Cb193b6ee5C5DC7bbde312290aB'
```
## Definition
```ts
function fromCreate2(
options: fromCreate2.Options,
): Address.Address
```
**Source:** [src/core/ContractAddress.ts](https://github.com/wevm/ox/blob/main/src/core/ContractAddress.ts#L123)
## Parameters
### options
* **Type:** `fromCreate2.Options`
Options for retrieving address.
#### options.bytecode
* **Type:** `0x${string} | Uint8Array`
#### options.bytecodeHash
* **Type:** `0x${string} | Uint8Array`
#### options.from
* **Type:** `abitype_Address`
#### options.salt
* **Type:** `0x${string} | Uint8Array`
## Return Type
Contract Address.
`Address.Address`
# Authorization
Utility functions for working with [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization lists & tuples.
## Examples
Below are some examples demonstrating common usages of the `Authorization` module:
* [Instantiating Authorizations](#instantiating-authorizations)
* [Computing Sign Payload](#computing-sign-payload)
* [Attaching Signatures to Authorizations](#attaching-signatures-to-authorizations)
### Instantiating Authorizations
An Authorization can be instantiated using [`Authorization.from`](/api/Authorization/from):
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 1,
nonce: 69n
})
```
### Computing Sign Payload
A signing payload can be computed using [`Authorization.getSignPayload`](/api/Authorization/getSignPayload). The result can then be passed to signing functions like [`Secp256k1.sign`](/api/Secp256k1/sign).
```ts twoslash
import { Authorization, Secp256k1 } from 'ox'
const authorization = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 1,
nonce: 69n
})
const payload = Authorization.getSignPayload(authorization) // [!code focus]
const signature = Secp256k1.sign({
payload,
privateKey: '0x...'
})
```
### Attaching Signatures to Authorizations
A signature can be attached to an Authorization using [`Authorization.from`](/api/Authorization/from):
```ts twoslash
import {
Authorization,
Secp256k1,
TxEnvelopeEip7702,
Value
} from 'ox'
const authorization = Authorization.from({
address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
chainId: 1,
nonce: 40n
})
const signature = Secp256k1.sign({
payload: Authorization.getSignPayload(authorization),
privateKey: '0x...'
})
const authorization_signed = Authorization.from(
authorization,
{ signature }
) // [!code focus]
const envelope = TxEnvelopeEip7702.from({
authorizationList: [authorization_signed],
chainId: 1,
maxFeePerGas: Value.fromGwei('10'),
to: '0x0000000000000000000000000000000000000000',
value: Value.fromEther('1')
})
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Authorization.from`](/api/Authorization/from) | Converts an [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization object into a typed [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.fromRpc`](/api/Authorization/fromRpc) | Converts an [`Authorization.Rpc`](/api/Authorization/types#rpc) to an [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.fromRpcList`](/api/Authorization/fromRpcList) | Converts an [`Authorization.ListRpc`](/api/Authorization/types#listrpc) to an [`Authorization.List`](/api/Authorization/types#list). |
| [`Authorization.fromTuple`](/api/Authorization/fromTuple) | Converts an [`Authorization.Tuple`](/api/Authorization/types#tuple) to an [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.fromTupleList`](/api/Authorization/fromTupleList) | Converts an [`Authorization.TupleList`](/api/Authorization/types#tuplelist) to an [`Authorization.List`](/api/Authorization/types#list). |
| [`Authorization.getSignPayload`](/api/Authorization/getSignPayload) | Computes the sign payload for an [`Authorization.Authorization`](/api/Authorization/types#authorization) in [EIP-7702 format](https://eips.ethereum.org/EIPS/eip-7702): `keccak256('0x05' || rlp([chain_id, address, nonce]))`. |
| [`Authorization.hash`](/api/Authorization/hash) | Computes the hash for an [`Authorization.Authorization`](/api/Authorization/types#authorization) in [EIP-7702 format](https://eips.ethereum.org/EIPS/eip-7702): `keccak256('0x05' || rlp([chain_id, address, nonce]))`. |
| [`Authorization.toRpc`](/api/Authorization/toRpc) | Converts an [`Authorization.Authorization`](/api/Authorization/types#authorization) to an [`Authorization.Rpc`](/api/Authorization/types#rpc). |
| [`Authorization.toRpcList`](/api/Authorization/toRpcList) | Converts an [`Authorization.List`](/api/Authorization/types#list) to an [`Authorization.ListRpc`](/api/Authorization/types#listrpc). |
| [`Authorization.toTuple`](/api/Authorization/toTuple) | Converts an [`Authorization.Authorization`](/api/Authorization/types#authorization) to an [`Authorization.Tuple`](/api/Authorization/types#tuple). |
| [`Authorization.toTupleList`](/api/Authorization/toTupleList) | Converts an [`Authorization.List`](/api/Authorization/types#list) to an [`Authorization.TupleList`](/api/Authorization/types#tuplelist). |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Authorization.Authorization`](/api/Authorization/types#authorizationauthorization) | Root type for an EIP-7702 Authorization. |
| [`Authorization.List`](/api/Authorization/types#authorizationlist) | List of [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.ListRpc`](/api/Authorization/types#authorizationlistrpc) | RPC representation of an [`Authorization.List`](/api/Authorization/types#list). |
| [`Authorization.ListSigned`](/api/Authorization/types#authorizationlistsigned) | Signed representation of a list of [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.Rpc`](/api/Authorization/types#authorizationrpc) | RPC representation of an [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.Signed`](/api/Authorization/types#authorizationsigned) | Signed representation of an [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.Tuple`](/api/Authorization/types#authorizationtuple) | Tuple representation of an [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.TupleList`](/api/Authorization/types#authorizationtuplelist) | Tuple representation of a list of [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.TupleListSigned`](/api/Authorization/types#authorizationtuplelistsigned) | Tuple representation of a list of signed [`Authorization.Authorization`](/api/Authorization/types#authorization). |
| [`Authorization.TupleSigned`](/api/Authorization/types#authorizationtuplesigned) | Tuple representation of a signed [`Authorization.Authorization`](/api/Authorization/types#authorization). |
# Authorization.from
Converts an [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization object into a typed [`Authorization.Authorization`](/api/Authorization/types#authorization).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
An Authorization can be instantiated from an [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization tuple in object format.
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 1,
nonce: 69n
})
```
### Attaching Signatures
A [`Signature.Signature`](/api/Signature/types#signature) can be attached with the `signature` option. The example below demonstrates signing an Authorization with [`Secp256k1.sign`](/api/Secp256k1/sign).
```ts twoslash
import { Authorization, Secp256k1 } from 'ox'
const authorization = Authorization.from({
address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
chainId: 1,
nonce: 40n
})
const signature = Secp256k1.sign({
payload: Authorization.getSignPayload(authorization),
privateKey: '0x...'
})
const authorization_signed = Authorization.from(
authorization,
{ signature }
) // [!code focus]
```
## Definition
```ts
function from(
authorization: authorization | Authorization,
options?: from.Options,
): from.ReturnType
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L123)
## Parameters
### authorization
* **Type:** `authorization | Authorization`
An [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization tuple in object format.
### options
* **Type:** `from.Options`
* **Optional**
Authorization options.
#### options.signature
* **Type:** `signature | { r: 0x${string}; s: 0x${string}; yParity: number; }`
* **Optional**
The [`Signature.Signature`](/api/Signature/types#signature) to attach to the Authorization.
## Return Type
The [`Authorization.Authorization`](/api/Authorization/types#authorization).
`from.ReturnType`
# Authorization.fromRpc
Converts an [`Authorization.Rpc`](/api/Authorization/types#rpc) to an [`Authorization.Authorization`](/api/Authorization/types#authorization).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.fromRpc({
address: '0x0000000000000000000000000000000000000000',
chainId: '0x1',
nonce: '0x1',
r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
yParity: '0x0'
})
```
## Definition
```ts
function fromRpc(
authorization: Rpc,
): Signed
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L180)
## Parameters
### authorization
* **Type:** `Rpc`
The RPC-formatted Authorization.
## Return Type
A signed [`Authorization.Authorization`](/api/Authorization/types#authorization).
[`Signed`](/api/Authorization/types#authorizationsigned)
# Authorization.fromRpcList
Converts an [`Authorization.ListRpc`](/api/Authorization/types#listrpc) to an [`Authorization.List`](/api/Authorization/types#list).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorizationList = Authorization.fromRpcList([
{
address: '0x0000000000000000000000000000000000000000',
chainId: '0x1',
nonce: '0x1',
r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
yParity: '0x0'
}
])
```
## Definition
```ts
function fromRpcList(
authorizationList: ListRpc,
): ListSigned
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L218)
## Parameters
### authorizationList
* **Type:** [`ListRpc`](/api/Authorization/types#authorizationlistrpc)
The RPC-formatted Authorization list.
## Return Type
A signed [`Authorization.List`](/api/Authorization/types#list).
[`ListSigned`](/api/Authorization/types#authorizationlistsigned)
# Authorization.fromTuple
Converts an [`Authorization.Tuple`](/api/Authorization/types#tuple) to an [`Authorization.Authorization`](/api/Authorization/types#authorization).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.fromTuple([
'0x1',
'0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
'0x3'
])
// @log: {
// @log: address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
// @log: chainId: 1,
// @log: nonce: 3n
// @log: }
```
It is also possible to append a Signature tuple to the end of an Authorization tuple.
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.fromTuple([
'0x1',
'0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
'0x3',
'0x1',
'0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90',
'0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064'
])
// @log: {
// @log: address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
// @log: chainId: 1,
// @log: nonce: 3n
// @log: r: '0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90',
// @log: s: '0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064',
// @log: yParity: 0,
// @log: }
```
## Definition
```ts
function fromTuple(
tuple: tuple,
): fromTuple.ReturnType
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L272)
## Parameters
### tuple
* **Type:** `tuple`
The [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization tuple.
## Return Type
The [`Authorization.Authorization`](/api/Authorization/types#authorization).
`fromTuple.ReturnType`
# Authorization.fromTupleList
Converts an [`Authorization.TupleList`](/api/Authorization/types#tuplelist) to an [`Authorization.List`](/api/Authorization/types#list).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorizationList = Authorization.fromTupleList([
[
'0x1',
'0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
'0x3'
],
[
'0x3',
'0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
'0x14'
]
])
// @log: [
// @log: {
// @log: address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
// @log: chainId: 1,
// @log: nonce: 3n,
// @log: },
// @log: {
// @log: address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
// @log: chainId: 3,
// @log: nonce: 20n,
// @log: },
// @log: ]
```
It is also possible to append a Signature tuple to the end of an Authorization tuple.
```ts twoslash
import { Authorization } from 'ox'
const authorizationList = Authorization.fromTupleList([
[
'0x1',
'0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
'0x3',
'0x1',
'0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90',
'0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064'
],
[
'0x3',
'0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
'0x14',
'0x1',
'0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90',
'0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064'
]
])
// @log: [
// @log: {
// @log: address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
// @log: chainId: 1,
// @log: nonce: 3n,
// @log: r: '0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90',
// @log: s: '0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064',
// @log: yParity: 0,
// @log: },
// @log: {
// @log: address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
// @log: chainId: 3,
// @log: nonce: 20n,
// @log: r: '0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90',
// @log: s: '0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064',
// @log: yParity: 0,
// @log: },
// @log: ]
```
## Definition
```ts
function fromTupleList(
tupleList: tupleList,
): fromTupleList.ReturnType
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L374)
## Parameters
### tupleList
* **Type:** `tupleList`
The [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization tuple list.
## Return Type
An [`Authorization.List`](/api/Authorization/types#list).
`fromTupleList.ReturnType`
# Authorization.getSignPayload
Computes the sign payload for an [`Authorization.Authorization`](/api/Authorization/types#authorization) in [EIP-7702 format](https://eips.ethereum.org/EIPS/eip-7702): `keccak256('0x05' || rlp([chain_id, address, nonce]))`.
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
The example below demonstrates computing the sign payload for an [`Authorization.Authorization`](/api/Authorization/types#authorization). This payload can then be passed to signing functions like [`Secp256k1.sign`](/api/Secp256k1/sign).
```ts twoslash
import { Authorization, Secp256k1 } from 'ox'
const authorization = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 1,
nonce: 69n
})
const payload = Authorization.getSignPayload(authorization) // [!code focus]
const signature = Secp256k1.sign({
payload,
privateKey: '0x...'
})
```
## Definition
```ts
function getSignPayload(
authorization: Authorization,
): Hex.Hex
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L417)
## Parameters
### authorization
* **Type:** `Authorization`
The [`Authorization.Authorization`](/api/Authorization/types#authorization).
#### authorization.address
* **Type:** `abitype_Address`
Address of the contract to set as code for the Authority.
#### authorization.chainId
* **Type:** `numberType`
Chain ID to authorize.
#### authorization.nonce
* **Type:** `bigintType`
Nonce of the Authority to authorize.
## Return Type
The sign payload.
`Hex.Hex`
# Authorization.hash
Computes the hash for an [`Authorization.Authorization`](/api/Authorization/types#authorization) in [EIP-7702 format](https://eips.ethereum.org/EIPS/eip-7702): `keccak256('0x05' || rlp([chain_id, address, nonce]))`.
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 1,
nonce: 69n
})
const hash = Authorization.hash(authorization) // [!code focus]
```
## Definition
```ts
function hash(
authorization: Authorization,
options?: hash.Options,
): Hex.Hex
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L444)
## Parameters
### authorization
* **Type:** `Authorization`
The [`Authorization.Authorization`](/api/Authorization/types#authorization).
#### authorization.address
* **Type:** `abitype_Address`
Address of the contract to set as code for the Authority.
#### authorization.chainId
* **Type:** `numberType`
Chain ID to authorize.
#### authorization.nonce
* **Type:** `bigintType`
Nonce of the Authority to authorize.
### options
* **Type:** `hash.Options`
* **Optional**
#### options.presign
* **Type:** `boolean`
* **Optional**
Whether to hash this authorization for signing.
## Return Type
The hash.
`Hex.Hex`
# Authorization.toRpc
Converts an [`Authorization.Authorization`](/api/Authorization/types#authorization) to an [`Authorization.Rpc`](/api/Authorization/types#rpc).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.toRpc({
address: '0x0000000000000000000000000000000000000000',
chainId: 1,
nonce: 1n,
r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
yParity: 0
})
```
## Definition
```ts
function toRpc(
authorization: toRpc.Input,
): Rpc
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L501)
## Parameters
### authorization
* **Type:** `toRpc.Input`
An Authorization.
## Return Type
An RPC-formatted Authorization.
`Rpc`
# Authorization.toRpcList
Converts an [`Authorization.List`](/api/Authorization/types#list) to an [`Authorization.ListRpc`](/api/Authorization/types#listrpc).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.toRpcList([
{
address: '0x0000000000000000000000000000000000000000',
chainId: 1,
nonce: 1n,
r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d',
s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540',
yParity: 0
}
])
```
## Definition
```ts
function toRpcList(
authorizationList: toRpcList.Input,
): ListRpc
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L541)
## Parameters
### authorizationList
* **Type:** `toRpcList.Input`
An Authorization List.
## Return Type
An RPC-formatted Authorization List.
[`ListRpc`](/api/Authorization/types#authorizationlistrpc)
# Authorization.toTuple
Converts an [`Authorization.Authorization`](/api/Authorization/types#authorization) to an [`Authorization.Tuple`](/api/Authorization/types#tuple).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorization = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 1,
nonce: 69n
})
const tuple = Authorization.toTuple(authorization) // [!code focus]
// @log: [
// @log: address: '0x1234567890abcdef1234567890abcdef12345678',
// @log: chainId: 1,
// @log: nonce: 69n,
// @log: ]
```
## Definition
```ts
function toTuple(
authorization: authorization,
): toTuple.ReturnType
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L576)
## Parameters
### authorization
* **Type:** `authorization`
The [`Authorization.Authorization`](/api/Authorization/types#authorization).
## Return Type
An [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization tuple.
`toTuple.ReturnType`
# Authorization.toTupleList
Converts an [`Authorization.List`](/api/Authorization/types#list) to an [`Authorization.TupleList`](/api/Authorization/types#tuplelist).
## Imports
:::code-group
```ts [Named]
import { Authorization } from 'ox'
```
```ts [Entrypoint]
import * as Authorization from 'ox/Authorization'
```
:::
## Examples
```ts twoslash
import { Authorization } from 'ox'
const authorization_1 = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 1,
nonce: 69n
})
const authorization_2 = Authorization.from({
address: '0x1234567890abcdef1234567890abcdef12345678',
chainId: 3,
nonce: 20n
})
const tuple = Authorization.toTupleList([
authorization_1,
authorization_2
]) // [!code focus]
// @log: [
// @log: [
// @log: address: '0x1234567890abcdef1234567890abcdef12345678',
// @log: chainId: 1,
// @log: nonce: 69n,
// @log: ],
// @log: [
// @log: address: '0x1234567890abcdef1234567890abcdef12345678',
// @log: chainId: 3,
// @log: nonce: 20n,
// @log: ],
// @log: ]
```
## Definition
```ts
function toTupleList(
list?: list,
): toTupleList.ReturnType
```
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L635)
## Parameters
### list
* **Type:** `list`
* **Optional**
An [`Authorization.List`](/api/Authorization/types#list).
## Return Type
An [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) Authorization tuple list.
`toTupleList.ReturnType`
# Authorization Types
## `Authorization.Authorization`
Root type for an EIP-7702 Authorization.
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L11)
## `Authorization.List`
List of [`Authorization.Authorization`](/api/Authorization/types#authorization).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L32)
## `Authorization.ListRpc`
RPC representation of an [`Authorization.List`](/api/Authorization/types#list).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L39)
## `Authorization.ListSigned`
Signed representation of a list of [`Authorization.Authorization`](/api/Authorization/types#authorization).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L42)
## `Authorization.Rpc`
RPC representation of an [`Authorization.Authorization`](/api/Authorization/types#authorization).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L29)
## `Authorization.Signed`
Signed representation of an [`Authorization.Authorization`](/api/Authorization/types#authorization).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L49)
## `Authorization.Tuple`
Tuple representation of an [`Authorization.Authorization`](/api/Authorization/types#authorization).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L56)
## `Authorization.TupleList`
Tuple representation of a list of [`Authorization.Authorization`](/api/Authorization/types#authorization).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L71)
## `Authorization.TupleListSigned`
Tuple representation of a list of signed [`Authorization.Authorization`](/api/Authorization/types#authorization).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L75)
## `Authorization.TupleSigned`
Tuple representation of a signed [`Authorization.Authorization`](/api/Authorization/types#authorization).
**Source:** [src/core/Authorization.ts](https://github.com/wevm/ox/blob/main/src/core/Authorization.ts#L68)
# BinaryStateTree
Utility functions for working with [EIP-7864](https://eips.ethereum.org/EIPS/eip-7864) Binary State Trees.
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`BinaryStateTree.create`](/api/BinaryStateTree/create) | Creates a new Binary State Tree instance. |
| [`BinaryStateTree.insert`](/api/BinaryStateTree/insert) | Inserts a key-value pair into the Binary State Tree. |
| [`BinaryStateTree.merkelize`](/api/BinaryStateTree/merkelize) | Merkelizes a Binary State Tree. |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`BinaryStateTree.BinaryStateTree`](/api/BinaryStateTree/types#binarystatetreebinarystatetree) | Type that defines a Binary State Tree instance. |
| [`BinaryStateTree.Node`](/api/BinaryStateTree/types#binarystatetreenode) | Type defining a node of the BST. |
# BinaryStateTree.create
Creates a new Binary State Tree instance.
## Imports
:::code-group
```ts [Named]
import { BinaryStateTree } from 'ox'
```
```ts [Entrypoint]
import * as BinaryStateTree from 'ox/BinaryStateTree'
```
:::
## Examples
```ts twoslash
import { BinaryStateTree } from 'ox'
const tree = BinaryStateTree.create()
```
## Definition
```ts
function create(): BinaryStateTree
```
**Source:** [src/core/BinaryStateTree.ts](https://github.com/wevm/ox/blob/main/src/core/BinaryStateTree.ts#L25)
## Return Type
A Binary State Tree.
[`BinaryStateTree.BinaryStateTree`](/api/BinaryStateTree/types#binarystatetreebinarystatetree)
# BinaryStateTree.insert
Inserts a key-value pair into the Binary State Tree.
## Imports
:::code-group
```ts [Named]
import { BinaryStateTree } from 'ox'
```
```ts [Entrypoint]
import * as BinaryStateTree from 'ox/BinaryStateTree'
```
:::
## Examples
```ts twoslash
import { BinaryStateTree, Bytes } from 'ox'
const tree = BinaryStateTree.create()
BinaryStateTree.insert(
// [!code focus]
tree, // [!code focus]
Bytes.fromHex(
'0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54'
), // [!code focus]
Bytes.fromHex(
'0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1'
) // [!code focus]
) // [!code focus]
```
## Definition
```ts
function insert(
tree: BinaryStateTree.BinaryStateTree,
key: Bytes.Bytes,
value: Bytes.Bytes,
): void
```
**Source:** [src/core/BinaryStateTree.ts](https://github.com/wevm/ox/blob/main/src/core/BinaryStateTree.ts#L56)
## Parameters
### tree
* **Type:** [`BinaryStateTree.BinaryStateTree`](/api/BinaryStateTree/types#binarystatetreebinarystatetree)
Binary State Tree instance.
#### tree.root
* **Type:** `Node`
### key
* **Type:** `Bytes.Bytes`
Key to insert.
### value
* **Type:** `Bytes.Bytes`
Value to insert.
## Return Type
`void`
# BinaryStateTree.merkelize
Merkelizes a Binary State Tree.
## Imports
:::code-group
```ts [Named]
import { BinaryStateTree } from 'ox'
```
```ts [Entrypoint]
import * as BinaryStateTree from 'ox/BinaryStateTree'
```
:::
## Examples
```ts twoslash
import { BinaryStateTree, Bytes } from 'ox'
const tree = BinaryStateTree.create()
BinaryStateTree.insert(
tree,
Bytes.fromHex(
'0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54'
),
Bytes.fromHex(
'0xd4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1'
)
)
const hash = BinaryStateTree.merkelize(tree) // [!code focus]
```
## Definition
```ts
function merkelize(
tree: BinaryStateTree.BinaryStateTree,
): Bytes.Bytes
```
**Source:** [src/core/BinaryStateTree.ts](https://github.com/wevm/ox/blob/main/src/core/BinaryStateTree.ts#L135)
## Parameters
### tree
* **Type:** [`BinaryStateTree.BinaryStateTree`](/api/BinaryStateTree/types#binarystatetreebinarystatetree)
Binary State Tree instance.
#### tree.root
* **Type:** `Node`
## Return Type
Merkle hash.
`Bytes.Bytes`
# BinaryStateTree Types
## `BinaryStateTree.BinaryStateTree`
Type that defines a Binary State Tree instance.
**Source:** [src/core/BinaryStateTree.ts](https://github.com/wevm/ox/blob/main/src/core/BinaryStateTree.ts#L6)
## `BinaryStateTree.Node`
Type defining a node of the BST.
**Source:** [src/core/BinaryStateTree.ts](https://github.com/wevm/ox/blob/main/src/core/BinaryStateTree.ts#L11)
# Blobs
Utility functions for working with [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) Blobs.
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Blobs.commitmentsToVersionedHashes`](/api/Blobs/commitmentsToVersionedHashes) | Transform a list of Commitments to Blob Versioned Hashes. |
| [`Blobs.commitmentToVersionedHash`](/api/Blobs/commitmentToVersionedHash) | Transform a Commitment to its Blob Versioned Hash. |
| [`Blobs.from`](/api/Blobs/from) | Transforms arbitrary data to [`Blobs.Blobs`](/api/Blobs/types#blobs). |
| [`Blobs.to`](/api/Blobs/to) | Transforms Ox-shaped [`Blobs.Blobs`](/api/Blobs/types#blobs) into the originating data. |
| [`Blobs.toBytes`](/api/Blobs/toBytes) | Transforms Ox-shaped [`Blobs.Blobs`](/api/Blobs/types#blobs) into the originating data. |
| [`Blobs.toCellProofs`](/api/Blobs/toCellProofs) | Compute the flat list of PeerDAS (EIP-7594) cell KZG proofs for a list of [`Blobs.Blobs`](/api/Blobs/types#blobs). Returns `128 * blobs.length` proofs, where `proofs[i * 128 + j]` is the proof for cell `j` of `blobs[i]`'s extended form. |
| [`Blobs.toCommitments`](/api/Blobs/toCommitments) | Compute commitments from a list of [`Blobs.Blobs`](/api/Blobs/types#blobs). |
| [`Blobs.toHex`](/api/Blobs/toHex) | Transforms Ox-shaped [`Blobs.Blobs`](/api/Blobs/types#blobs) into the originating data. |
| [`Blobs.toVersionedHashes`](/api/Blobs/toVersionedHashes) | Compute Blob Versioned Hashes from a list of [`Blobs.Blobs`](/api/Blobs/types#blobs). |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Blobs.BlobSizeTooLargeError`](/api/Blobs/errors#blobsblobsizetoolargeerror) | Thrown when the blob size is too large. |
| [`Blobs.EmptyBlobError`](/api/Blobs/errors#blobsemptybloberror) | Thrown when the blob is empty. |
| [`Blobs.EmptyBlobVersionedHashesError`](/api/Blobs/errors#blobsemptyblobversionedhasheserror) | Thrown when the blob versioned hashes are empty. |
| [`Blobs.InvalidVersionedHashSizeError`](/api/Blobs/errors#blobsinvalidversionedhashsizeerror) | Thrown when the blob versioned hash size is invalid. |
| [`Blobs.InvalidVersionedHashVersionError`](/api/Blobs/errors#blobsinvalidversionedhashversionerror) | Thrown when the blob versioned hash version is invalid. |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Blobs.Blob`](/api/Blobs/types#blobsblob) | Root type for a Blob. |
| [`Blobs.Blobs`](/api/Blobs/types#blobsblobs) | A list of [`Blobs.Blob`](/api/Blobs/types#blob). |
# Blobs.commitmentsToVersionedHashes
Transform a list of Commitments to Blob Versioned Hashes.
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const commitments = Blobs.toCommitments(blobs, { kzg })
const versionedHashes =
Blobs.commitmentsToVersionedHashes(commitments) // [!code focus]
// @log: ['0x...', '0x...']
```
### Configuring Return Type
It is possible to configure the return type for the Versioned Hashes with the `as` option.
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const commitments = Blobs.toCommitments(blobs, { kzg })
const versionedHashes = Blobs.commitmentsToVersionedHashes(
commitments,
{
as: 'Bytes' // [!code focus]
}
)
// @log: [Uint8Array [ ... ], Uint8Array [ ... ]]
```
### Versioning Hashes
It is possible to configure the version for the Versioned Hashes with the `version` option.
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const commitments = Blobs.toCommitments(blobs, { kzg })
const versionedHashes = Blobs.commitmentsToVersionedHashes(
commitments,
{
version: 2 // [!code focus]
}
)
```
## Definition
```ts
function commitmentsToVersionedHashes(
commitments: commitments | readonly Bytes.Bytes[] | readonly Hex.Hex[],
options?: commitmentsToVersionedHashes.Options,
): commitmentsToVersionedHashes.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L99)
## Parameters
### commitments
* **Type:** `commitments | readonly Bytes.Bytes[] | readonly Hex.Hex[]`
A list of commitments.
### options
* **Type:** `commitmentsToVersionedHashes.Options`
* **Optional**
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
#### options.version
* **Type:** `number`
* **Optional**
Version to tag onto the hashes.
## Return Type
A list of Blob Versioned Hashes.
`commitmentsToVersionedHashes.ReturnType`
# Blobs.commitmentToVersionedHash
Transform a Commitment to its Blob Versioned Hash.
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const [commitment] = Blobs.toCommitments(blobs, { kzg })
const versionedHash =
Blobs.commitmentToVersionedHash(commitment) // [!code focus]
```
### Configuring Return Type
It is possible to configure the return type for the Versioned Hash with the `as` option.
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const [commitment] = Blobs.toCommitments(blobs, { kzg })
const versionedHashes = Blobs.commitmentToVersionedHash(
commitment,
{
as: 'Bytes' // [!code focus]
}
)
// @log: [Uint8Array [ ... ], Uint8Array [ ... ]]
```
### Versioning Hashes
It is possible to configure the version for the Versioned Hash with the `version` option.
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const [commitment] = Blobs.toCommitments(blobs, { kzg })
const versionedHashes = Blobs.commitmentToVersionedHash(
commitment,
{
version: 2 // [!code focus]
}
)
```
## Definition
```ts
function commitmentToVersionedHash(
commitment: commitment | Hex.Hex | Bytes.Bytes,
options?: commitmentToVersionedHash.Options,
): commitmentToVersionedHash.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L200)
## Parameters
### commitment
* **Type:** `commitment | Hex.Hex | Bytes.Bytes`
The commitment.
### options
* **Type:** `commitmentToVersionedHash.Options`
* **Optional**
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
#### options.version
* **Type:** `number`
* **Optional**
Version to tag onto the hash.
## Return Type
The Blob Versioned Hash.
`commitmentToVersionedHash.ReturnType`
# Blobs.from
Transforms arbitrary data to [`Blobs.Blobs`](/api/Blobs/types#blobs).
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts twoslash
import { Blobs } from 'ox'
const blobs = Blobs.from('0xdeadbeef')
```
### Creating Blobs from a String
An example of creating Blobs from a string using [`Hex.from`](/api/Hex/from):
```ts twoslash
import { Blobs, Hex } from 'ox'
const blobs = Blobs.from(Hex.fromString('Hello world!'))
```
### Configuring Return Type
It is possible to configure the return type for the Blobs with the `as` option.
```ts twoslash
import { Blobs } from 'ox'
const blobs = Blobs.from('0xdeadbeef', { as: 'Bytes' })
// ^?
```
## Definition
```ts
function from(
data: data | Hex.Hex | Bytes.Bytes,
options?: from.Options,
): from.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L271)
## Parameters
### data
* **Type:** `data | Hex.Hex | Bytes.Bytes`
The data to convert to [`Blobs.Blobs`](/api/Blobs/types#blobs).
### options
* **Type:** `from.Options`
* **Optional**
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
## Return Type
The [`Blobs.Blobs`](/api/Blobs/types#blobs).
`from.ReturnType`
# Blobs.to
Transforms Ox-shaped [`Blobs.Blobs`](/api/Blobs/types#blobs) into the originating data.
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts twoslash
import { Blobs, Hex } from 'ox'
const blobs = Blobs.from('0xdeadbeef')
const data = Blobs.to(blobs) // [!code focus]
// @log: '0xdeadbeef'
```
### Configuring Return Type
It is possible to configure the return type with second argument.
```ts twoslash
import { Blobs } from 'ox'
const blobs = Blobs.from('0xdeadbeef')
const data = Blobs.to(blobs, 'Bytes')
// @log: Uint8Array [ 13, 174, 190, 239 ]
```
## Definition
```ts
function to(
blobs: blobs | Blobs | Blobs,
to?: to | 'Hex' | 'Bytes',
): to.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L381)
## Parameters
### blobs
* **Type:** `blobs | Blobs | Blobs`
The [`Blobs.Blobs`](/api/Blobs/types#blobs) to transform.
### to
* **Type:** `to | 'Hex' | 'Bytes'`
* **Optional**
The type to transform to.
## Return Type
The originating data.
`to.ReturnType`
# Blobs.toBytes
Transforms Ox-shaped [`Blobs.Blobs`](/api/Blobs/types#blobs) into the originating data.
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts
import { Blobs, Hex } from 'ox'
const blobs = Blobs.from('0xdeadbeef')
const data = Blobs.toBytes(blobs) // [!code focus]
// @log: Uint8Array [ 13, 174, 190, 239 ]
```
## Definition
```ts
function toBytes(
blobs: Blobs | Blobs,
): toBytes.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L475)
## Parameters
### blobs
* **Type:** `Blobs | Blobs`
## Return Type
`toBytes.ReturnType`
# Blobs.toCellProofs
Compute the flat list of PeerDAS (EIP-7594) cell KZG proofs for a list of [`Blobs.Blobs`](/api/Blobs/types#blobs). Returns `128 * blobs.length` proofs, where `proofs[i * 128 + j]` is the proof for cell `j` of `blobs[i]`'s extended form.
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const cellProofs = Blobs.toCellProofs(blobs, { kzg }) // [!code focus]
```
### Configuring Return Type
It is possible to configure the return type with the `as` option.
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const cellProofs = Blobs.toCellProofs(blobs, {
as: 'Bytes', // [!code focus]
kzg
})
// @log: [Uint8Array [ ... ], Uint8Array [ ... ], ...]
```
## Definition
```ts
function toCellProofs(
blobs: blobs | Blobs | Blobs,
options: toCellProofs.Options,
): toCellProofs.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L605)
## Parameters
### blobs
* **Type:** `blobs | Blobs | Blobs`
The [`Blobs.Blobs`](/api/Blobs/types#blobs) to transform to cell proofs.
### options
* **Type:** `toCellProofs.Options`
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
#### options.kzg
* **Type:** `Pick`
KZG implementation.
## Return Type
The flat list of cell KZG proofs.
`toCellProofs.ReturnType`
# Blobs.toCommitments
Compute commitments from a list of [`Blobs.Blobs`](/api/Blobs/types#blobs).
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const commitments = Blobs.toCommitments(blobs, { kzg }) // [!code focus]
```
### Configuring Return Type
It is possible to configure the return type with the `as` option.
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const commitments = Blobs.toCommitments(blobs, {
as: 'Bytes', // [!code focus]
kzg
})
// @log: [Uint8Array [ ... ], Uint8Array [ ... ]]
```
## Definition
```ts
function toCommitments(
blobs: blobs | Blobs | Blobs,
options: toCommitments.Options,
): toCommitments.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L516)
## Parameters
### blobs
* **Type:** `blobs | Blobs | Blobs`
The [`Blobs.Blobs`](/api/Blobs/types#blobs) to transform to commitments.
### options
* **Type:** `toCommitments.Options`
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
#### options.kzg
* **Type:** `Pick`
KZG implementation.
## Return Type
The commitments.
`toCommitments.ReturnType`
# Blobs.toHex
Transforms Ox-shaped [`Blobs.Blobs`](/api/Blobs/types#blobs) into the originating data.
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts twoslash
import { Blobs, Hex } from 'ox'
const blobs = Blobs.from('0xdeadbeef')
const data = Blobs.toHex(blobs) // [!code focus]
// @log: '0xdeadbeef'
```
## Definition
```ts
function toHex(
blobs: Blobs | Blobs,
): toHex.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L452)
## Parameters
### blobs
* **Type:** `Blobs | Blobs`
## Return Type
`toHex.ReturnType`
# Blobs.toVersionedHashes
Compute Blob Versioned Hashes from a list of [`Blobs.Blobs`](/api/Blobs/types#blobs).
## Imports
:::code-group
```ts [Named]
import { Blobs } from 'ox'
```
```ts [Entrypoint]
import * as Blobs from 'ox/Blobs'
```
:::
## Examples
```ts twoslash
// @noErrors
import { Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const versionedHashes = Blobs.toVersionedHashes(blobs, {
kzg
}) // [!code focus]
```
## Definition
```ts
function toVersionedHashes(
blobs: blobs | Blobs | Blobs,
options: toVersionedHashes.Options,
): toVersionedHashes.ReturnType
```
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L675)
## Parameters
### blobs
* **Type:** `blobs | Blobs | Blobs`
The [`Blobs.Blobs`](/api/Blobs/types#blobs) to transform into Blob Versioned Hashes.
### options
* **Type:** `toVersionedHashes.Options`
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
#### options.kzg
* **Type:** `Pick`
KZG implementation.
## Return Type
The Blob Versioned Hashes.
`toVersionedHashes.ReturnType`
# Blobs Errors
## `Blobs.BlobSizeTooLargeError`
Thrown when the blob size is too large.
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L708)
## `Blobs.EmptyBlobError`
Thrown when the blob is empty.
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L718)
## `Blobs.EmptyBlobVersionedHashesError`
Thrown when the blob versioned hashes are empty.
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L726)
## `Blobs.InvalidVersionedHashSizeError`
Thrown when the blob versioned hash size is invalid.
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L734)
## `Blobs.InvalidVersionedHashVersionError`
Thrown when the blob versioned hash version is invalid.
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L744)
# Blobs Types
## `Blobs.Blob`
Root type for a Blob.
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L31)
## `Blobs.Blobs`
A list of [`Blobs.Blob`](/api/Blobs/types#blob).
**Source:** [src/core/Blobs.ts](https://github.com/wevm/ox/blob/main/src/core/Blobs.ts#L35)
# Kzg
Utility functions for working with KZG Commitments.
Mainly for [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) Blobs.
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Kzg.from`](/api/Kzg/from) | Defines a KZG interface. |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`Kzg.Kzg`](/api/Kzg/types#kzgkzg) | Root type for a KZG interface. |
# Kzg.from
Defines a KZG interface.
## Imports
:::code-group
```ts [Named]
import { Kzg } from 'ox'
```
```ts [Entrypoint]
import * as Kzg from 'ox/Kzg'
```
:::
## Examples
```ts twoslash
// @noErrors
import * as cKzg from 'c-kzg'
import { Kzg } from 'ox'
import { Paths } from 'ox/trusted-setups'
cKzg.loadTrustedSetup(Paths.mainnet)
const kzg = Kzg.from(cKzg)
```
## Definition
```ts
function from(
value: Kzg,
): Kzg
```
**Source:** [src/core/Kzg.ts](https://github.com/wevm/ox/blob/main/src/core/Kzg.ts#L66)
## Parameters
### value
* **Type:** `Kzg`
The KZG object to convert.
#### value.cells
* **Type:** `readonly Uint8Array[]`
#### value.proofs
* **Type:** `readonly Uint8Array[]`
## Return Type
The KZG interface object.
`Kzg`
# Kzg Types
## `Kzg.Kzg`
Root type for a KZG interface.
**Source:** [src/core/Kzg.ts](https://github.com/wevm/ox/blob/main/src/core/Kzg.ts#L8)
# BlobCells
Cell-level helpers for [PeerDAS (EIP-7594)](https://eips.ethereum.org/EIPS/eip-7594):
deriving the 128 cells and cell KZG proofs of an extended blob, and verifying
cell proofs against blob commitments.
## Examples
```ts twoslash
// @noErrors
import { BlobCells, Blobs } from 'ox'
import { kzg } from './kzg'
const [blob] = Blobs.from('0xdeadbeef')
const { cells, proofs } = BlobCells.fromBlob(blob, { kzg })
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`BlobCells.fromBlob`](/api/BlobCells/fromBlob) | Compute the cells and KZG proofs for a single blob (PeerDAS, EIP-7594). |
| [`BlobCells.recover`](/api/BlobCells/recover) | Reconstruct all 128 cells (and their KZG proofs) of an extended blob from at least 64 known cells (PeerDAS, EIP-7594). |
| [`BlobCells.toDataColumns`](/api/BlobCells/toDataColumns) | Build the 128 PeerDAS data columns from a list of blobs (EIP-7594). |
| [`BlobCells.verify`](/api/BlobCells/verify) | Verify a batch of cell KZG proofs against their commitments (PeerDAS, EIP-7594). |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`BlobCells.InsufficientCellsError`](/api/BlobCells/errors#blobcellsinsufficientcellserror) | Thrown when fewer than [`BlobCells.cellsPerExtBlob`](/api/BlobCells)/2 cells are passed to [`BlobCells.recover`](/api/BlobCells/recover). |
| [`BlobCells.MismatchedLengthsError`](/api/BlobCells/errors#blobcellsmismatchedlengthserror) | Thrown when two parallel input arrays have different lengths. |
## Types
| Name | Description |
| ------------------- | ----------------------------------- |
| [`BlobCells.Cell`](/api/BlobCells/types#blobcellscell) | Root type for a Cell. |
| [`BlobCells.CellIndex`](/api/BlobCells/types#blobcellscellindex) | The 0-based index of a cell within an extended blob (0…127). |
| [`BlobCells.CellProof`](/api/BlobCells/types#blobcellscellproof) | Root type for a cell KZG proof. |
| [`BlobCells.ColumnIndex`](/api/BlobCells/types#blobcellscolumnindex) | The 0-based index of a column across all blobs in a block (0…127). |
| [`BlobCells.DataColumn`](/api/BlobCells/types#blobcellsdatacolumn) | A PeerDAS data column for a single block: one cell + cell proof per blob, plus the blob-level commitments needed to verify them. |
# BlobCells.fromBlob
Compute the cells and KZG proofs for a single blob (PeerDAS, EIP-7594).
Returns 128 cells (each 2048 bytes) and 128 cell-level KZG proofs (each 48 bytes).
## Imports
:::code-group
```ts [Named]
import { BlobCells } from 'ox'
```
```ts [Entrypoint]
import * as BlobCells from 'ox/BlobCells'
```
:::
## Examples
```ts twoslash
// @noErrors
import { BlobCells, Blobs } from 'ox'
import { kzg } from './kzg'
const [blob] = Blobs.from('0xdeadbeef')
const { cells, proofs } = BlobCells.fromBlob(blob, { kzg })
```
## Definition
```ts
function fromBlob(
blob: blob | Hex.Hex | Bytes.Bytes,
options: fromBlob.Options,
): fromBlob.ReturnType
```
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L68)
## Parameters
### blob
* **Type:** `blob | Hex.Hex | Bytes.Bytes`
The blob to convert.
### options
* **Type:** `fromBlob.Options`
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
#### options.kzg
* **Type:** `Pick`
KZG implementation.
## Return Type
The cells and proofs.
`fromBlob.ReturnType`
# BlobCells.recover
Reconstruct all 128 cells (and their KZG proofs) of an extended blob from at least 64 known cells (PeerDAS, EIP-7594).
## Imports
:::code-group
```ts [Named]
import { BlobCells } from 'ox'
```
```ts [Entrypoint]
import * as BlobCells from 'ox/BlobCells'
```
:::
## Examples
```ts twoslash
// @noErrors
import { BlobCells } from 'ox'
import { kzg } from './kzg'
// Reconstruct from 64 of 128 cells.
const { cells, proofs } = BlobCells.recover(
knownIndices, // e.g. [0, 2, 4, …]
knownCells,
{ kzg }
)
```
## Definition
```ts
function recover(
cellIndices: readonly CellIndex[],
cells: cells | readonly (Hex.Hex | Bytes.Bytes)[],
options: recover.Options,
): recover.ReturnType
```
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L206)
## Parameters
### cellIndices
* **Type:** `readonly CellIndex[]`
The indices of the known cells (must contain ≥ 64 distinct values).
### cells
* **Type:** `cells | readonly (Hex.Hex | Bytes.Bytes)[]`
The known cells, parallel to `cellIndices`.
### options
* **Type:** `recover.Options`
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
#### options.kzg
* **Type:** `Pick`
KZG implementation.
## Return Type
The full set of 128 cells and 128 proofs.
`recover.ReturnType`
# BlobCells.toDataColumns
Build the 128 PeerDAS data columns from a list of blobs (EIP-7594).
For each column index `i ∈ [0, 128)`, produces a [`BlobCells.DataColumn`](/api/BlobCells/types#datacolumn) containing one cell + one cell proof per blob (at column `i` of each blob's extended form), alongside the blob-level commitments needed to verify them.
## Imports
:::code-group
```ts [Named]
import { BlobCells } from 'ox'
```
```ts [Entrypoint]
import * as BlobCells from 'ox/BlobCells'
```
:::
## Examples
```ts twoslash
// @noErrors
import { BlobCells, Blobs } from 'ox'
import { kzg } from './kzg'
const blobs = Blobs.from('0xdeadbeef')
const columns = BlobCells.toDataColumns(blobs, { kzg }) // 128 columns
```
## Definition
```ts
function toDataColumns(
blobs: blobs | Blobs.Blobs | Blobs.Blobs,
options: toDataColumns.Options,
): toDataColumns.ReturnType
```
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L301)
## Parameters
### blobs
* **Type:** `blobs | Blobs.Blobs | Blobs.Blobs`
The blobs to convert.
### options
* **Type:** `toDataColumns.Options`
Options.
#### options.as
* **Type:** `"Bytes" | "Hex" | as`
* **Optional**
Return type.
#### options.kzg
* **Type:** `Pick`
KZG implementation.
## Return Type
128 data columns.
`toDataColumns.ReturnType`
# BlobCells.verify
Verify a batch of cell KZG proofs against their commitments (PeerDAS, EIP-7594).
Each cell at index `cellIndices[i]` is checked against the commitment `commitments[i]` using the proof `proofs[i]`.
## Imports
:::code-group
```ts [Named]
import { BlobCells } from 'ox'
```
```ts [Entrypoint]
import * as BlobCells from 'ox/BlobCells'
```
:::
## Examples
```ts twoslash
// @noErrors
import { BlobCells, Blobs } from 'ox'
import { kzg } from './kzg'
const [blob] = Blobs.from('0xdeadbeef')
const [commitment] = Blobs.toCommitments([blob], { kzg })
const { cells, proofs } = BlobCells.fromBlob(blob, { kzg })
const valid = BlobCells.verify({
cells,
cellIndices: cells.map((_, i) => i),
commitments: cells.map(() => commitment),
proofs,
kzg
})
```
## Definition
```ts
function verify(
options: verify.Options,
): boolean
```
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L154)
## Parameters
### options
* **Type:** `verify.Options`
Verification options.
#### options.cellIndices
* **Type:** `readonly number[]`
Cell indices within their respective extended blobs.
#### options.cells
* **Type:** `readonly (0x${string} | Uint8Array)[]`
Cells to verify.
#### options.commitments
* **Type:** `readonly (0x${string} | Uint8Array)[]`
Commitments, one per cell (parallel to `cells`).
#### options.kzg
* **Type:** `Pick`
KZG implementation.
#### options.proofs
* **Type:** `readonly (0x${string} | Uint8Array)[]`
Proofs, one per cell (parallel to `cells`).
## Return Type
Whether all (commitment, cell, proof) tuples verify.
`boolean`
# BlobCells Errors
## `BlobCells.InsufficientCellsError`
Thrown when fewer than [`BlobCells.cellsPerExtBlob`](/api/BlobCells)/2 cells are passed to [`BlobCells.recover`](/api/BlobCells/recover).
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L362)
## `BlobCells.MismatchedLengthsError`
Thrown when two parallel input arrays have different lengths.
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L373)
# BlobCells Types
## `BlobCells.Cell`
Root type for a Cell.
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L18)
## `BlobCells.CellIndex`
The 0-based index of a cell within an extended blob (0…127).
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L27)
## `BlobCells.CellProof`
Root type for a cell KZG proof.
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L22)
## `BlobCells.ColumnIndex`
The 0-based index of a column across all blobs in a block (0…127).
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L30)
## `BlobCells.DataColumn`
A PeerDAS data column for a single block: one cell + cell proof per blob, plus the blob-level commitments needed to verify them.
**Source:** [src/core/BlobCells.ts](https://github.com/wevm/ox/blob/main/src/core/BlobCells.ts#L36)
# AesGcm
Utilities & types for working with AES-GCM encryption. Internally uses the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API).
## Examples
Below are some examples demonstrating common usages of the `AesGcm` module:
* [Encrypting Data](#encrypting-data)
* [Decrypting Data](#decrypting-data)
### Encrypting Data
Data can be encrypted using [`AesGcm.encrypt`](/api/AesGcm/encrypt):
```ts twoslash
import { AesGcm, Hex } from 'ox'
const key = await AesGcm.getKey({ password: 'qwerty' })
const secret = Hex.fromString('i am a secret message')
const encrypted = await AesGcm.encrypt(secret, key) // [!code focus]
// @log: '0x5e257b25bcf53d5431e54e5a68ca0138306d31bb6154f35a97bb8ea18111e7d82bcf619d3c76c4650688bc5310eed80b8fc86d1e3e'
```
### Decrypting Data
Data can be decrypted using [`AesGcm.decrypt`](/api/AesGcm/decrypt):
```ts twoslash
import { AesGcm, Hex } from 'ox'
const key = await AesGcm.getKey({ password: 'qwerty' })
const encrypted = await AesGcm.encrypt(
Hex.fromString('i am a secret message'),
key
)
const decrypted = await AesGcm.decrypt(encrypted, key) // [!code focus]
// @log: Hex.fromString('i am a secret message')
```
## Functions
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AesGcm.decrypt`](/api/AesGcm/decrypt) | Decrypts encrypted data using AES-GCM. |
| [`AesGcm.encrypt`](/api/AesGcm/encrypt) | Encrypts data using AES-GCM. |
| [`AesGcm.fromPrf`](/api/AesGcm/fromPrf) | Derives an AES-256-GCM key from a 32-byte WebAuthn PRF output. |
| [`AesGcm.getKey`](/api/AesGcm/getKey) | Derives an AES-GCM key from a password using PBKDF2. |
| [`AesGcm.randomSalt`](/api/AesGcm/randomSalt) | Generates a random salt of the specified size. |
## Errors
| Name | Description |
| ------------------- | ----------------------------------- |
| [`AesGcm.InvalidPrfSizeError`](/api/AesGcm/errors#aesgcminvalidprfsizeerror) | Thrown when a WebAuthn PRF output is not 32 bytes. |
# AesGcm.decrypt
Decrypts encrypted data using AES-GCM.
## Imports
:::code-group
```ts [Named]
import { AesGcm } from 'ox'
```
```ts [Entrypoint]
import * as AesGcm from 'ox/AesGcm'
```
:::
## Examples
```ts twoslash
import { AesGcm, Hex } from 'ox'
const key = await AesGcm.getKey({ password: 'qwerty' })
const secret = Hex.fromString('i am a secret message')
const encrypted = await AesGcm.encrypt(secret, key)
const decrypted = await AesGcm.decrypt(encrypted, key) // [!code focus]
// @log: Hex.fromString('i am a secret message')
```
## Definition
```ts
function decrypt(
value: value | Bytes.Bytes | Hex.Hex,
key: CryptoKey,
options?: decrypt.Options,
): Promise>
```
**Source:** [src/core/AesGcm.ts](https://github.com/wevm/ox/blob/main/src/core/AesGcm.ts#L28)
## Parameters
### value
* **Type:** `value | Bytes.Bytes | Hex.Hex`
The data to encrypt.
### key
* **Type:** `CryptoKey`
The `CryptoKey` to use for encryption.
### options
* **Type:** `decrypt.Options