/** * Transport shared by every builder call that authenticates with the * Personal Server Write API: the data writes of * {@link ../protocol/personal-server-write} and the derivative question * routes of {@link ../protocol/derivative-questions}. * * @remarks * Both sign a single-use Web3Signed proof per request, so both need the same * two things: a `fetch` wrapper that re-signs on every transport attempt, and * one process-wide record of the `iat` seconds already issued, so two proofs * for the same request identity can never come out byte-identical (the server * would reject the second as a replay). The record must be shared, not * per-module: a builder that polls one question every few milliseconds signs * the same `{ aud, method, uri, bodyHash, grantId }` many times a second. * * @internal */ /** * Transport-level retry knobs shared by every Write API call. * * @remarks * Applies only when `fetch` **throws** (connection reset, DNS, a relay drop). * Every attempt signs a fresh proof, because the Personal Server consumes a * proof the moment it accepts it. A received HTTP response is never retried: * a 4xx/5xx is surfaced as a typed error. * @category Protocol */ export interface WriteTransportRetryOptions { /** Total attempts including the first (default 3). `1` disables retries. */ attempts?: number; /** Delay before the first retry (ms); doubles per retry (default 1_000). */ initialDelayMs?: number; } /** Strip trailing slashes so a base URL concatenates with a path. */ export declare function normalizeBaseUrl(url: string): string; /** The caller's `fetch`, else the global one. */ export declare function resolveFetch(fetchFn: typeof fetch | undefined): typeof fetch; export declare function errorMessage(err: unknown): string; export declare function finiteOr(value: number | undefined, fallback: number): number; export declare function sleep(ms: number): Promise; /** * Reserve the next `iat` for a request identity. The reservation is made * synchronously so concurrent callers never share a value; the returned * promise only waits when the reserved `iat` is further ahead of the clock * than {@link PROOF_IAT_MAX_AHEAD_SECONDS}. */ export declare function nextProofIat(proofKey: string): Promise; /** * A fresh `nonce` claim for one proof. * * @remarks * The Personal Server keys its replay guard on `(builder, nonce)` when a * proof carries a nonce, and on the whole proof when it does not. A nonce is * therefore what makes two identical requests signed inside the same second * distinct instead of the second being refused as a replay, which is the * difference between a poll loop that works and one that dies on its second * pass. Every question call sends one. */ export declare function freshProofNonce(): string; /** The identity a proof is deduplicated by. */ export declare function proofKeyFor(parts: { aud: string; method: string; uri: string; grantId: string; signedBytes?: Uint8Array; }): string; /** * Send a request, re-signing it on every attempt. Only a thrown `fetch` is * retried; the proof builder and any received response are never retried. */ export declare function sendWithFreshProof(label: string, fetchFn: typeof fetch, options: WriteTransportRetryOptions | undefined, proofKey: string, build: (iat: number) => Promise<{ url: string; init: RequestInit; }>): Promise;