Skip to content

TypeScript SDK

The public package is @smart-byte/leani-sdk, for Node 20.3+ and Bun 1.2+. In a source checkout, run bun install --cwd packages/sdk and bun run --cwd packages/sdk build. The query/follow guide includes an executable client, a matching node config, and pagination/reset handling.

For a node started with leani init blocks and leani serve:

import { createLeaniClient } from "@smart-byte/leani-sdk";
const leani = createLeaniClient({ baseUrl: "http://127.0.0.1:18080" });
const stop = new AbortController();
for await (const change of leani.blocks.subscribe({ signal: stop.signal })) {
if (change.operation === "apply" && change.data) {
console.log(change.data.blockNumber);
}
}

Pass an AbortSignal to cancel an idle subscription; breaking out of the loop also cancels its response body. Transport disconnects reconnect from the last yielded cursor. Protocol errors and expired history require application action. An incomplete final event is discarded before reconnecting. Retryable HTTP errors, including rate limiting, use the configured reconnect backoff, and so do error events marked retryable; after five of them in a row without a new change, the subscription throws the last one. A stream that sends nothing, not even the node’s 15-second keep-alive comments, for idleTimeoutMs (default 60,000) while the loop waits reconnects too. An event over 8 MiB fails the subscription with a non-retryable invalid_response error. This print-only example does not maintain state; stateful consumers must apply undo mutations too.

A request that fails below HTTP rejects with TransportError, a LeaniError with status 0, code: "transport", retryable: true, and the runtime’s error as cause: a refused or reset connection, a response body that breaks off, a passed deadline, or a silent stream. Aborting your own signal rejects with its reason instead, and the SDK never retries it. The SDK does not follow redirects: a 3xx answer rejects with the non-retryable redirect_refused, with the target in details.location, so configure the final URL as baseUrl. Every request path resolves under the base URL’s path, one starting with / included. A path segment that decodes to . or .., or holds a backslash, an encoded slash or backslash (%2F, %5C), or an encoded percent sign (%25), and a control character anywhere in the path, are refused before any request. request() applies the same rule to a custom query extension’s path, so a path parameter whose value can hold / or % must move to the query string, request()’s params.

Typed subscriptions accept processor to select a configured instance, for example leani.blobs.subscribe({ processor: "blobs-production" }). The blobs apply payload is { block, transactions }. Narrow operation before reading processor data: finalized carries { throughBlock } instead, or, when isLiveGapChange() holds, the { fromBlock, toBlock } the live lane skipped. liveGapBackfill() in @smart-byte/leani-sdk/backfill turns that range into an idempotent fill_missing subscription request; see Keep your application in sync. Discover canonical query paths with capabilities() and pass queryBasePaths when aliases are ambiguous.

queryAndFollow() returns the first page of an immutable snapshot and its stream boundary. Follow every nextCursor with queryEntities(), release the snapshot in finally, then subscribe from boundaryCursor. SSE resets throw ResetRequiredError; HTTP expiry throws LeaniError with code: "cursor_expired" or "query_snapshot_expired". Rebuild the seed for either case.

queryEntities() also works when delivery is disabled; its boundaryCursor and recovery.follow are then null. queryAndFollow() requires delivery and returns a FollowSnapshotPage with a non-null boundary, or HTTP 409 delivery_disabled. The stream and change endpoints return the same error when delivery is disabled.

Durable live/history sessions live in @smart-byte/leani-sdk/backfill. Construct them with createBackfillSubscriptionClient({ baseUrl, token, fetch, timeoutMs }); both entry points use the same LeaniError and TransportError classes and HTTP error fields (status, code, retryable, requestId). The deadline applies to JSON requests, lease renewals, and acknowledgements, and to a stream until its hello arrives. An established stream that sends nothing, heartbeats included, for three heartbeatIntervalMs while its iterator waits fails with a TransportError; time spent handling a record does not count. A lease renewal that fails with a retryable error is retried with backoff while the lease holds; one that fails otherwise, or keeps failing until the lease would lapse, ends the session at once, and the iterator throws its error. The lanes of subscribe() reconnect after either, and after any other retryable error. A stream record over 65 MiB fails the session with a non-retryable invalid_response error. A backfill stream can request smaller batches with batching.maximumEncodedBytes; streamLive() takes no batching option, so a live stream’s batches follow the node’s api.delivery.live_batches.maximum_encoded_bytes. Always close delivery sessions in finally. Commit idempotent destination writes before acknowledging a batch. Acknowledge a batch’s boundary, never a change’s own cursor: the node refuses one inside a live block or a history progress unit. A backfill session’s deliveryBatches() yields every boundary as ackCursor with the events it covers, including batches without changes and the completion; events() flattens the changes without boundaries. A consumer with a credential passes it as credential on every call and stream. retry(subscription) re-queues a failed subscription to resume from its committed progress, and delete(subscription, { discardUnacknowledged: true }) deletes a failed or cancelled one whose consumer has not acknowledged every record. See durable delivery for lease and reset semantics.

Run a history subscription in one call

runBackfill(client, request, options) in @smart-byte/leani-sdk/backfill runs an application-owned subscription to its end; request must name its consumer. It creates the subscription, applies each history batch with options.onBatch and acknowledges it once that resolves, acknowledges the completion, closes the session, and deletes the subscription. It resolves with the outcome (completed, cancelled, or failed), the subscription as it ended, the completion record it received, if it streamed one, and the deletion. Creation is idempotent by idempotencyKey: running the identical request again, as after a crash, resumes the same subscription after its last acknowledged batch, and the node refuses a different request under the same key. A batch applied but not acknowledged is delivered again, so onBatch must be idempotent. A subscription already complete when created is deleted without opening its stream.

After a lost connection or consumer session, or while another connection still holds the consumer’s session, it waits a backoff of 1 second, doubling up to 30 seconds, and reads the subscription’s state before it opens the stream again: a subscription that ended meanwhile, as when the node applied the completion’s acknowledgement but its answer was lost, ends the run instead. A failed subscription follows options.onFailure. "retry", the default, re-queues it with retry(), up to maxRetries times (3 by default), then throws a BackfillStreamError with code: "backfill_failed" and leaves it failed. "discard" deletes it with discardUnacknowledged: true and resolves with the outcome failed, and "throw" throws at once. A cancelled subscription is deleted with discardUnacknowledged: true. An error from onBatch, a reset_required stream, any other failure, and an abort of options.signal or request.signal close the session and reject without deleting the subscription, so the identical request can run again once the cause is fixed. The stream presents options.credential, by default the request’s consumer.credential.

Inventory

The inventory below is generated from both public entry points and shared error types. The backfill.* members belong to the backfill client.

baseUrl

