/** * Personal Server data-read request builder and the 402 -> escrow-pay -> retry loop. * * @remarks * The read targets the Personal Server data path (`/v1/data/{scope}`), * authenticates with a Web3Signed header (built on {@link buildWeb3SignedHeader}), * and — on `402 Payment Required` — signs the challenged escrow operation and * retries once. * * The 402 body is parsed into a validated grant or receipt-bound data-access * operation, which drives the escrow settlement. * * @category Direct * @module direct/personal-server-read */ import type { Web3SignedSignFn } from "../auth/web3-signed-builder.js"; import { type EscrowPaymentHeaderConfig } from "./escrow-payment.js"; import type { DirectPaymentResponseMetadata, PersonalServerPaymentOperation } from "./types.js"; /** Minimal `Response`-like shape so the read loop is testable without a DOM. */ export interface FetchResponseLike { ok: boolean; status: number; statusText: string; headers: { get(name: string): string | null; }; json(): Promise; text(): Promise; } /** Minimal `fetch` signature accepted by {@link readPersonalServerData}. */ export type PersonalServerFetch = (input: string, init: { method: string; headers: Record; }) => Promise; /** A built, ready-to-send Personal Server data read request. */ export interface PersonalServerDataReadRequest { /** Absolute URL of the read endpoint. */ url: string; /** HTTP method (always `"GET"`). */ method: "GET"; /** Request path used in the Web3Signed `uri` claim (e.g. `/v1/data/{scope}`). */ path: string; /** Headers including the Web3Signed `Authorization` value. */ headers: Record; } /** * Transport-level retry knobs for {@link readPersonalServerData}. * * @remarks * Applies only when the underlying `fetch` **throws** (connection reset, DNS, * socket died mid-handshake — the browser-PS relay drop window). A received * HTTP response is never retried here: 402 has its own payment loop and other * statuses are surfaced to the caller unchanged. */ export interface PersonalServerTransportRetryOptions { /** 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; /** Cap on the between-retry delay (ms, default 5_000). */ maxDelayMs?: number; } /** Outcome of {@link readPersonalServerData}. */ export interface PersonalServerReadResult { /** The decoded JSON payload returned by the Personal Server. */ data: unknown; /** * Shape-validated but unauthenticated payment metadata echoed by the * Personal Server. Never treat this field as accounting proof. */ payment?: DirectPaymentResponseMetadata; } /** Compute the data path for a scope (`/v1/data/{scope}`). */ export declare function dataPathForScope(scope: string): string; /** * Build a Web3Signed-authenticated Personal Server data read request. * * @param params - Personal Server URL, scope, grant id, and an EIP-191 signer. * @returns The request URL, method, path, and headers (including `Authorization`). */ export declare function buildPersonalServerDataReadRequest(params: { /** Base URL of the user's Personal Server. */ personalServerUrl: string; /** Scope to read (e.g. `"icloud_notes.notes"`). */ scope: string; /** Grant id authorizing the read. */ grantId: string; /** EIP-191 signer for the Web3Signed header (the app key). */ signMessage: Web3SignedSignFn; }): Promise; /** * Parse a `402 Payment Required` body into a validated payment operation. * * @remarks * Accepts a few field spellings and falls back to the read's own grantId and the * native asset when a field is absent from a legacy grant challenge. * * Receipt-bound `data_access` uses a fail-closed canonical path: one compatible * `accepts` entry must contain the scheme, network, message, and complete * receipt. Its positive uint256 `paymentNonce` is mandatory because the * Personal Server encodes challenge freshness in that nonce and checks it on * retry. This parser shape-validates the receipt and binds `opId` to `recordId`; * it does not recover or verify the server signature. * * @param res - The 402 response. * @param grantId - The grant id of the read (default legacy grant `opId`). * @returns The parsed payment requirement. */ export declare function parsePersonalServerPaymentRequired(res: FetchResponseLike, grantId: string): Promise; /** * Read approved data from a Personal Server, settling a 402 via escrow. * * @remarks * Sends a Web3Signed-authenticated `GET /v1/data/{scope}`. On `402`, parses what * is owed, authorizes the challenged escrow operation, and retries once. If * escrow is not configured, throws {@link PaymentRequiredError} carrying the * parsed requirement so callers can debug amount/asset. * * Transport failures (fetch throwing — the browser-PS relay reconnect window) * are retried with backoff per `transportRetry` (default 3 attempts). The paid * retry reuses the already-signed `X-PAYMENT` header, so transport retries can * never double-pay. * * @param params - Connection details, app signer, optional escrow config and fetch. * @returns `{ data, payment? }`. */ export declare function readPersonalServerData(params: { personalServerUrl: string; scope: string; grantId: string; payerAddress: `0x${string}`; signMessage: Web3SignedSignFn; escrow?: EscrowPaymentHeaderConfig; fetchFn?: PersonalServerFetch; transportRetry?: PersonalServerTransportRetryOptions; }): Promise;