Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Types – ERC-8128
Skip to content

Types

Glossary of types in @slicekit/erc8128.

Hex

Hex-encoded string with 0x prefix.

type Hex = `0x${string}`

Address

Ethereum address (40 hex characters with 0x prefix).

type Address = `0x${string}`

EthHttpSigner

Interface for Ethereum message signing. Used by signRequest and signedFetch.

interface EthHttpSigner {
  /** Ethereum address (EOA or smart contract account) */
  address: Address
  
  /** Chain ID for the keyid */
  chainId: number
  
  /** Sign the RFC 9421 signature base as an Ethereum message (EIP-191) */
  signMessage: (message: Uint8Array) => Promise<Hex>
}

Example

Here's how to create an EthHttpSigner using viem's privateKeyToAccount:

import type { EthHttpSigner } from '@slicekit/erc8128'
import { privateKeyToAccount } from 'viem/accounts'
 
const account = privateKeyToAccount('0x...')
 
const signer: EthHttpSigner = {
  chainId: 1,
  address: account.address,
  signMessage: async (message) => {
    return account.signMessage({ message: { raw: message } })
  },
}

SignOptions

Options for signRequest and signedFetch.

type SignOptions = {
  /** Signature label (default: "eth") */
  label?: string
  
  /** Binding mode (default: "request-bound") */
  binding?: BindingMode
  
  /** Replay mode (default: "non-replayable") */
  replay?: ReplayMode
  
  /** Unix timestamp when signature becomes valid (default: now) */
  created?: number
  
  /** Unix timestamp when signature expires (default: created + ttlSeconds) */
  expires?: number
  
  /** Validity duration in seconds (default: 60) */
  ttlSeconds?: number
  
  /** Custom nonce value or generator function */
  nonce?: string | (() => Promise<string>)
  
  /** Content-Digest handling (default: "auto") */
  contentDigest?: ContentDigestMode
  
  /** Additional components to sign beyond the default set */
  components?: string[]
}

BindingMode

Controls which request components are signed.

type BindingMode = "request-bound" | "class-bound"
ValueDescription
request-boundSign @authority, @method, @path, @query (if present), and content-digest (if body present). This is the secure default.
class-boundSign only the components you explicitly specify. Requires components array.

ReplayMode

Controls whether requests can be replayed.

type ReplayMode = "non-replayable" | "replayable"
ValueDescription
non-replayableInclude a nonce (auto-generated if not provided). Default.
replayableNo nonce. Signature can be reused within its validity window. Trades single-use guarantee for reduced overhead.

ContentDigestMode

Controls Content-Digest header handling.

type ContentDigestMode = "auto" | "recompute" | "require" | "off"
ValueDescription
autoAdd Content-Digest if body is present and components include it. Default.
recomputeAlways recompute Content-Digest even if header exists.
requireRequire existing Content-Digest header.
offDon't add Content-Digest.

VerifyPolicy

Policy for verifyRequest.

type VerifyPolicy = {
  /** Preferred signature label (default: "eth") */
  label?: string
  
  /** If true, require exact label match (default: false) */
  strictLabel?: boolean
  
  /**
   * Extra components required in addition to the default request-bound set.
   * Use this for custom headers like 'x-idempotency-key'.
   */
  additionalRequestBoundComponents?: string[]
  
  /**
   * Class-bound policies (one list or a list of lists).
   * If any policy list is covered by the signed components, the signature is accepted.
   * `@authority` is always required (added if missing).
   */
  classBoundPolicies?: string[] | string[][]
  
  /** Allow replayable (nonce-less) signatures (default: false) */
  replayable?: boolean
 
  /**
   * Optional replayable invalidation (per-keyid).
   * When set and a signature is replayable, requests with created < notBefore are rejected.
   */
  replayableNotBefore?: (keyid: string) => number | null | undefined | Promise<number | null | undefined>
 
  /**
   * Optional per-signature invalidation hook for replayable signatures.
   * Return true to mark the signature as invalidated.
   */
  replayableInvalidated?: (args: {
    keyid: string
    created: number
    expires: number
    label: string
    signature: Hex
    signatureBase: Uint8Array
    signatureParamsValue: string
  }) => boolean | Promise<boolean>
  
  /** Maximum number of signatures to verify (default: 3) */
  maxSignatureVerifications?: number
  
  /** Current time function (default: Date.now() / 1000) */
  now?: () => number
  
  /** Allowed clock skew in seconds (default: 0) */
  clockSkewSec?: number
  
  /** Maximum validity window in seconds (default: 300) */
  maxValiditySec?: number
  
  /** Maximum nonce validity window (optional) */
  maxNonceWindowSec?: number
  
  /** Custom key generator for nonce storage */
  nonceKey?: (keyid: string, nonce: string) => string
}

NonceStore

Interface for replay protection storage. See NonceStore implementations.

interface NonceStore {
  /**
   * Atomically consume a nonce.
   * Returns true if newly stored (not seen before), false if already exists.
   */
  consume(key: string, ttlSeconds: number): Promise<boolean>
}

VerifyMessageFn

Function type for verifying Ethereum signatures. See VerifyMessageFn with viem.

type VerifyMessageFn = (args: {
  address: Address
  message: { raw: Hex }
  signature: Hex
}) => boolean | Promise<boolean>

VerifyResult

Result of verifyRequest.

type VerifyResult =
  | {
      ok: true
      address: Address
      chainId: number
      label: string
      components: string[]
      params: SignatureParams
      replayable: boolean
      binding: BindingMode
    }
  | {
      ok: false
      reason: VerifyFailReason
      detail?: string
    }