MemberContract
baseUrlreadonly baseUrl: URL

request

MemberContract
requestrequest<T>( path: string, params?: Record<string, QueryValue>, options?: { signal?: AbortSignal }, ): Promise<T>

health

MemberContract
health.livelive(options?: { signal?: AbortSignal }): Promise<Health>
health.readyready(options?: { signal?: AbortSignal }): Promise<Health>

status

MemberContract
statusstatus(options?: { signal?: AbortSignal }): Promise<NodeStatus>

capabilities

MemberContract
capabilitiescapabilities(options?: { signal?: AbortSignal }): Promise<Capabilities>

processors

MemberContract
processors.listlist(options?: { signal?: AbortSignal }): Promise<ProcessorSummary[]>
processors.statusstatus( id: string, options?: { signal?: AbortSignal }, ): Promise<ProcessorCoverage>
processors.changeschanges<T = unknown>( id: string, options?: ChangesOptions, ): Promise<Page<ChangeEnvelope<T>>>
processors.changeHeadchangeHead( id: string, options?: { signal?: AbortSignal }, ): Promise<ChangeHead>
processors.resetLiveLaneresetLiveLane( id: string, options?: { signal?: AbortSignal }, ): Promise<LiveLaneReset>
processors.listCollectionslistCollections( id: string, options?: { signal?: AbortSignal }, ): Promise<{ processor: ProcessorSummary; outputMode: "none" | "latest" | "window" | "full"; retained: boolean; data: string[]; }>
processors.queryEntitiesqueryEntities<T = unknown>( id: string, collection: string, options?: OutputQueryOptions, ): Promise<GenericSnapshotPage<T>>
processors.queryAndFollowqueryAndFollow<T = unknown>( id: string, collection: string, options?: Omit<OutputQueryOptions, "cursor">, ): Promise<FollowSnapshotPage<T>>
processors.getEntitygetEntity<T = unknown>( id: string, collection: string, key: Hex, options?: { signal?: AbortSignal }, ): Promise<GenericOutputEntity<T>>
processors.releaseSnapshotreleaseSnapshot( id: string, snapshotId: string, options?: { signal?: AbortSignal }, ): Promise<void>
processors.consumers.listlist( id: string, options?: { signal?: AbortSignal }, ): Promise<DurableConsumer[]>
processors.consumers.createcreate( id: string, options: CreateConsumerOptions, ): Promise<DurableConsumer>
processors.consumers.inspectinspect( id: string, consumer: string, options?: { signal?: AbortSignal }, ): Promise<DurableConsumer>
processors.consumers.revokerevoke( id: string, consumer: string, options?: { signal?: AbortSignal }, ): Promise<DurableConsumer>
processors.consumers.renewrenew( id: string, consumer: string, credential: string, options?: { signal?: AbortSignal }, ): Promise<DurableConsumer>
processors.consumers.changeschanges<T = unknown>( id: string, consumer: string, credential: string, options?: { limit?: number; signal?: AbortSignal }, ): Promise<Page<ChangeEnvelope<T>>>
processors.consumers.acknowledgeacknowledge( id: string, consumer: string, credential: string, cursor: string, options?: { signal?: AbortSignal }, ): Promise<DurableConsumer>
processors.subscribesubscribe<T = unknown>( id: string, options?: SubscribeOptions, ): AsyncGenerator<ChangeEnvelope<T>>

blobs

MemberContract
blobs.getBlockgetBlock( number: number, options?: { signal?: AbortSignal }, ): Promise<BlobsBlock>
blobs.listBlockslistBlocks(options: ListBlocksOptions): Promise<Page<BlobsBlock>>
blobs.listSnapshotlistSnapshot( options: ListBlocksOptions, ): Promise<Page<BlobsSnapshotEntry>>
blobs.getTransactiongetTransaction( hash: Hex, options?: { signal?: AbortSignal }, ): Promise<BlobTransaction>
blobs.listTransactionslistTransactions( options: ListTransactionsOptions, ): Promise<Page<BlobTransaction>>
blobs.getSchedulegetSchedule(options?: { atBlock?: number; signal?: AbortSignal; }): Promise<BlobSchedule>
blobs.subscribesubscribe( options?: ProcessorSubscribeOptions, ): AsyncGenerator<ChangeEnvelope<BlobsSnapshotEntry>>

erc20

MemberContract
erc20.getBalancegetBalance( token: Hex, address: Hex, options?: { signal?: AbortSignal }, ): Promise<Erc20Balance>
erc20.subscribesubscribe( options?: ProcessorSubscribeOptions, ): AsyncGenerator<ChangeEnvelope<Erc20Balance>>

uniswap

MemberContract
uniswap.getPoolgetPool( address: Hex, options?: { signal?: AbortSignal }, ): Promise<UniswapPoolPrice>
uniswap.getLatestObservationgetLatestObservation( address: Hex, options?: { processor?: string; signal?: AbortSignal }, ): Promise<LatestUniswapObservation>
uniswap.listConfiguredPoolslistConfiguredPools(options?: { processor?: string; signal?: AbortSignal; }): Promise<ConfiguredUniswapPools>
uniswap.subscribesubscribe( options?: ProcessorSubscribeOptions, ): AsyncGenerator<ChangeEnvelope<UniswapPoolPrice>>

blocks

MemberContract
blocks.getLatestgetLatest(options?: { processor?: string; signal?: AbortSignal; }): Promise<LatestBlockSummary>
blocks.getByNumbergetByNumber( number: number, options?: { processor?: string; signal?: AbortSignal }, ): Promise<LatestBlockSummary>
blocks.subscribesubscribe( options?: ProcessorSubscribeOptions, ): AsyncGenerator<ChangeEnvelope<BlockSummary>>

backfill

MemberContract
backfill.baseUrlreadonly baseUrl: URL
backfill.createcreate(request: CreateBackfillSubscription): Promise<BackfillStatus>
backfill.listlist(options?: { signal?: AbortSignal }): Promise<BackfillStatus[]>
backfill.inspectinspect( subscription: string, options?: { signal?: AbortSignal }, ): Promise<BackfillStatus>
backfill.cancelcancel( subscription: string, options?: { signal?: AbortSignal }, ): Promise<BackfillStatus>
backfill.retryretry( subscription: string, options?: { signal?: AbortSignal }, ): Promise<BackfillStatus>
backfill.deletedelete( subscription: string, options?: { signal?: AbortSignal; discardUnacknowledged?: boolean }, ): Promise<HistoricalWorkDeletion>
backfill.changeschanges<T = unknown>( subscription: string, consumer: string, options?: { credential?: string; limit?: number; signal?: AbortSignal; }, ): Promise<{ data: ChangeEnvelope<T>[]; nextCursor: string | null; coverage: unknown; }>
backfill.streamstream<T = unknown>( subscription: string, consumer: string, options?: { credential?: string; batching?: BackfillBatchingRequest; signal?: AbortSignal; }, ): Promise<BackfillDeliverySession<T>>
backfill.streamLivestreamLive<T = unknown>( processor: string, consumer: string, options?: { credential?: string; signal?: AbortSignal }, ): Promise<LiveDeliverySession<T>>
backfill.subscribesubscribe<T = unknown>( request: MultiLaneSubscriptionRequest, ): Promise<MultiLaneDelivery<T>>

Exported types and helpers

Hex@smart-byte/leani-sdk
export type Hex = `0x${string}`;
Finality@smart-byte/leani-sdk
export type Finality = "unattested" | "attested" | "finalized";
ChangeOperation@smart-byte/leani-sdk
export type ChangeOperation =
  | "apply"
  | "undo"
  | "attested"
  | "finalized"
  | "reset_required";
LeaniClientOptions@smart-byte/leani-sdk
export interface LeaniClientOptions {
  baseUrl: string | URL;
  token?: string;
  timeoutMs?: number;
  fetch?: FetchLike;
  /**
   * Override typed query-extension mounts with canonical `basePath` values
   * returned by `capabilities()` when an ergonomic alias is unavailable.
   */
  queryBasePaths?: {
    blobs?: string;
    erc20?: string;
    uniswap?: string;
  };
  reconnect?: {
    initialDelayMs?: number;
    maxDelayMs?: number;
    jitter?: number;
  };
}
FetchLike@smart-byte/leani-sdk
export type FetchLike = (
  input: RequestInfo | URL,
  init?: RequestInit,
) => Promise<Response>;
ProcessorSummary@smart-byte/leani-sdk
export interface ProcessorSummary {
  id: string;
  instance: string;
  version: string;
  codeHash: Hex;
  configHash: Hex;
  genericApi: "processor-v1";
  changeSchema: string;
  queryExtensions: QueryExtensionSummary[];
  subscriptions: boolean;
  artifactRetention: "none" | "window" | "full";
  deliveryOrdering: "canonical" | "block_versioned_idempotent";
}
QueryExtensionSummary@smart-byte/leani-sdk
export interface QueryExtensionSummary {
  id: string;
  basePath: string;
  aliasPath: string | null;
}
QueryExtensionCapability@smart-byte/leani-sdk
export interface QueryExtensionCapability extends QueryExtensionSummary {
  processor: string;
}
Capabilities@smart-byte/leani-sdk
export interface Capabilities {
  chainId: number;
  ethereumRpc: Record<string, unknown>;
  processors: ProcessorSummary[];
  queryExtensions: QueryExtensionCapability[];
}
NodeStatus@smart-byte/leani-sdk
export interface NodeStatus {
  apiVersion: "1";
  project: string;
  version: string;
  chainId: number;
  uptimeSeconds: number;
  databaseBytes: number;
  processor: ProcessorSummary;
  processors: ProcessorSummary[];
  readiness: Readiness;
}
Readiness@smart-byte/leani-sdk
export interface Readiness {
  liveRequired: boolean;
  liveReady: boolean;
  finalityRequired: boolean;
  finalityReady: boolean;
  ready: boolean;
}
Health@smart-byte/leani-sdk
export interface Health {
  status: "live" | "ready" | "not_ready" | "failed";
  uptimeSeconds: number;
  database: "available" | "unavailable";
  readiness: Readiness;
  reasons: string[];
}
CoverageInterval@smart-byte/leani-sdk
export interface CoverageInterval {
  fromBlock: number;
  toBlock: number;
  finality: Finality;
}
ProcessorCoverage@smart-byte/leani-sdk
export interface ProcessorCoverage {
  chainId: number;
  chainFinalizedHead: {
    number: number;
    hash: string;
  } | null;
  requested?: {
    fromBlock: number;
    toBlock: number;
  } | null;
  available: CoverageInterval[];
  configuredStartBlock: number;
  processedThrough: number | null;
  finalizedThrough: number | null;
  complete: boolean;
  state:
    | "starting"
    | "backfilling"
    | "catching_up"
    | "live"
    | "degraded"
    | "paused"
    | "failed";
}
Page@smart-byte/leani-sdk
export interface Page<T> {
  data: T[];
  nextCursor: string | null;
  coverage: ProcessorCoverage;
}
BlobsBlock@smart-byte/leani-sdk
export interface BlobsBlock {
  network: string;
  blockNumber: number;
  blockHash: Hex;
  parentHash: Hex;
  timestamp: number;
  size: string;
  blobCount: number;
  blobGasUsed: string;
  excessBlobGas: string;
  /**
   * Protocol blob base fee in wei per blob gas: the EIP-4844 fee for
   * `excessBlobGas` under the fork active at `timestamp`. EIP-7918 does not
   * change it.
   */
  blobBaseFee: string;
  executionBaseFee: string;
  gasUsed: string;
  gasLimit: string;
  executionEthBurnedWei: string;
  /** `blobBaseFee` times `blobGasUsed`. */
  blobEthBurnedWei: string;
  /**
   * EIP-7918 reserve price in wei per blob gas from Fusaka on, `null` before.
   * It only changes how excess blob gas evolves and is not applied to
   * `blobBaseFee`.
   */
  reserveFeeWei: string | null;
  transactionCount: number;
  targetBlobsPerBlock: number;
  maxBlobsPerBlock: number;
  transformVersion: number;
  finality: Finality;
}
BlobTransaction@smart-byte/leani-sdk
export interface BlobTransaction {
  network: string;
  blockNumber: number;
  blockHash: Hex;
  txHash: Hex;
  transactionIndex: number;
  senderAddress: Hex;
  /**
   * The transaction's to address. Every blob transaction has one: a rollup's
   * inbox, or a contract that routes the call, such as Multicall3.
   */
  toAddress: Hex;
  blobVersionedHashes: Hex[];
  blobCount: number;
  totalBurnedWei: string;
  executionBurnedWei: string;
  /** The block's `blobBaseFee` times this transaction's blob gas. */
  blobBurnedWei: string;
}
BlobsSnapshotEntry@smart-byte/leani-sdk
export interface BlobsSnapshotEntry {
  block: BlobsBlock;
  transactions: BlobTransaction[];
}
ChangeHead@smart-byte/leani-sdk
export interface ChangeHead {
  earliestSequence: string | null;
  latestSequence: string | null;
  cursor: string | null;
}
GenericOutputEntity@smart-byte/leani-sdk
export interface GenericOutputEntity<T = unknown> {
  ordinal: string;
  key: Hex;
  schema: string;
  data: T;
  blockNumber: number;
  blockTimestamp: number;
  finality: Finality;
}
OutputBounds@smart-byte/leani-sdk
export interface OutputBounds {
  earliestBlock: number;
  latestBlock: number;
  earliestTimestamp: number;
  latestTimestamp: number;
}
GenericSnapshotPage@smart-byte/leani-sdk
export interface GenericSnapshotPage<T = unknown> {
  data: GenericOutputEntity<T>[];
  nextCursor: string | null;
  snapshotId: string;
  boundaryCursor: string | null;
  rowCount: string;
  valueBytes: string;
  expiresAtUnixMs: string;
  retainedBounds: OutputBounds | null;
  coverage: ProcessorCoverage;
  recovery: {
    follow: string | null;
    outsideRetention: "create_processor_instance_or_source_scan";
  };
}
FollowSnapshotPage@smart-byte/leani-sdk
export interface FollowSnapshotPage<T = unknown> extends GenericSnapshotPage<T> {
  boundaryCursor: string;
  recovery: GenericSnapshotPage<T>["recovery"] & { follow: string };
}
OutputQueryOptions@smart-byte/leani-sdk
export interface OutputQueryOptions {
  fromBlock?: number;
  toBlock?: number;
  fromTimestamp?: number;
  toTimestamp?: number;
  limit?: number;
  cursor?: string;
  signal?: AbortSignal;
}
ConsumerRole@smart-byte/leani-sdk
export type ConsumerRole = "required" | "best_effort";
ConsumerState@smart-byte/leani-sdk
export type ConsumerState = "active" | "reset_required" | "revoked";
ConsumerStart@smart-byte/leani-sdk
export type ConsumerStart =
  | { position: "earliest_retained" }
  | { position: "current_head" }
  | { position: "cursor"; cursor: string };