Success Properties

PropertyTypeDescription
oktrueVerification succeeded
addressAddressVerified Ethereum address
chainIdnumberChain ID from keyid
labelstringSignature label that was verified
componentsstring[]Components that were signed
paramsSignatureParamsParsed signature parameters
replayablebooleanWhether the signature is replayable (nonce-less)
bindingBindingModeBinding mode used by the signature

Failure Properties

PropertyTypeDescription
okfalseVerification failed
reasonVerifyFailReasonWhy verification failed
detailstring?Optional detail message

SignatureParams

Parsed signature parameters from Signature-Input header.

type SignatureParams = {
  created: number
  expires: number
  keyid: string
  nonce?: string
  tag?: string
}

VerifyFailReason

All possible verification failure reasons. See Failure Reasons for descriptions.

type VerifyFailReason =
  | "missing_headers"
  | "label_not_found"
  | "bad_signature_input"
  | "bad_signature"
  | "bad_keyid"
  | "bad_time"
  | "not_yet_valid"
  | "expired"
  | "validity_too_long"
  | "nonce_required"
  | "replayable_not_allowed"
  | "replayable_invalidation_required"
  | "replayable_not_before"
  | "replayable_invalidated"
  | "class_bound_not_allowed"
  | "nonce_window_too_long"
  | "replay"
  | "not_request_bound"
  | "digest_required"
  | "digest_mismatch"
  | "alg_not_allowed"
  | "bad_signature_bytes"
  | "bad_signature_check"

Client

Return type of createSignerClient. Provides bound methods for signing requests.

type Client = {
  signRequest: {
    (input: RequestInfo, opts?: SignOptions): Promise<Request>
    (input: RequestInfo, init: RequestInit | undefined, opts?: SignOptions): Promise<Request>
  }
  signedFetch: {
    (input: RequestInfo, opts?: ClientOptions): Promise<Response>
    (input: RequestInfo, init: RequestInit | undefined, opts?: ClientOptions): Promise<Response>
  }
  fetch: {
    (input: RequestInfo, opts?: ClientOptions): Promise<Response>
    (input: RequestInfo, init: RequestInit | undefined, opts?: ClientOptions): Promise<Response>
  }
}

Methods

MethodDescription
signRequestSign a request without sending
signedFetchSign and send a request
fetchAlias for signedFetch

ClientOptions

Options for createSignerClient and client methods. Extends SignOptions.

type ClientOptions = SignOptions & { fetch?: typeof fetch }

VerifierClient

Return type of createVerifierClient. Provides a bound method for verifying requests.

type VerifierClient = {
  verifyRequest: (args: {
    request: Request
    policy?: VerifyPolicy
    setHeaders?: (name: string, value: string) => void
  }) => Promise<VerifyResult>
}

Methods

MethodDescription
verifyRequestVerify a signed request

VerifierClientOptions

Options for createVerifierClient and client methods. Extends VerifyPolicy.

type VerifierClientOptions = VerifyPolicy

SetHeadersFn

Callback to set response headers. Used by verifyRequest to emit Accept-Signature.

type SetHeadersFn = (name: string, value: string) => void

VerifyRequestArgs

Argument object for verifyRequest.

type VerifyRequestArgs = {
  request: Request
  verifyMessage: VerifyMessageFn
  nonceStore: NonceStore
  policy?: VerifyPolicy
  setHeaders?: SetHeadersFn
}
PropertyTypeDescription
requestRequestThe HTTP request to verify
verifyMessageVerifyMessageFnSignature verification function
nonceStoreNonceStoreReplay protection store
policyVerifyPolicyOptional verification policy
setHeadersSetHeadersFnOptional callback to set Accept-Signature response header

VerifierClientVerifyRequestArgs

Argument object for verifierClient.verifyRequest(). The client already has verifyMessage and nonceStore bound, so only request and optional overrides are needed.

type VerifierClientVerifyRequestArgs = {
  request: Request
  policy?: VerifyPolicy
  setHeaders?: SetHeadersFn
}

CreateVerifierClientArgs

Argument object for createVerifierClient.

type CreateVerifierClientArgs = {
  verifyMessage: VerifyMessageFn
  nonceStore: NonceStore
  defaults?: VerifyPolicy
}
PropertyTypeDescription
verifyMessageVerifyMessageFnSignature verification function
nonceStoreNonceStoreReplay protection store
defaultsVerifyPolicyDefault policy applied to all requests

Erc8128Error

Custom error class for ERC-8128 operations.

class Erc8128Error extends Error {
  code: Erc8128ErrorCode
}

Erc8128ErrorCode

Error codes for Erc8128Error.

type Erc8128ErrorCode =
  | "CRYPTO_UNAVAILABLE"   // WebCrypto not available
  | "INVALID_OPTIONS"      // Bad sign options
  | "UNSUPPORTED_REQUEST"  // Can't sign this request
  | "BODY_READ_FAILED"     // Can't read request body
  | "DIGEST_REQUIRED"      // Content-Digest required but not present
  | "BAD_DERIVED_VALUE"    // Can't derive component value
  | "BAD_HEADER_VALUE"     // Invalid header format
  | "PARSE_ERROR"          // Can't parse input

Example

Catch Erc8128Error to handle specific error codes during signing or verification:

import { signRequest, Erc8128Error } from '@slicekit/erc8128'
 
try {
  const signedRequest = await signRequest(input, signer)
} catch (error) {
  if (error instanceof Erc8128Error) {
    console.error(`Error (${error.code}): ${error.message}`)
  }
  throw error
}