CreateConsumerOptions@smart-byte/leani-sdk
export interface CreateConsumerOptions {
  id: string;
  role: ConsumerRole;
  start: ConsumerStart;
  leaseTtlSeconds: number;
  credential: string;
  signal?: AbortSignal;
}
DurableConsumer@smart-byte/leani-sdk
export interface DurableConsumer {
  id: string;
  processorInstance: string;
  /** The delivery stream this consumer reads. */
  streamId: string;
  role: ConsumerRole;
  state: ConsumerState;
  acknowledgedSequence: string;
  deliveredSequence: string;
  acknowledgedCursor: string;
  deliveredCursor: string;
  /** Stream sessions that have taken the lease; `"0"` before the first. */
  leaseGeneration: string;
  leaseTtlMs: string;
  leaseExpiresAtUnixMs: string;
  leaseActive: boolean;
  lagChanges: string;
  lagBlocks: string;
  lagBytes: string;
  lagAgeMs: string;
  createdAtUnixMs: string;
  updatedAtUnixMs: string;
}
BlobSchedule@smart-byte/leani-sdk
export interface BlobSchedule {
  name: string;
  /**
   * Block-number label for `atBlock` lookups. For Dencun it is 19426589, the
   * first block the blobs processor covers.
   */
  activationBlock: number;
  /** The fork's parameters apply to blocks from this timestamp on. */
  activationTimestamp: number;
  forkId: Hex;
  targetBlobsPerBlock: number;
  maxBlobsPerBlock: number;
  baseFeeUpdateFraction: string;
  eip7918: boolean;
  source: "chain_spec" | "eth_config" | "configured";
}
Erc20Balance@smart-byte/leani-sdk
export interface Erc20Balance {
  token: Hex;
  address: Hex;
  balance: string;
  asOfBlock: number;
  blockHash: Hex;
  finality: Finality;
  coverageFrom: number;
  complete: boolean;
  /**
   * Block whose transfer proved the ledger incomplete for this token and
   * holder. From that block the pair is no longer derived and `balance` keeps
   * its last derived value; `null` while the pair is derived.
   */
  incompleteFrom: number | null;
  method: "erc20_transfer_ledger";
}
EvmEvent@smart-byte/leani-sdk
export interface EvmEvent {
  schemaVersion: number;
  contract: Hex;
  event: string;
  signature: string;
  blockNumber: number;
  blockHash: Hex;
  blockTimestamp: number;
  bucketStartTimestamp?: number;
  transactionHash: Hex;
  transactionIndex: number;
  logIndex: number;
  finality: Finality;
  values: Record<string, string>;
}
TransactionStats@smart-byte/leani-sdk
export interface TransactionStats {
  from: Hex;
  to: Hex;
  /** Submitted transactions from `from` to `to`, reverted ones included. */
  count: number;
  /** Submitted value in wei, including the value of reverted transactions. */
  totalValueWei: string;
  asOfBlock: number;
  blockHash: Hex;
  finality: Finality;
  coverageFrom: number;
  complete: boolean;
}
UniswapPoolPrice@smart-byte/leani-sdk
export interface UniswapPoolPrice {
  pool: Hex;
  kind: "v2" | "v3";
  reserve0: string | null;
  reserve1: string | null;
  /** Signed token0 pool delta for a V3 swap, in raw token units. */
  amount0: string | null;
  /** Signed token1 pool delta for a V3 swap, in raw token units. */
  amount1: string | null;
  sqrtPriceX96: string | null;
  blockNumber: number;
  blockHash: Hex;
  logIndex: number;
  finality: Finality;
}
LatestUniswapObservation@smart-byte/leani-sdk
export interface LatestUniswapObservation {
  data: UniswapPoolPrice;
  timestamp: number;
}
ConfiguredUniswapPool@smart-byte/leani-sdk
export interface ConfiguredUniswapPool {
  address: Hex;
  kind: "v2" | "v3";
}
ConfiguredUniswapPools@smart-byte/leani-sdk
export interface ConfiguredUniswapPools {
  data: ConfiguredUniswapPool[];
}
BlockSummary@smart-byte/leani-sdk
export interface BlockSummary {
  chainId: number;
  blockNumber: number;
  blockHash: Hex;
  parentHash: Hex;
  timestamp: number;
  gasLimit: number | null;
  gasUsed: number | null;
  baseFeePerGas: string | null;
  blobGasUsed: number | null;
  excessBlobGas: number | null;
  transactionCount: number | null;
  sizeBytes: number | null;
  finality: Finality;
}
LatestBlockSummary@smart-byte/leani-sdk
export interface LatestBlockSummary {
  data: BlockSummary;
}
ChangeMetadata@smart-byte/leani-sdk
export interface ChangeMetadata {
  apiVersion: "1";
  sequence: string;
  cursor: string;
  originKind:
    | "live"
    | "live_recovery"
    | "historical_backfill"
    | "recompute";
  originId: string;
  publicationRevision: string;
  chainId: number;
  block: {
    number: number;
    hash: Hex;
    parentHash: Hex;
    timestamp: number;
  } | null;
  finality: Finality;
  kind: string;
  schema: string;
  key: string | null;
  /** Present only on `reset_required` events, as the current coverage hint. */
  coverage?: ProcessorCoverage;
  /** RFC 3339 UTC emission time with millisecond precision. */
  emittedAt: string;
}
LiveGapChangeData@smart-byte/leani-sdk
export interface LiveGapChangeData {
  fromBlock: number;
  toBlock: number;
  /**
   * Leani did not fill the range: the processor's history is on demand, and a
   * `live_gap_fill` limit, if it has one, did not cover or complete it.
   */
  reason: "not_filled";
}
ChangeEnvelope@smart-byte/leani-sdk
export type ChangeEnvelope<T = unknown> = ChangeMetadata & (
  | { operation: "apply" | "undo"; data: T | null }
  | { operation: "attested"; data: { throughBlock: number } }
  | { operation: "finalized"; data: { throughBlock: number } }
  | { operation: "finalized"; data: LiveGapChangeData }
  | { operation: "reset_required"; data: {
      earliestAvailableSequence: string;
      latestAvailableSequence: string;
      action: "query_snapshot_then_resume";
    } }
);
isLiveGapChange@smart-byte/leani-sdk
export function isLiveGapChange<T>(
  change: ChangeEnvelope<T>,
): change is Extract<ChangeEnvelope<T>, { data: LiveGapChangeData }>;
LiveLaneReset@smart-byte/leani-sdk
export interface LiveLaneReset {
  processor: string;
  state: "paused";
  reason: "operator_reset_pending_replay";
  firstUnappliedBlock: number;
  firstUnappliedHash: Hex;
  requiredDeliveryBytes: string;
}
StreamHello@smart-byte/leani-sdk
export interface StreamHello {
  apiVersion: "1";
  chainId: number;
  processor: ProcessorSummary;
  coverage: ProcessorCoverage;
}
ListBlocksOptions@smart-byte/leani-sdk
export interface ListBlocksOptions {
  fromBlock: number;
  toBlock: number;
  limit?: number;
  cursor?: string;
  allowPartial?: boolean;
  signal?: AbortSignal;
}
ListTransactionsOptions@smart-byte/leani-sdk
export interface ListTransactionsOptions {
  blockNumber: number;
  limit?: number;
  cursor?: string;
  signal?: AbortSignal;
}
ChangesOptions@smart-byte/leani-sdk
export interface ChangesOptions {
  after?: string;
  limit?: number;
  signal?: AbortSignal;
}
SubscribeOptions@smart-byte/leani-sdk
export interface SubscribeOptions {
  after?: string;
  signal?: AbortSignal;
  /** Receives the connection handshake frame; called once per (re)connect. */
  onHello?: (hello: StreamHello) => void;
  /**
   * Reconnect when the stream sends nothing, not even the node's 15-second
   * keep-alive comments, for this long while the loop waits for a change.
   * Defaults to 60,000 ms.
   */
  idleTimeoutMs?: number;
}
ProcessorSubscribeOptions@smart-byte/leani-sdk
export interface ProcessorSubscribeOptions extends SubscribeOptions {
  processor?: string;
}
LeaniClient@smart-byte/leani-sdk
export interface LeaniClient {
  readonly baseUrl: URL;
  request<T>(
    path: string,
    params?: Record<string, QueryValue>,
    options?: { signal?: AbortSignal },
  ): Promise<T>;
  health: {
    live(options?: { signal?: AbortSignal }): Promise<Health>;
    ready(options?: { signal?: AbortSignal }): Promise<Health>;
  };
  status(options?: { signal?: AbortSignal }): Promise<NodeStatus>;
  capabilities(options?: { signal?: AbortSignal }): Promise<Capabilities>;
  processors: {
    list(options?: { signal?: AbortSignal }): Promise<ProcessorSummary[]>;
    status(
      id: string,
      options?: { signal?: AbortSignal },
    ): Promise<ProcessorCoverage>;
    changes<T = unknown>(
      id: string,
      options?: ChangesOptions,
    ): Promise<Page<ChangeEnvelope<T>>>;
    changeHead(
      id: string,
      options?: { signal?: AbortSignal },
    ): Promise<ChangeHead>;
    resetLiveLane(
      id: string,
      options?: { signal?: AbortSignal },
    ): Promise<LiveLaneReset>;
    listCollections(
      id: string,
      options?: { signal?: AbortSignal },
    ): Promise<{
      processor: ProcessorSummary;
      outputMode: "none" | "latest" | "window" | "full";
      retained: boolean;
      data: string[];
    }>;
    queryEntities<T = unknown>(
      id: string,
      collection: string,
      options?: OutputQueryOptions,
    ): Promise<GenericSnapshotPage<T>>;
    /** First snapshot page plus an atomic stream boundary. Read all nextCursor pages and releaseSnapshot before following. */
    queryAndFollow<T = unknown>(
      id: string,
      collection: string,
      options?: Omit<OutputQueryOptions, "cursor">,
    ): Promise<FollowSnapshotPage<T>>;
    getEntity<T = unknown>(
      id: string,
      collection: string,
      key: Hex,
      options?: { signal?: AbortSignal },
    ): Promise<GenericOutputEntity<T>>;
    releaseSnapshot(
      id: string,
      snapshotId: string,
      options?: { signal?: AbortSignal },
    ): Promise<void>;
    consumers: {
      list(
        id: string,
        options?: { signal?: AbortSignal },
      ): Promise<DurableConsumer[]>;
      create(
        id: string,
        options: CreateConsumerOptions,
      ): Promise<DurableConsumer>;
      inspect(
        id: string,
        consumer: string,
        options?: { signal?: AbortSignal },
      ): Promise<DurableConsumer>;
      revoke(
        id: string,
        consumer: string,
        options?: { signal?: AbortSignal },
      ): Promise<DurableConsumer>;
      renew(
        id: string,
        consumer: string,
        credential: string,
        options?: { signal?: AbortSignal },
      ): Promise<DurableConsumer>;
      changes<T = unknown>(
        id: string,
        consumer: string,
        credential: string,
        options?: { limit?: number; signal?: AbortSignal },
      ): Promise<Page<ChangeEnvelope<T>>>;
      acknowledge(
        id: string,
        consumer: string,
        credential: string,
        cursor: string,
        options?: { signal?: AbortSignal },
      ): Promise<DurableConsumer>;
    };
    subscribe<T = unknown>(
      id: string,
      options?: SubscribeOptions,
    ): AsyncGenerator<ChangeEnvelope<T>>;
  };
  blobs: {
    getBlock(
      number: number,
      options?: { signal?: AbortSignal },
    ): Promise<BlobsBlock>;
    listBlocks(options: ListBlocksOptions): Promise<Page<BlobsBlock>>;
    listSnapshot(
      options: ListBlocksOptions,
    ): Promise<Page<BlobsSnapshotEntry>>;
    getTransaction(
      hash: Hex,
      options?: { signal?: AbortSignal },
    ): Promise<BlobTransaction>;
    listTransactions(
      options: ListTransactionsOptions,
    ): Promise<Page<BlobTransaction>>;
    getSchedule(options?: {
      atBlock?: number;
      signal?: AbortSignal;
    }): Promise<BlobSchedule>;
    subscribe(
      options?: ProcessorSubscribeOptions,
    ): AsyncGenerator<ChangeEnvelope<BlobsSnapshotEntry>>;
  };
  erc20: {
    getBalance(
      token: Hex,
      address: Hex,
      options?: { signal?: AbortSignal },
    ): Promise<Erc20Balance>;
    subscribe(
      options?: ProcessorSubscribeOptions,
    ): AsyncGenerator<ChangeEnvelope<Erc20Balance>>;
  };
  uniswap: {
    getPool(
      address: Hex,
      options?: { signal?: AbortSignal },
    ): Promise<UniswapPoolPrice>;
    getLatestObservation(
      address: Hex,
      options?: { processor?: string; signal?: AbortSignal },
    ): Promise<LatestUniswapObservation>;
    listConfiguredPools(options?: {
      processor?: string;
      signal?: AbortSignal;
    }): Promise<ConfiguredUniswapPools>;
    subscribe(
      options?: ProcessorSubscribeOptions,
    ): AsyncGenerator<ChangeEnvelope<UniswapPoolPrice>>;
  };
  blocks: {
    getLatest(options?: {
      processor?: string;
      signal?: AbortSignal;
    }): Promise<LatestBlockSummary>;
    getByNumber(
      number: number,
      options?: { processor?: string; signal?: AbortSignal },
    ): Promise<LatestBlockSummary>;
    subscribe(
      options?: ProcessorSubscribeOptions,
    ): AsyncGenerator<ChangeEnvelope<BlockSummary>>;
  };
}
createLeaniClient@smart-byte/leani-sdk
export function createLeaniClient(
  options: LeaniClientOptions,
): LeaniClient;
QueryValue@smart-byte/leani-sdk
export type QueryValue = string | number | boolean | undefined;
parseSse@smart-byte/leani-sdk
export async function* parseSse(
  body: ReadableStream<Uint8Array>,
  signal?: AbortSignal,
): AsyncGenerator<SseMessage>;
compareSequences@smart-byte/leani-sdk
export function compareSequences(left: string, right: string): -1 | 0 | 1;
isResetRequired@smart-byte/leani-sdk
export function isResetRequired(
  change: ChangeEnvelope,
): change is ChangeEnvelope & { operation: "reset_required" };
EntityChangeTarget@smart-byte/leani-sdk
export interface EntityChangeTarget<T> {
  put(key: string, value: T): void | Promise<void>;
  delete(key: string): void | Promise<void>;
}
applyEntityChange@smart-byte/leani-sdk
export async function applyEntityChange<T>(
  target: EntityChangeTarget<T>,
  change: ChangeEnvelope<T>,
): Promise<void>;
commitThenAcknowledge@smart-byte/leani-sdk
export async function commitThenAcknowledge<T>(
  destinationCommit: () => Promise<T>,
  acknowledge: (committed: T) => Promise<unknown>,
): Promise<T>;
CursorStore@smart-byte/leani-sdk
export interface CursorStore {
  get(): string | undefined;
  set(cursor: string): void;
  clear(): void;
}
createInMemoryCursorStore@smart-byte/leani-sdk
export function createInMemoryCursorStore(initial?: string): CursorStore;
BackfillExecutionMode@smart-byte/leani-sdk/backfill
export type BackfillExecutionMode = "fill_missing" | "recompute";
BackfillState@smart-byte/leani-sdk/backfill
export type BackfillState =
  | "waiting_for_consumer"
  | "queued"
  | "running"
  | "backpressured"
  | "storage_backpressured"
  | "draining"
  | "complete_reclaimable"
  | "completed"
  | "failed"
  | "cancelled";
BackfillRange@smart-byte/leani-sdk/backfill
export interface BackfillRange {
  fromBlock: number;
  toBlock: number;
}
RequestedBackfillRange@smart-byte/leani-sdk/backfill
export interface RequestedBackfillRange {
  fromBlock: number;
  toBlock: number | "finalized";
}
BackfillStatus@smart-byte/leani-sdk/backfill
export interface BackfillStatus {
  id: string;
  owner: "subscription";
  processor: string;
  /**
   * Whether the node configures the processor instance `processor` now.
   * Without it, the stream and acknowledgement routes refuse the
   * subscription. That can be temporary; if the instance will not return,
   * cancel the subscription and delete it with `discardUnacknowledged: true`,
   * which discards its unacknowledged records.
   */
  processorConfigured: boolean;
  /** The required consumer; tell your subscriptions apart by it, not by `id`. */
  consumer: string | null;
  deliveryStreamId?: string;
  publicationRevision?: string;
  fromBlock: number;
  toBlock: number;
  ranges: BackfillRange[];
  requestedBlocks: number;
  processedBlocks: number;
  remainingBlocks: number;
  capturedFinalizedTarget?: number;
  mode: BackfillExecutionMode;
  batching?: EffectiveBackfillBatching;
  state: BackfillState;
  attempts: number;
  updatedAtUnixMs: number;
  report: unknown | null;
  lastError: string | null;
}
HistoricalWorkDeletion@smart-byte/leani-sdk/backfill
export interface HistoricalWorkDeletion {
  id: string;
  owner: "subscription";
  removedJobs: number;
  removedSubscriptionRanges: number;
  removedConsumers: number;
  removedDeliveryRecords: number;
  removedDeliveryStreams: number;
  removedCoverageIntervals: number;
  removedCoverageSegments: number;
  removedExactCoverage: number;
  removedAppliedBlocks: number;
  removedFinalizedUndo: number;
  retainedProcessorOutput: boolean;
  retainedLiveStream: boolean;
}
BackfillBatchingRequest@smart-byte/leani-sdk/backfill
export type BackfillBatchingRequest = Partial<
  Omit<
    EffectiveBackfillBatching,
    "maximumBufferedBatches" | "maximumBufferedBytes"
  >
>;
BackfillBatchingProfile@smart-byte/leani-sdk/backfill
export type BackfillBatchingProfile = "latency" | "balanced" | "throughput";
backfillBatchingProfile@smart-byte/leani-sdk/backfill
export function backfillBatchingProfile(
  profile: BackfillBatchingProfile,
): Required<BackfillBatchingRequest>;
EffectiveBackfillBatching@smart-byte/leani-sdk/backfill
export interface EffectiveBackfillBatching {
  targetEncodedBytes: number;
  maximumEncodedBytes: number;
  maximumEvents: number;
  maximumProcessedBlocks: number;
  maximumDelayMs: number;
  maximumBufferedBatches: number;
  maximumBufferedBytes: number;
  compression: "none" | "gzip";
}
CreateBackfillSubscription@smart-byte/leani-sdk/backfill
export type CreateBackfillSubscription = CreateBackfillSubscriptionBase &
  (
    | {
        fromBlock: number;
        toBlock: number | "finalized";
        ranges?: never;
      }
    | {
        ranges: RequestedBackfillRange[];
        fromBlock?: never;
        toBlock?: never;
      }
  );
liveGapBackfill@smart-byte/leani-sdk/backfill
export function liveGapBackfill(
  range: BackfillRange,
  request: Omit<CreateBackfillSubscriptionBase, "mode" | "idempotencyKey"> & {
    consumer: NonNullable<CreateBackfillSubscriptionBase["consumer"]>;
  },
): CreateBackfillSubscription;
BackfillStreamHello@smart-byte/leani-sdk/backfill
export interface BackfillStreamHello {
  type: "hello";
  apiVersion: "1";
  chainId: number;
  processor: ProcessorSummary;
  subscriptionId: string;
  streamId: string;
  streamKind: "backfill";
  publicationRevision: string;
  ranges: BackfillRange[];
  acknowledgedCursor: string;
  storeEpoch: string;
  heartbeatIntervalMs: string;
  sessionExpiresAtUnixMs: string;
  leaseTtlMs: string;
}
BackfillStreamBatch@smart-byte/leani-sdk/backfill
export interface BackfillStreamBatch<T = unknown> {
  type: "batch";
  streamId: string;
  originKind: "historical_backfill" | "recompute";
  originId: string;
  publicationRevision: string;
  fromBlock: number;
  throughBlock: number;
  processedBlockCount: string;
  domainChangeCount: string;
  progressUnitCount: string;
  rawPayloadBytes: string;
  uncompressedEncodedBytes: string;
  transmittedBytes: string;
  buildDelayMs: string;
  firstCursor: string | null;
  lastCursor: string | null;
  acknowledgeableCursor: string;
  changes: ChangeEnvelope<T>[];
}
BackfillStreamCompletion@smart-byte/leani-sdk/backfill
export interface BackfillStreamCompletion {
  type: "backfill_complete";
  subscriptionId: string;
  streamId: string;
  ranges: BackfillRange[];
  throughBlock: number;
  cursor: string;
  mode: BackfillExecutionMode;
  disposition:
    | "published_all"
    | "published_missing_only"
    | "already_covered_noop";
  requestedBlockCount: string;
  coveredBeforeRequestBlockCount: string;
  coveredBeforeRequestRanges: BackfillRange[];
  newlyProcessedBlockCount: string;
  republishedBlockCount: string;
  domainChangeCount: string;
  preexistingCoverageSkipped: boolean;
  repairHint?: "recompute";
}
BackfillStreamHeartbeat@smart-byte/leani-sdk/backfill
export interface BackfillStreamHeartbeat {
  type: "heartbeat";
  emittedAt: string;
}
BackfillStreamReset@smart-byte/leani-sdk/backfill
export interface BackfillStreamReset {
  type: "reset_required";
  code: "reset_required";
  message: string;
  earliestAvailableSequence: string | null;
  latestAvailableSequence: string | null;
}
BackfillStreamFailure@smart-byte/leani-sdk/backfill
export interface BackfillStreamFailure {
  type: "error";
  code: string;
  message: string;
  earliestAvailableSequence: string | null;
  latestAvailableSequence: string | null;
}
BackfillStreamRecord@smart-byte/leani-sdk/backfill
export type BackfillStreamRecord<T = unknown> =
  | BackfillStreamBatch<T>
  | BackfillStreamCompletion
  | BackfillStreamHeartbeat;
LiveStreamHello@smart-byte/leani-sdk/backfill
export interface LiveStreamHello {
  type: "hello";
  apiVersion: "1";
  chainId: number;
  processor: ProcessorSummary;
  streamId: string;
  streamKind: "live";
  acknowledgedCursor: string;
  storeEpoch: string;
  heartbeatIntervalMs: string;
  sessionExpiresAtUnixMs: string;
  leaseTtlMs: string;
  /** What the processor covers as the session starts: diff it against the
   * destination to find blocks to request as history. */
  coverage: ProcessorCoverage;
}
LiveStreamBatch@smart-byte/leani-sdk/backfill
export interface LiveStreamBatch<T = unknown> {
  type: "batch";
  streamId: string;
  originKind: "live" | "live_recovery";
  originId: string;
  publicationRevision: "0";
  fromBlock: number;
  throughBlock: number;
  processedBlockCount: "1";
  domainChangeCount: string;
  progressUnitCount: "1";
  rawPayloadBytes: string;
  uncompressedEncodedBytes: string;
  transmittedBytes: string;
  buildDelayMs: string;
  firstCursor: string;
  lastCursor: string;
  acknowledgeableCursor: string;
  changes: ChangeEnvelope<T>[];
}
LiveStreamRecord@smart-byte/leani-sdk/backfill
export type LiveStreamRecord<T = unknown> =
  | LiveStreamBatch<T>
  | BackfillStreamHeartbeat;
DeliverySession@smart-byte/leani-sdk/backfill
export interface DeliverySession<THello, TRecord>
  extends AsyncIterable<TRecord> {
  readonly hello: THello;
  acknowledge(
    cursor: string,
    options?: { signal?: AbortSignal },
  ): Promise<DurableConsumer>;
  close(): Promise<void>;
}
BackfillDeliverySession@smart-byte/leani-sdk/backfill
export interface BackfillDeliverySession<T = unknown>
  extends DeliverySession<BackfillStreamHello, BackfillStreamRecord<T>> {
  batches(): AsyncIterable<BackfillStreamBatch<T>>;
  /**
   * Every acknowledgement boundary with the changes it covers: each batch,
   * including one without changes, then the completion. Commit `events`,
   * then acknowledge `ackCursor`.
   */
  deliveryBatches(): AsyncIterable<HistoryDeliveryBatch<T>>;
  /**
   * The batches' changes, flattened. They carry no acknowledgement
   * boundary; acknowledge from `deliveryBatches()` or `batches()`.
   */
  events(): AsyncIterable<ChangeEnvelope<T>>;
}
LiveDeliverySession@smart-byte/leani-sdk/backfill
export type LiveDeliverySession<T = unknown> = DeliverySession<
  LiveStreamHello,
  LiveStreamRecord<T>
>;
MultiLaneSubscriptionRequest@smart-byte/leani-sdk/backfill
export interface MultiLaneSubscriptionRequest {
  processor: string;
  consumer: string;
  credential?: string;
  lanes: {
    live?: boolean;
    history?: Array<{ subscriptionId: string }>;
  };
  view?: "live_priority" | "lane_specific";
  batching?: BackfillBatchingRequest;
  signal?: AbortSignal;
}
UnifiedDeliveryBatch@smart-byte/leani-sdk/backfill
export type UnifiedDeliveryBatch<T = unknown> =
  | {
      laneKind: "live";
      laneId: "live";
      streamId: string;
      ackCursor: string;
      events: ChangeEnvelope<T>[];
      completion?: never;
      record: LiveStreamBatch<T>;
    }
  | {
      laneKind: "history";
      laneId: string;
      streamId: string;
      ackCursor: string;
      events: ChangeEnvelope<T>[];
      completion?: BackfillStreamCompletion;
      record: BackfillStreamBatch<T> | BackfillStreamCompletion;
    };
HistoryDeliveryBatch@smart-byte/leani-sdk/backfill
export type HistoryDeliveryBatch<T = unknown> = Extract<
  UnifiedDeliveryBatch<T>,
  { laneKind: "history" }
>;
MultiLaneDelivery@smart-byte/leani-sdk/backfill
export interface MultiLaneDelivery<T = unknown> {
  batches(): AsyncIterable<UnifiedDeliveryBatch<T>>;
  liveBatches(): AsyncIterable<UnifiedDeliveryBatch<T>>;
  historyBatches(
    subscriptionId: string,
  ): AsyncIterable<UnifiedDeliveryBatch<T>>;
  acknowledge(
    batch: UnifiedDeliveryBatch<T>,
    options?: { signal?: AbortSignal },
  ): Promise<DurableConsumer>;
  close(): Promise<void>;
}
BackfillSubscriptionClientOptions@smart-byte/leani-sdk/backfill
export interface BackfillSubscriptionClientOptions {
  baseUrl: string | URL;
  token?: string;
  fetch?: FetchLike;
  /** Deadline for JSON requests; established delivery streams stay open. */
  timeoutMs?: number;
}
BackfillSubscriptionClient@smart-byte/leani-sdk/backfill
export interface BackfillSubscriptionClient {
  readonly baseUrl: URL;
  create(request: CreateBackfillSubscription): Promise<BackfillStatus>;
  list(options?: { signal?: AbortSignal }): Promise<BackfillStatus[]>;
  inspect(
    subscription: string,
    options?: { signal?: AbortSignal },
  ): Promise<BackfillStatus>;
  cancel(
    subscription: string,
    options?: { signal?: AbortSignal },
  ): Promise<BackfillStatus>;
  /** Re-queue a failed subscription to resume from its committed progress. */
  retry(
    subscription: string,
    options?: { signal?: AbortSignal },
  ): Promise<BackfillStatus>;
  /**
   * Delete a terminal subscription. A failed or cancelled one is refused
   * while its required consumer has unacknowledged records, unless
   * `discardUnacknowledged` is set.
   */
  delete(
    subscription: string,
    options?: { signal?: AbortSignal; discardUnacknowledged?: boolean },
  ): Promise<HistoricalWorkDeletion>;
  changes<T = unknown>(
    subscription: string,
    consumer: string,
    options?: {
      credential?: string;
      limit?: number;
      signal?: AbortSignal;
    },
  ): Promise<{
    data: ChangeEnvelope<T>[];
    nextCursor: string | null;
    coverage: unknown;
  }>;
  stream<T = unknown>(
    subscription: string,
    consumer: string,
    options?: {
      credential?: string;
      batching?: BackfillBatchingRequest;
      signal?: AbortSignal;
    },
  ): Promise<BackfillDeliverySession<T>>;
  streamLive<T = unknown>(
    processor: string,
    consumer: string,
    options?: { credential?: string; signal?: AbortSignal },
  ): Promise<LiveDeliverySession<T>>;
  subscribe<T = unknown>(
    request: MultiLaneSubscriptionRequest,
  ): Promise<MultiLaneDelivery<T>>;
}
createBackfillSubscriptionClient@smart-byte/leani-sdk/backfill
export function createBackfillSubscriptionClient(
  options: BackfillSubscriptionClientOptions,
): BackfillSubscriptionClient;
BackfillFailurePolicy@smart-byte/leani-sdk/backfill
export type BackfillFailurePolicy = "retry" | "discard" | "throw";
RunBackfillOptions@smart-byte/leani-sdk/backfill
export interface RunBackfillOptions<T = unknown> {
  /** Apply one history batch. It is acknowledged after this resolves. */
  onBatch(batch: HistoryDeliveryBatch<T>): void | Promise<void>;
  /** What a failed subscription does: retry it (default), delete it, or throw. */
  onFailure?: BackfillFailurePolicy;
  /** Retries before "retry" gives up and throws. Default 3. */
  maxRetries?: number;
  /** The consumer's credential; `request.consumer.credential` by default. */
  credential?: string;
  batching?: BackfillBatchingRequest;
  /**
   * Stops the run, as `request.signal` does too. The run rejects with the
   * abort reason and keeps the subscription.
   */
  signal?: AbortSignal;
}
RunBackfillResult@smart-byte/leani-sdk/backfill
export interface RunBackfillResult {
  outcome: "completed" | "cancelled" | "failed";
  /** The subscription as it ended, before its deletion. */
  subscription: BackfillStatus;
  /** The completion record this run received, if it streamed one. */
  completion?: BackfillStreamCompletion;
  deletion: HistoricalWorkDeletion;
}
runBackfill@smart-byte/leani-sdk/backfill
export async function runBackfill<T = unknown>(
  client: BackfillSubscriptionClient,
  request: CreateBackfillSubscription,
  options: RunBackfillOptions<T>,
): Promise<RunBackfillResult>;
parseNdjson@smart-byte/leani-sdk/backfill
export async function* parseNdjson(
  body: ReadableStream<Uint8Array>,
  signal?: AbortSignal,
): AsyncGenerator<unknown>;
LeaniErrorBody@smart-byte/leani-sdk
export interface LeaniErrorBody {
  error: {
    code: string;
    message: string;
    retryable: boolean;
    details?: Record<string, unknown> | null;
    requestId: string;
  };
}