{"version":3,"sources":["../../src/protocol/gateway.ts"],"sourcesContent":["import { tryGrantPermissions, type GrantPermission } from \"./scope-actions\";\nimport {\n  DataPointDeletedError,\n  DataPointNotFoundError,\n  DataPointVersionConflictError,\n} from \"../errors\";\nimport {\n  isDataPointTombstone,\n  tombstoneDeletedAt,\n} from \"./data-point-deletion\";\nimport { deriveDataPointId } from \"./lineage\";\nimport {\n  isPlainObject,\n  readJsonObject,\n  readJsonValue,\n} from \"../utils/response-body\";\nimport type { EscrowBalanceResult } from \"./escrow\";\n\nexport type {\n  EscrowBalanceEntry,\n  EscrowBalanceResult,\n  FailedDepositEntry as EscrowDepositFailed,\n  FinalizedDepositEntry as EscrowDepositFinalized,\n  SubmittedDepositEntry as EscrowDepositSubmitted,\n} from \"./escrow\";\n\nexport interface GatewayEnvelope<T> {\n  data: T;\n  proof: GatewayProof;\n  /**\n   * Cursor-based pagination metadata, present on list endpoints (e.g.\n   * `GET /v1/data`). A sibling of `data`, not nested inside it — so callers\n   * that need it must read the full envelope rather than going through\n   * `unwrapEnvelope`, which intentionally returns only `data`.\n   */\n  pagination?: GatewayPagination;\n}\n\nexport interface GatewayPagination {\n  limit: number;\n  hasMore: boolean;\n  /**\n   * Opaque cursor for the NEXT page; pass back as the `cursor` query param.\n   * Null when there are no further pages.\n   */\n  nextCursor: string | null;\n}\n\nexport interface GatewayProof {\n  signature: string;\n  timestamp: string;\n  gatewayAddress: string;\n  requestHash: string;\n  responseHash: string;\n  userSignature: string;\n  status: string;\n  chainBlockHeight: number;\n}\n\nexport interface Builder {\n  id: string;\n  ownerAddress: string;\n  granteeAddress: string;\n  publicKey: string;\n  appUrl: string;\n  addedAt: string;\n}\n\nexport interface Schema {\n  id: string;\n  ownerAddress: string;\n  name: string;\n  definitionUrl: string;\n  scope: string;\n  addedAt: string;\n}\n\n// Row shape returned by `GET /v1/servers?owner=…`. A discovery-only list —\n// the endpoint carries no per-item gateway attestation (use\n// `getServer(serverAddress)` if you need a verifiable single-server proof).\n// `status` is the gateway's chain-sync state ('pending' | 'confirmed' |\n// 'finalized' | 'reorged'); kept as an open string since the gateway may add\n// states without a SDK bump.\nexport interface OwnerServerRecord {\n  id: string;\n  ownerAddress: string;\n  serverAddress: string;\n  publicKey: string;\n  serverUrl: string;\n  status: string;\n  chainBlockHeight: string | null;\n  // ISO timestamp of the gateway-side upsert.\n  addedAt: string;\n  // ISO timestamp when the grantor deregistered this server. Always null for\n  // entries in the `active` list, always non-null for `revoked`.\n  revokedAt: string | null;\n}\n\n// Response from `GET /v1/servers?owner=…`. Split into two arrays; each is\n// ordered newest-first (`addedAt DESC`, `id ASC` tiebreaker) so `active[0]`\n// is unambiguously the newest active server — the sensible default when the\n// caller just needs one URL. The gateway caps the total across both arrays\n// at 200 — per-owner counts are tiny in practice, so no cursor.\nexport interface OwnerServersResult {\n  active: OwnerServerRecord[];\n  revoked: OwnerServerRecord[];\n  count: number;\n}\n\nexport interface ServerInfo {\n  id: string;\n  ownerAddress: string;\n  serverAddress: string;\n  publicKey: string;\n  serverUrl: string;\n  addedAt: string;\n  // ISO timestamp when the grantor deregistered this server, null while\n  // active. The gateway returns this on /v1/servers/:address GETs since\n  // covering revocation in the response keeps the attestation hash\n  // authoritative for both states.\n  revokedAt: string | null;\n}\n\n// Fee annotation surfaced on every GET grant response. Amounts are decimal\n// uint256 strings to match `/v1/escrow/pay`'s wire format. totalDue is a\n// snapshot — the gateway re-resolves fees at pay time, so clients shouldn't\n// cache this across requests.\nexport interface GatewayGrantFee {\n  asset: string;\n  registrationFee: string;\n  dataAccessFee: string;\n  totalDue: string;\n}\n\n// Lifecycle of a grant's on-chain settlement, tracked separately from the\n// fee-payment lifecycle (paymentStatus). Driven by POST /v1/settle:\n//   pending    — nothing on-chain yet\n//   submitting — settle tx broadcast but receipt not yet observed\n//   confirmed  — settle tx mined successfully\n//   finalized  — finalized tip past the settle block, reorg-safe\n//   reorged    — finalized observation reverted; back to 'pending' on next settle\nexport type GatewayGrantStatus =\n  | \"pending\"\n  | \"submitting\"\n  | \"confirmed\"\n  | \"finalized\"\n  | \"reorged\";\n\nexport interface GatewayGrantResponse {\n  id: string;\n  grantorAddress: string;\n  granteeId: string;\n  // The signed scope entries, verbatim (`[operation:]scope`, bare = read).\n  // This is the wire form: it is what the grantor signed and what the\n  // gateway stores. Render `permissions` instead of parsing these.\n  scopes: string[];\n  // Derived by the SDK at read time from `scopes` via grantPermissions():\n  // one `{ scope, actions }` row per scope pattern, canonically ordered.\n  // Never sent to the gateway and never part of the signed payload. Absent\n  // when `scopes` carries an entry this SDK version cannot interpret (an\n  // operation introduced after this release) - fall back to `scopes` and\n  // do not assume such a grant is read-only.\n  permissions?: GrantPermission[];\n  status: GatewayGrantStatus;\n  addedAt: string;\n  // Grantor-signed deadline. null = perpetual grant (signed value was 0).\n  expiresAt: string | null;\n  // Derived at read time from expiresAt vs the gateway's clock — a snapshot,\n  // not a cached truth. Re-check against expiresAt locally if you care.\n  expired: boolean;\n  revokedAt: string | null;\n  revocationSignature: string | null;\n  // 'pending' until the grant registration fee is settled via /v1/escrow/pay.\n  paymentStatus: \"pending\" | \"paid\";\n  paidAt: string | null;\n  paidBy: string | null;\n  // Decimal-string uint256 monotonic nonce; advances on every state change.\n  grantVersion: string;\n  // Settle metadata — populated as the grant progresses through the chain\n  // lifecycle. Null while `status === 'pending'`.\n  settleTxHash: string | null;\n  settleSubmittedAt: string | null;\n  // Revocation metadata — populated independently when the grantor signs\n  // and the gateway pushes a deregister tx.\n  revocationTxHash: string | null;\n  revocationSubmittedAt: string | null;\n  fee: GatewayGrantFee;\n}\n\nexport type GrantListItem = GatewayGrantResponse;\n\n// Mirror of a DataRegistryV2 row as the gateway exposes it. `id` is the\n// deterministic `keccak256(abi.encode(owner, scope))` dataPointId — the same\n// value the contract uses as its primary key. `expectedVersion` is the latest\n// version the gateway has accepted; the on-chain row may be one version behind\n// while a settle is still pending. The gateway response intentionally drops\n// `status` from the body — read it from the on-chain contract when you need\n// the canonical lifecycle state.\nexport interface DataPointRecord {\n  id: string;\n  ownerAddress: string;\n  scope: string;\n  dataHash: string;\n  metadataHash: string;\n  // Decimal-string uint256.\n  expectedVersion: string;\n  // ISO 8601 timestamp of the most recent gateway-side upsert.\n  addedAt: string;\n  // ISO 8601 timestamp of the deletion tombstone, null/absent while live.\n  // Only present on reads that opted in via `includeDeleted`; a plain\n  // `getDataPoint` of a deleted row throws `DataPointDeletedError` instead.\n  deletedAt?: string | null;\n}\n\nexport interface GetDataPointOptions {\n  /**\n   * Return the row even after it was deleted (with `deletedAt` set and the\n   * tombstone hash pair) instead of throwing `DataPointDeletedError`.\n   */\n  includeDeleted?: boolean;\n}\n\nexport interface DataPointListResult {\n  dataPoints: DataPointRecord[];\n  cursor: string | null;\n}\n\nexport interface ListDataPointsOptions {\n  /**\n   * Only return rows added at or after this ISO 8601 timestamp. Used by sync\n   * loops that want incremental tails — pass the last seen `addedAt`.\n   */\n  since?: string;\n  /** Page size. Capped at 1000 by the gateway. */\n  limit?: number;\n  /**\n   * Include deleted (tombstoned) rows, each carrying `deletedAt`. Off by\n   * default; without it the SDK also drops any tombstone the gateway leaks.\n   */\n  includeDeleted?: boolean;\n}\n\n// grantVersion and expiresAt are decimal-string uint256s — same wire format\n// the gateway expects. The caller is responsible for converting their bigint\n// to a decimal string and for signing GRANT_REGISTRATION_TYPES with matching\n// bigint values.\nexport interface CreateGrantParams {\n  grantorAddress: string;\n  granteeId: string;\n  scopes: string[];\n  grantVersion: string;\n  expiresAt: string;\n  signature: string;\n}\n\nexport interface RevokeGrantParams {\n  grantId: string;\n  grantorAddress: string;\n  grantVersion: string;\n  signature: string;\n}\n\nexport interface RegisterServerParams {\n  ownerAddress: string;\n  serverAddress: string;\n  publicKey: string;\n  serverUrl: string;\n  signature: string;\n}\n\nexport interface RegisterServerResult {\n  serverId?: string;\n  alreadyRegistered: boolean;\n}\n\nexport interface RegisterBuilderParams {\n  ownerAddress: string;\n  // Wallet the builder authenticates to the Personal Server with. The\n  // builderId is deterministically derived from (owner, grantee, publicKey,\n  // appUrl) so this triple pins the on-chain identity.\n  granteeAddress: string;\n  publicKey: string;\n  appUrl: string;\n  signature: string;\n}\n\nexport interface RegisterBuilderResult {\n  builderId?: string;\n  alreadyRegistered: boolean;\n}\n\n// AddData on DataRegistryV2. dataHash + metadataHash are bytes32 commitments\n// to the off-chain payload + its metadata. expectedVersion is a CAS knob —\n// the gateway/contract rejects on 409 if a higher version is already stored,\n// and the error body surfaces `currentExpectedVersion` so callers can re-sign.\nexport interface RegisterDataPointParams {\n  ownerAddress: string;\n  scope: string;\n  dataHash: string;\n  metadataHash: string;\n  expectedVersion: string;\n  signature: string;\n}\n\nexport interface RegisterDataPointResult {\n  dataPointId?: string;\n  expectedVersion?: string;\n}\n\n// Deletion = an owner-signed AddData for version current+1 carrying the\n// tombstone hash pair (see protocol/data-point-deletion.ts). The gateway\n// reconstructs the AddData from the body plus the tombstone constants and\n// recovers the signer, so the hashes are NOT on the wire. Used at\n// DELETE /v1/data/:dataPointId. expectedVersion is the tombstone's version\n// as a decimal uint256 string; the signature is the raw EIP-712 hex.\nexport interface DeleteDataPointParams {\n  ownerAddress: string;\n  scope: string;\n  expectedVersion: string;\n  signature: string;\n}\n\n// The tombstone version record the gateway returns on 200. Fields are\n// optional because, like RegisterDataPointResult, the SDK tolerates either\n// a bare body or an enveloped `{data}`; `deletedAt` is the durable marker.\nexport interface DeleteDataPointResult {\n  dataPointId?: string;\n  ownerAddress?: string;\n  scope?: string;\n  dataHash?: string;\n  metadataHash?: string;\n  expectedVersion?: string;\n  deletedAt?: string | null;\n}\n\n// ── Escrow / data-access payment path ───────────────────────────────────────\n// /v1/escrow/pay debits the payer's escrow balance for a payable op. For a\n// Legacy grants use opType='grant' and opId=grantId. Standalone receipt-bound\n// reads use opType='data_access' and opId=accessRecord.recordId. amount and\n// paymentNonce are decimal uint256 strings on the wire. The signature is the\n// raw EIP-712 hex of GENERIC_PAYMENT_TYPES against escrowPaymentDomain.\n\n// A server-signed delivery receipt attached to a data-access payment. The\n// signature is over RECORD_DATA_ACCESS_TYPES against dataRegistryDomain; the\n// signer must be a personal server the data point's owner has registered as\n// trusted. Shape validation in clients does not verify this signature; the\n// gateway verifies it before re-using it on-chain in the next /v1/settle pass\n// via DataRegistryV2.recordDataAccess, where `recordId` dedupes via\n// `_usedRecordIds`.\nexport interface AccessRecord {\n  dataPointId: string;\n  // Decimal-string uint256 — the data point version being attested to.\n  version: string;\n  // Must equal the enclosing payment's payerAddress (the gateway enforces).\n  accessor: string;\n  recordId: string;\n  signature: string;\n}\n\nexport interface PayForOperationParams {\n  payerAddress: string;\n  opType: string;\n  opId: string;\n  asset: string;\n  amount: string;\n  // Per-payer monotonic; (payer, nonce, kind) must be unique. The gateway\n  // returns 409 if reused — bump and re-sign.\n  paymentNonce: string;\n  signature: string;\n  // Optional: attach a server-signed access record so the next /v1/settle\n  // pass submits a recordDataAccess tx alongside the payment settlement.\n  // Required for data-access payments (the second-and-onward payments per\n  // grant) that want their on-chain `totalAccesses` counter to advance.\n  accessRecord?: AccessRecord;\n}\n\nexport interface PayForOperationResult {\n  opType: string;\n  opId: string;\n  payerAddress: string;\n  asset: string;\n  amount: string;\n  // Echoes how the gateway split this payment. `registrationPaid` is true on\n  // the first payment for a grant (which bundles both fees) and false on\n  // subsequent data-access-only payments. Off-chain ledger state only — the\n  // on-chain settlement of the registration is tracked by the grant's\n  // `status` field, not this flag.\n  breakdown: {\n    registrationFee: string;\n    dataAccessFee: string;\n    registrationPaid: boolean;\n  };\n  paymentNonce: string;\n  paidAt: string;\n}\n\n// ── Settle / reconcile ──────────────────────────────────────────────────────\n// POST /v1/settle drains pending-on-chain rows (grants, servers, builders,\n// data points, data-point statuses, access records) to the relayer, then\n// promotes 'submitting' → 'confirmed' and 'confirmed' → 'finalized' for\n// previously-submitted rows. One call does all three; the response surfaces\n// each phase's outcomes.\n\n// The op-types the settle endpoint emits in `items[]`. Kept as a union so\n// callers can narrow inside the discriminated SettleItem shape. Mirrors the\n// gateway's drain phases (drainGrants/drainServers/drainBuilders/\n// drainDataPoints/drainDataPointStatuses/drainAccessRecords) — keep in sync\n// when the gateway adds a drain.\nexport type SettleOpType =\n  | \"grant\"\n  | \"server\"\n  | \"data\"\n  | \"access\"\n  | \"builder\"\n  | \"data-status\";\n\nexport type SettleItem =\n  | {\n      opType: SettleOpType;\n      opId: string;\n      // 'confirmed' when the submit function waited for the receipt and it\n      // mined (registerAndSettle path); 'submitting' when only the tx was\n      // sent (no receipt wait).\n      status: \"submitting\" | \"confirmed\";\n      settleTxHash: string | null;\n      settleSubmittedAt: string | null;\n      // Block height the tx mined in; only set when status === 'confirmed'.\n      chainBlockHeight: string | null;\n      revocationTxHash: string | null;\n      revocationSubmittedAt: string | null;\n      // True while lib/settle.ts is in placeholder mode for this row's pass.\n      placeholder: boolean;\n    }\n  | {\n      opType: SettleOpType;\n      opId: string;\n      status: \"skipped\";\n      reason: string;\n    }\n  | {\n      opType: SettleOpType;\n      opId: string;\n      status: \"failed\";\n      error: string;\n    };\n\n// Outcome of the housekeeping pass that retries earlier `submitting` rows\n// whose receipt arrived after the prior /v1/settle's wait budget elapsed.\nexport interface SettlePromoteResult {\n  opType: SettleOpType;\n  opId: string;\n  status: \"confirmed\" | \"failed\" | \"pending\" | \"skipped\";\n  txHash: string;\n  chainBlockHeight: string | null;\n  reason?: string;\n}\n\n// Outcome of the reconcile pass that advances 'confirmed' → 'finalized' once\n// the chain's finalized tip catches up past the tx's block (or reverts to\n// 'pending' on reorg detection).\nexport interface SettleReconcileItem {\n  opId: string;\n  status: \"finalized\" | \"reorged\" | \"unchanged\";\n  chainBlockHeight: string | null;\n  settleTxHash: string | null;\n  reason?: string;\n}\n\nexport interface SettleParams {\n  // Per-phase cap. Bounded by MAX_LIMIT on the gateway side; omit to use\n  // the gateway's default BATCH_LIMIT.\n  limit?: number;\n}\n\nexport interface SettleResult {\n  scanned: number;\n  submitted: number;\n  confirmed: number;\n  skipped: number;\n  failed: number;\n  items: SettleItem[];\n  promoted: { count: number; items: SettlePromoteResult[] };\n  reconciled: {\n    scanned: number;\n    finalized: number;\n    reorged: number;\n    unchanged: number;\n    items: SettleReconcileItem[];\n  };\n  // Present only when the gateway is configured for paced submission —\n  // spreads work across several blocks within one /v1/settle invocation.\n  paced?: { iterations: number };\n}\n\n/**\n * Legacy `GatewayClient` name for the canonical `/v1/escrow/balance` response.\n * `availableAmount` is `max(balance − authorizedAmount − withdrawingAmount, 0)`.\n */\nexport type EscrowBalance = EscrowBalanceResult;\n\n// /v1/escrow/deposit announces an on-chain deposit tx so the gateway can\n// reconcile it into the payer's balance. The gateway extracts the credited\n// account from calldata — no off-chain claim about who paid.\nexport interface SubmitDepositParams {\n  txHash: string;\n}\n\nexport interface DepositState {\n  txHash: string;\n  account: string;\n  // 'submitted' | 'finalized' | 'failed' — kept open since the gateway adds\n  // states (e.g. 'orphaned') as the deposit flow evolves.\n  status: string;\n  blockNumber: string | null;\n  submittedAt: string;\n  finalizedAt: string | null;\n  lastError: string | null;\n}\n\nexport interface GatewayClient {\n  isRegisteredBuilder(address: string): Promise<boolean>;\n  getBuilder(address: string): Promise<Builder | null>;\n  getGrant(grantId: string): Promise<GatewayGrantResponse | null>;\n  listGrantsByUser(userAddress: string): Promise<GrantListItem[]>;\n  getSchemaForScope(scope: string): Promise<Schema | null>;\n  getServer(address: string): Promise<ServerInfo | null>;\n  /**\n   * List every personal server an owner has registered — split into `active`\n   * (currently trusted) and `revoked` (deregistered). Each list is ordered\n   * newest-first; `active[0]` is the sensible default when the caller just\n   * needs one URL for the owner. Empty owner returns `{active: [], revoked: [], count: 0}`.\n   * Discovery-only endpoint — no per-server attestation; use `getServer` for that.\n   */\n  listServersByOwner(owner: string): Promise<OwnerServersResult>;\n  /**\n   * Fetch a single data point by its deterministic id (keccak256 of (owner, scope)).\n   * Returns null on 404. Throws `DataPointDeletedError` on 410, or when the row is a\n   * tombstone, unless `options.includeDeleted` is set. The gateway omits `status` from\n   * the response body -- read it from the on-chain DataRegistryV2 contract when you need\n   * the canonical lifecycle state.\n   */\n  getDataPoint(\n    dataPointId: string,\n    options?: GetDataPointOptions,\n  ): Promise<DataPointRecord | null>;\n  /**\n   * Page through an owner's data points. Cursor is opaque; pass `null` for the first\n   * page and feed back `result.cursor` until it returns null.\n   * Deleted rows are excluded unless `options.includeDeleted` is set.\n   */\n  listDataPointsByOwner(\n    owner: string,\n    cursor: string | null,\n    options?: ListDataPointsOptions,\n  ): Promise<DataPointListResult>;\n  getSchema(schemaId: string): Promise<Schema | null>;\n  registerServer(params: RegisterServerParams): Promise<RegisterServerResult>;\n  registerBuilder(\n    params: RegisterBuilderParams,\n  ): Promise<RegisterBuilderResult>;\n  registerDataPoint(\n    params: RegisterDataPointParams,\n  ): Promise<RegisterDataPointResult>;\n  /**\n   * Tombstone a data point: `DELETE /v1/data/:dataPointId` with the owner's\n   * AddData signature for version `current + 1`. The dataPointId is derived\n   * from (ownerAddress, scope). Throws `DataPointVersionConflictError` on\n   * 409, `DataPointDeletedError` on 410 (already deleted),\n   * `DataPointNotFoundError` on 404.\n   */\n  deleteDataPoint(\n    params: DeleteDataPointParams,\n  ): Promise<DeleteDataPointResult>;\n  createGrant(params: CreateGrantParams): Promise<{ grantId?: string }>;\n  revokeGrant(params: RevokeGrantParams): Promise<void>;\n  getEscrowBalance(account: string): Promise<EscrowBalanceResult>;\n  submitEscrowDeposit(params: SubmitDepositParams): Promise<DepositState>;\n  payForOperation(\n    params: PayForOperationParams,\n  ): Promise<PayForOperationResult>;\n  settle(params?: SettleParams): Promise<SettleResult>;\n}\n\n// Attach the derived `permissions` view to a grant record read back from the\n// gateway. The wire `scopes` are left untouched.\nfunction withGrantPermissions<T extends GatewayGrantResponse>(grant: T): T {\n  // Gateway responses are untrusted runtime data despite their type. The\n  // `permissions` view is SDK-owned: drop whatever the body carried under\n  // that name, then derive only from a well-formed string[] and leave the\n  // field absent otherwise, so a spoofed or stale value can never be\n  // rendered as this grant's authority.\n  const stripped = { ...grant };\n  delete stripped.permissions;\n  const scopes: unknown = stripped.scopes;\n  if (!Array.isArray(scopes)) {\n    return stripped;\n  }\n  const permissions = tryGrantPermissions(scopes as string[]);\n  return permissions === undefined ? stripped : { ...stripped, permissions };\n}\n\nexport function createGatewayClient(baseUrl: string): GatewayClient {\n  const base = baseUrl.replace(/\\/+$/, \"\");\n\n  function malformedBody(res: Response): Error {\n    return new Error(\n      `Gateway error: ${res.status} malformed response body (expected a JSON envelope)`,\n    );\n  }\n\n  // GET responses are `{ data, proof, pagination? }`. A 200 whose body is\n  // empty, not JSON, or not an object with `data` is a gateway bug, not a\n  // record: fail with a clear error instead of returning undefined.\n  async function readEnvelope<T>(\n    res: Response,\n  ): Promise<Record<string, unknown> & { data: T }> {\n    const envelope = await readJsonValue(res);\n    if (!isPlainObject(envelope) || !(\"data\" in envelope)) {\n      throw malformedBody(res);\n    }\n    return envelope as Record<string, unknown> & { data: T };\n  }\n\n  async function unwrapEnvelope<T>(res: Response): Promise<T> {\n    return (await readEnvelope<T>(res)).data;\n  }\n\n  function getMutationId(body: unknown, key: string): string | undefined {\n    if (!isPlainObject(body)) return undefined;\n    const value = body[key] ?? body[\"id\"];\n    return typeof value === \"string\" ? value : undefined;\n  }\n\n  // Mutation responses are bare JSON; GET responses are enveloped. Accept\n  // either so a gateway that wraps the tombstone record still round-trips.\n  // Any body that is not a plain object (empty 204, `null`, an array, an\n  // HTML error page) reads as `{}` so the status-code mapping still wins.\n  async function readBody(res: Response): Promise<Record<string, unknown>> {\n    const raw = await readJsonObject(res);\n    const data = raw[\"data\"];\n    if (isPlainObject(data) && \"proof\" in raw) {\n      return data;\n    }\n    return raw;\n  }\n\n  function stringOrUndefined(value: unknown): string | undefined {\n    return typeof value === \"string\" ? value : undefined;\n  }\n\n  async function deletedError(\n    res: Response,\n    details: { dataPointId?: string; scope?: string; ownerAddress?: string },\n  ): Promise<DataPointDeletedError> {\n    const body = await readBody(res);\n    return new DataPointDeletedError(\n      `Data point ${details.dataPointId ?? details.scope ?? \"\"} has been deleted`,\n      { ...details, deletedAt: tombstoneDeletedAt(body) },\n    );\n  }\n\n  return {\n    async isRegisteredBuilder(address: string): Promise<boolean> {\n      const builder = await this.getBuilder(address);\n      return builder !== null;\n    },\n\n    async getBuilder(address: string): Promise<Builder | null> {\n      const res = await fetch(`${base}/v1/builders/${address}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<Builder>(res);\n    },\n\n    async getGrant(grantId: string): Promise<GatewayGrantResponse | null> {\n      const res = await fetch(`${base}/v1/grants/${grantId}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return withGrantPermissions(\n        await unwrapEnvelope<GatewayGrantResponse>(res),\n      );\n    },\n\n    async listGrantsByUser(userAddress: string): Promise<GrantListItem[]> {\n      const res = await fetch(`${base}/v1/grants?user=${userAddress}`);\n      if (res.status === 404) return [];\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const grants = await unwrapEnvelope<GrantListItem[]>(res);\n      return grants.map(withGrantPermissions);\n    },\n\n    async getSchemaForScope(scope: string): Promise<Schema | null> {\n      const res = await fetch(`${base}/v1/schemas?scope=${scope}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<Schema>(res);\n    },\n\n    async getServer(address: string): Promise<ServerInfo | null> {\n      const res = await fetch(`${base}/v1/servers/${address}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<ServerInfo>(res);\n    },\n\n    async listServersByOwner(owner: string): Promise<OwnerServersResult> {\n      // URLSearchParams encodes the owner so a malformed value (e.g.\n      // \"0xabc&foo=bar\") can't inject extra query params. Same pattern as\n      // listDataPointsByOwner.\n      const params = new URLSearchParams({ owner });\n      const res = await fetch(`${base}/v1/servers?${params.toString()}`);\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      // Unlike /v1/servers/:address, the list endpoint returns the body\n      // directly — no GatewayEnvelope, no attestation (discovery-only).\n      return (await res.json()) as OwnerServersResult;\n    },\n\n    async getDataPoint(\n      dataPointId: string,\n      options?: GetDataPointOptions,\n    ): Promise<DataPointRecord | null> {\n      const query = options?.includeDeleted ? \"?includeDeleted=true\" : \"\";\n      const res = await fetch(`${base}/v1/data/${dataPointId}${query}`);\n      if (res.status === 404) return null;\n      if (res.status === 410) {\n        throw await deletedError(res, { dataPointId });\n      }\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const record = await unwrapEnvelope<DataPointRecord>(res);\n      // Never hand a tombstone back as data unless the caller opted in --\n      // guards against a gateway that returns 200 + deletedAt on plain reads.\n      if (!options?.includeDeleted && isDataPointTombstone(record)) {\n        throw new DataPointDeletedError(\n          `Data point ${dataPointId} has been deleted`,\n          {\n            dataPointId,\n            scope: record.scope,\n            ownerAddress: record.ownerAddress,\n            deletedAt: tombstoneDeletedAt(record),\n          },\n        );\n      }\n      return record;\n    },\n\n    async listDataPointsByOwner(\n      owner: string,\n      cursor: string | null,\n      options?: ListDataPointsOptions,\n    ): Promise<DataPointListResult> {\n      const params = new URLSearchParams({ user: owner });\n      if (cursor !== null) {\n        params.set(\"cursor\", cursor);\n      }\n      if (options?.since) {\n        params.set(\"since\", options.since);\n      }\n      if (options?.limit !== undefined) {\n        params.set(\"limit\", String(options.limit));\n      }\n      if (options?.includeDeleted) {\n        params.set(\"includeDeleted\", \"true\");\n      }\n      const res = await fetch(`${base}/v1/data?${params.toString()}`);\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      // Next-page cursor lives in the envelope's `pagination.nextCursor`\n      // (a sibling of `data`), so read the full envelope rather than going\n      // through `unwrapEnvelope`, which returns only `data`.\n      const envelope = await readEnvelope<unknown>(res);\n      if (\n        !isPlainObject(envelope.data) ||\n        !Array.isArray(envelope.data[\"dataPoints\"])\n      ) {\n        throw malformedBody(res);\n      }\n      const rows = envelope.data[\"dataPoints\"] as DataPointRecord[];\n      const pagination = isPlainObject(envelope[\"pagination\"])\n        ? envelope[\"pagination\"]\n        : undefined;\n      const rawCursor = pagination?.[\"nextCursor\"];\n      const nextCursor =\n        pagination?.[\"hasMore\"] === false || typeof rawCursor !== \"string\"\n          ? null\n          : rawCursor;\n      // Tombstones only surface when asked for; drop any the gateway leaks\n      // on a plain list so sync loops never ingest one as data.\n      const dataPoints = options?.includeDeleted\n        ? rows\n        : rows.filter((row) => !isDataPointTombstone(row));\n      return {\n        dataPoints,\n        cursor: nextCursor,\n      };\n    },\n\n    async getSchema(schemaId: string): Promise<Schema | null> {\n      const res = await fetch(`${base}/v1/schemas/${schemaId}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<Schema>(res);\n    },\n\n    async registerServer(\n      params: RegisterServerParams,\n    ): Promise<RegisterServerResult> {\n      const res = await fetch(`${base}/v1/servers`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          ownerAddress: params.ownerAddress,\n          serverAddress: params.serverAddress,\n          publicKey: params.publicKey,\n          serverUrl: params.serverUrl,\n        }),\n      });\n      if (res.status === 409) {\n        const body = await readJsonObject(res);\n        return {\n          serverId: getMutationId(body, \"serverId\"),\n          alreadyRegistered: true,\n        };\n      }\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const body = await readJsonObject(res);\n      return {\n        serverId: getMutationId(body, \"serverId\"),\n        alreadyRegistered: false,\n      };\n    },\n\n    async registerBuilder(\n      params: RegisterBuilderParams,\n    ): Promise<RegisterBuilderResult> {\n      const res = await fetch(`${base}/v1/builders`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          ownerAddress: params.ownerAddress,\n          granteeAddress: params.granteeAddress,\n          publicKey: params.publicKey,\n          appUrl: params.appUrl,\n        }),\n      });\n      // 409 is idempotent — the gateway's current 409 body doesn't include\n      // the builderId, but we tolerate it in case that changes (mirrors the\n      // registerServer / createGrant shape).\n      if (res.status === 409) {\n        const body = await readJsonObject(res);\n        return {\n          builderId: getMutationId(body, \"builderId\"),\n          alreadyRegistered: true,\n        };\n      }\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const body = await readJsonObject(res);\n      return {\n        builderId: getMutationId(body, \"builderId\"),\n        alreadyRegistered: false,\n      };\n    },\n\n    async registerDataPoint(\n      params: RegisterDataPointParams,\n    ): Promise<RegisterDataPointResult> {\n      const res = await fetch(`${base}/v1/data`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          ownerAddress: params.ownerAddress,\n          scope: params.scope,\n          dataHash: params.dataHash,\n          metadataHash: params.metadataHash,\n          expectedVersion: params.expectedVersion,\n        }),\n      });\n      // 409 is a real failure here (stale CAS), not an idempotent replay —\n      // surface the gateway's error message verbatim so the caller knows\n      // what `currentExpectedVersion` to re-sign against.\n      if (!res.ok) {\n        const body = await readJsonObject(res);\n        const detail = stringOrUndefined(body[\"error\"]) ?? res.statusText;\n        throw new Error(`Gateway error: ${res.status} ${detail}`);\n      }\n      const body = await readJsonObject(res);\n      return {\n        dataPointId: getMutationId(body, \"dataPointId\"),\n        expectedVersion: stringOrUndefined(body[\"expectedVersion\"]),\n      };\n    },\n\n    async deleteDataPoint(\n      params: DeleteDataPointParams,\n    ): Promise<DeleteDataPointResult> {\n      // The gateway keys the row on keccak256(abi.encode(owner, scope)) --\n      // derive it locally rather than asking the caller for it, so the path\n      // can never disagree with the signed (owner, scope).\n      const dataPointId = deriveDataPointId(\n        params.ownerAddress as `0x${string}`,\n        params.scope,\n      );\n      const details = {\n        dataPointId,\n        scope: params.scope,\n        ownerAddress: params.ownerAddress,\n      };\n      // Signature rides both in the body (the DELETE contract) and as the\n      // Web3Signed Authorization header every other /v1 mutation uses.\n      const res = await fetch(`${base}/v1/data/${dataPointId}`, {\n        method: \"DELETE\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          ownerAddress: params.ownerAddress,\n          scope: params.scope,\n          expectedVersion: params.expectedVersion,\n          signature: params.signature,\n        }),\n      });\n      if (res.status === 404) {\n        throw new DataPointNotFoundError(\n          `Data point ${dataPointId} (scope '${params.scope}') is not registered`,\n          details,\n        );\n      }\n      if (res.status === 409) {\n        const body = await readBody(res);\n        const currentExpectedVersion = stringOrUndefined(\n          body[\"currentExpectedVersion\"],\n        );\n        const detail = stringOrUndefined(body[\"error\"]) ?? res.statusText;\n        throw new DataPointVersionConflictError(\n          `Gateway error: 409 ${detail}`,\n          {\n            ...details,\n            expectedVersion: params.expectedVersion,\n            currentExpectedVersion,\n          },\n        );\n      }\n      if (res.status === 410) {\n        throw await deletedError(res, details);\n      }\n      if (!res.ok) {\n        // 400 = the recovered signer/hashes do not match the tombstone\n        // AddData. Surface the gateway's message verbatim, like\n        // registerDataPoint does.\n        const body = await readBody(res);\n        const detail = stringOrUndefined(body[\"error\"]) ?? res.statusText;\n        throw new Error(`Gateway error: ${res.status} ${detail}`);\n      }\n      const body = await readBody(res);\n      return {\n        dataPointId: getMutationId(body, \"dataPointId\") ?? dataPointId,\n        ownerAddress: stringOrUndefined(body[\"ownerAddress\"]),\n        scope: stringOrUndefined(body[\"scope\"]),\n        dataHash: stringOrUndefined(body[\"dataHash\"]),\n        metadataHash: stringOrUndefined(body[\"metadataHash\"]),\n        expectedVersion: stringOrUndefined(body[\"expectedVersion\"]),\n        deletedAt: tombstoneDeletedAt(body),\n      };\n    },\n\n    async createGrant(\n      params: CreateGrantParams,\n    ): Promise<{ grantId?: string }> {\n      const res = await fetch(`${base}/v1/grants`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          grantorAddress: params.grantorAddress,\n          granteeId: params.granteeId,\n          scopes: params.scopes,\n          grantVersion: params.grantVersion,\n          expiresAt: params.expiresAt,\n        }),\n      });\n      if (res.status === 409) {\n        const body = await readJsonObject(res);\n        return { grantId: getMutationId(body, \"grantId\") };\n      }\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const body = await readJsonObject(res);\n      return { grantId: getMutationId(body, \"grantId\") };\n    },\n\n    async revokeGrant(params: RevokeGrantParams): Promise<void> {\n      const res = await fetch(`${base}/v1/grants/${params.grantId}`, {\n        method: \"DELETE\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          grantorAddress: params.grantorAddress,\n          grantVersion: params.grantVersion,\n        }),\n      });\n      if (res.status === 409) return;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n    },\n\n    async getEscrowBalance(account: string): Promise<EscrowBalanceResult> {\n      const res = await fetch(`${base}/v1/escrow/balance?account=${account}`);\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      // Unlike the rest of /v1, the balance endpoint returns the body\n      // directly (no GatewayEnvelope wrap) — it's a pure read with no\n      // gateway-signed attestation. See data-gateway api/v1/escrow/balance.ts.\n      return (await res.json()) as EscrowBalanceResult;\n    },\n\n    async submitEscrowDeposit(\n      params: SubmitDepositParams,\n    ): Promise<DepositState> {\n      const res = await fetch(`${base}/v1/escrow/deposit`, {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({ txHash: params.txHash }),\n      });\n      // The gateway returns 202 for \"accepted (still confirming)\" and 200 for\n      // duplicate idempotent replays. Both carry the deposit's current state.\n      if (res.status !== 200 && res.status !== 202) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return (await res.json()) as DepositState;\n    },\n\n    async payForOperation(\n      params: PayForOperationParams,\n    ): Promise<PayForOperationResult> {\n      // Build the body without the accessRecord key when absent so the\n      // gateway's \"missing optional\" branch matches the no-receipt case\n      // exactly (an explicit `accessRecord: undefined` would JSON-serialize\n      // to nothing — same result — but keeping it conditional makes wire\n      // traces easier to read).\n      const body: Record<string, unknown> = {\n        payerAddress: params.payerAddress,\n        opType: params.opType,\n        opId: params.opId,\n        asset: params.asset,\n        amount: params.amount,\n        paymentNonce: params.paymentNonce,\n      };\n      if (params.accessRecord) {\n        body[\"accessRecord\"] = params.accessRecord;\n      }\n      const res = await fetch(`${base}/v1/escrow/pay`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify(body),\n      });\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return (await res.json()) as PayForOperationResult;\n    },\n\n    async settle(params?: SettleParams): Promise<SettleResult> {\n      const res = await fetch(`${base}/v1/settle`, {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        // The gateway accepts an empty body; only `limit` is recognised.\n        // Always send a JSON body so the gateway's req.body shape parse\n        // doesn't have to deal with an undefined.\n        body: JSON.stringify(params ?? {}),\n      });\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return (await res.json()) as SettleResult;\n    },\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAA0D;AAC1D,oBAIO;AACP,iCAGO;AACP,qBAAkC;AAClC,2BAIO;AA0jBP,SAAS,qBAAqD,OAAa;AAMzE,QAAM,WAAW,EAAE,GAAG,MAAM;AAC5B,SAAO,SAAS;AAChB,QAAM,SAAkB,SAAS;AACjC,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,WAAO;AAAA,EACT;AACA,QAAM,kBAAc,0CAAoB,MAAkB;AAC1D,SAAO,gBAAgB,SAAY,WAAW,EAAE,GAAG,UAAU,YAAY;AAC3E;AAEO,SAAS,oBAAoB,SAAgC;AAClE,QAAM,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AAEvC,WAAS,cAAc,KAAsB;AAC3C,WAAO,IAAI;AAAA,MACT,kBAAkB,IAAI,MAAM;AAAA,IAC9B;AAAA,EACF;AAKA,iBAAe,aACb,KACgD;AAChD,UAAM,WAAW,UAAM,oCAAc,GAAG;AACxC,QAAI,KAAC,oCAAc,QAAQ,KAAK,EAAE,UAAU,WAAW;AACrD,YAAM,cAAc,GAAG;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAEA,iBAAe,eAAkB,KAA2B;AAC1D,YAAQ,MAAM,aAAgB,GAAG,GAAG;AAAA,EACtC;AAEA,WAAS,cAAc,MAAe,KAAiC;AACrE,QAAI,KAAC,oCAAc,IAAI,EAAG,QAAO;AACjC,UAAM,QAAQ,KAAK,GAAG,KAAK,KAAK,IAAI;AACpC,WAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,EAC7C;AAMA,iBAAe,SAAS,KAAiD;AACvE,UAAM,MAAM,UAAM,qCAAe,GAAG;AACpC,UAAM,OAAO,IAAI,MAAM;AACvB,YAAI,oCAAc,IAAI,KAAK,WAAW,KAAK;AACzC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,WAAS,kBAAkB,OAAoC;AAC7D,WAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,EAC7C;AAEA,iBAAe,aACb,KACA,SACgC;AAChC,UAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,WAAO,IAAI;AAAA,MACT,cAAc,QAAQ,eAAe,QAAQ,SAAS,EAAE;AAAA,MACxD,EAAE,GAAG,SAAS,eAAW,+CAAmB,IAAI,EAAE;AAAA,IACpD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,oBAAoB,SAAmC;AAC3D,YAAM,UAAU,MAAM,KAAK,WAAW,OAAO;AAC7C,aAAO,YAAY;AAAA,IACrB;AAAA,IAEA,MAAM,WAAW,SAA0C;AACzD,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,gBAAgB,OAAO,EAAE;AACxD,UAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,aAAO,eAAwB,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,SAAS,SAAuD;AACpE,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,cAAc,OAAO,EAAE;AACtD,UAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,aAAO;AAAA,QACL,MAAM,eAAqC,GAAG;AAAA,MAChD;AAAA,IACF;AAAA,IAEA,MAAM,iBAAiB,aAA+C;AACpE,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,mBAAmB,WAAW,EAAE;AAC/D,UAAI,IAAI,WAAW,IAAK,QAAO,CAAC;AAChC,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,YAAM,SAAS,MAAM,eAAgC,GAAG;AACxD,aAAO,OAAO,IAAI,oBAAoB;AAAA,IACxC;AAAA,IAEA,MAAM,kBAAkB,OAAuC;AAC7D,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,qBAAqB,KAAK,EAAE;AAC3D,UAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,aAAO,eAAuB,GAAG;AAAA,IACnC;AAAA,IAEA,MAAM,UAAU,SAA6C;AAC3D,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,eAAe,OAAO,EAAE;AACvD,UAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,aAAO,eAA2B,GAAG;AAAA,IACvC;AAAA,IAEA,MAAM,mBAAmB,OAA4C;AAInE,YAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,CAAC;AAC5C,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,eAAe,OAAO,SAAS,CAAC,EAAE;AACjE,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AAGA,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,aACJ,aACA,SACiC;AACjC,YAAM,QAAQ,SAAS,iBAAiB,yBAAyB;AACjE,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,YAAY,WAAW,GAAG,KAAK,EAAE;AAChE,UAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,UAAI,IAAI,WAAW,KAAK;AACtB,cAAM,MAAM,aAAa,KAAK,EAAE,YAAY,CAAC;AAAA,MAC/C;AACA,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,YAAM,SAAS,MAAM,eAAgC,GAAG;AAGxD,UAAI,CAAC,SAAS,sBAAkB,iDAAqB,MAAM,GAAG;AAC5D,cAAM,IAAI;AAAA,UACR,cAAc,WAAW;AAAA,UACzB;AAAA,YACE;AAAA,YACA,OAAO,OAAO;AAAA,YACd,cAAc,OAAO;AAAA,YACrB,eAAW,+CAAmB,MAAM;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,sBACJ,OACA,QACA,SAC8B;AAC9B,YAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAClD,UAAI,WAAW,MAAM;AACnB,eAAO,IAAI,UAAU,MAAM;AAAA,MAC7B;AACA,UAAI,SAAS,OAAO;AAClB,eAAO,IAAI,SAAS,QAAQ,KAAK;AAAA,MACnC;AACA,UAAI,SAAS,UAAU,QAAW;AAChC,eAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AAAA,MAC3C;AACA,UAAI,SAAS,gBAAgB;AAC3B,eAAO,IAAI,kBAAkB,MAAM;AAAA,MACrC;AACA,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,YAAY,OAAO,SAAS,CAAC,EAAE;AAC9D,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AAIA,YAAM,WAAW,MAAM,aAAsB,GAAG;AAChD,UACE,KAAC,oCAAc,SAAS,IAAI,KAC5B,CAAC,MAAM,QAAQ,SAAS,KAAK,YAAY,CAAC,GAC1C;AACA,cAAM,cAAc,GAAG;AAAA,MACzB;AACA,YAAM,OAAO,SAAS,KAAK,YAAY;AACvC,YAAM,iBAAa,oCAAc,SAAS,YAAY,CAAC,IACnD,SAAS,YAAY,IACrB;AACJ,YAAM,YAAY,aAAa,YAAY;AAC3C,YAAM,aACJ,aAAa,SAAS,MAAM,SAAS,OAAO,cAAc,WACtD,OACA;AAGN,YAAM,aAAa,SAAS,iBACxB,OACA,KAAK,OAAO,CAAC,QAAQ,KAAC,iDAAqB,GAAG,CAAC;AACnD,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,IAEA,MAAM,UAAU,UAA0C;AACxD,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,eAAe,QAAQ,EAAE;AACxD,UAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,aAAO,eAAuB,GAAG;AAAA,IACnC;AAAA,IAEA,MAAM,eACJ,QAC+B;AAC/B,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,eAAe;AAAA,QAC5C,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,cAAc,OAAO,SAAS;AAAA,QAC/C;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,cAAc,OAAO;AAAA,UACrB,eAAe,OAAO;AAAA,UACtB,WAAW,OAAO;AAAA,UAClB,WAAW,OAAO;AAAA,QACpB,CAAC;AAAA,MACH,CAAC;AACD,UAAI,IAAI,WAAW,KAAK;AACtB,cAAMA,QAAO,UAAM,qCAAe,GAAG;AACrC,eAAO;AAAA,UACL,UAAU,cAAcA,OAAM,UAAU;AAAA,UACxC,mBAAmB;AAAA,QACrB;AAAA,MACF;AACA,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,YAAM,OAAO,UAAM,qCAAe,GAAG;AACrC,aAAO;AAAA,QACL,UAAU,cAAc,MAAM,UAAU;AAAA,QACxC,mBAAmB;AAAA,MACrB;AAAA,IACF;AAAA,IAEA,MAAM,gBACJ,QACgC;AAChC,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,gBAAgB;AAAA,QAC7C,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,cAAc,OAAO,SAAS;AAAA,QAC/C;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,cAAc,OAAO;AAAA,UACrB,gBAAgB,OAAO;AAAA,UACvB,WAAW,OAAO;AAAA,UAClB,QAAQ,OAAO;AAAA,QACjB,CAAC;AAAA,MACH,CAAC;AAID,UAAI,IAAI,WAAW,KAAK;AACtB,cAAMA,QAAO,UAAM,qCAAe,GAAG;AACrC,eAAO;AAAA,UACL,WAAW,cAAcA,OAAM,WAAW;AAAA,UAC1C,mBAAmB;AAAA,QACrB;AAAA,MACF;AACA,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,YAAM,OAAO,UAAM,qCAAe,GAAG;AACrC,aAAO;AAAA,QACL,WAAW,cAAc,MAAM,WAAW;AAAA,QAC1C,mBAAmB;AAAA,MACrB;AAAA,IACF;AAAA,IAEA,MAAM,kBACJ,QACkC;AAClC,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,YAAY;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,cAAc,OAAO,SAAS;AAAA,QAC/C;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,cAAc,OAAO;AAAA,UACrB,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,cAAc,OAAO;AAAA,UACrB,iBAAiB,OAAO;AAAA,QAC1B,CAAC;AAAA,MACH,CAAC;AAID,UAAI,CAAC,IAAI,IAAI;AACX,cAAMA,QAAO,UAAM,qCAAe,GAAG;AACrC,cAAM,SAAS,kBAAkBA,MAAK,OAAO,CAAC,KAAK,IAAI;AACvD,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,MAAM,EAAE;AAAA,MAC1D;AACA,YAAM,OAAO,UAAM,qCAAe,GAAG;AACrC,aAAO;AAAA,QACL,aAAa,cAAc,MAAM,aAAa;AAAA,QAC9C,iBAAiB,kBAAkB,KAAK,iBAAiB,CAAC;AAAA,MAC5D;AAAA,IACF;AAAA,IAEA,MAAM,gBACJ,QACgC;AAIhC,YAAM,kBAAc;AAAA,QAClB,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AACA,YAAM,UAAU;AAAA,QACd;AAAA,QACA,OAAO,OAAO;AAAA,QACd,cAAc,OAAO;AAAA,MACvB;AAGA,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,YAAY,WAAW,IAAI;AAAA,QACxD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,cAAc,OAAO,SAAS;AAAA,QAC/C;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,cAAc,OAAO;AAAA,UACrB,OAAO,OAAO;AAAA,UACd,iBAAiB,OAAO;AAAA,UACxB,WAAW,OAAO;AAAA,QACpB,CAAC;AAAA,MACH,CAAC;AACD,UAAI,IAAI,WAAW,KAAK;AACtB,cAAM,IAAI;AAAA,UACR,cAAc,WAAW,YAAY,OAAO,KAAK;AAAA,UACjD;AAAA,QACF;AAAA,MACF;AACA,UAAI,IAAI,WAAW,KAAK;AACtB,cAAMA,QAAO,MAAM,SAAS,GAAG;AAC/B,cAAM,yBAAyB;AAAA,UAC7BA,MAAK,wBAAwB;AAAA,QAC/B;AACA,cAAM,SAAS,kBAAkBA,MAAK,OAAO,CAAC,KAAK,IAAI;AACvD,cAAM,IAAI;AAAA,UACR,sBAAsB,MAAM;AAAA,UAC5B;AAAA,YACE,GAAG;AAAA,YACH,iBAAiB,OAAO;AAAA,YACxB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,IAAI,WAAW,KAAK;AACtB,cAAM,MAAM,aAAa,KAAK,OAAO;AAAA,MACvC;AACA,UAAI,CAAC,IAAI,IAAI;AAIX,cAAMA,QAAO,MAAM,SAAS,GAAG;AAC/B,cAAM,SAAS,kBAAkBA,MAAK,OAAO,CAAC,KAAK,IAAI;AACvD,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,MAAM,EAAE;AAAA,MAC1D;AACA,YAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,aAAO;AAAA,QACL,aAAa,cAAc,MAAM,aAAa,KAAK;AAAA,QACnD,cAAc,kBAAkB,KAAK,cAAc,CAAC;AAAA,QACpD,OAAO,kBAAkB,KAAK,OAAO,CAAC;AAAA,QACtC,UAAU,kBAAkB,KAAK,UAAU,CAAC;AAAA,QAC5C,cAAc,kBAAkB,KAAK,cAAc,CAAC;AAAA,QACpD,iBAAiB,kBAAkB,KAAK,iBAAiB,CAAC;AAAA,QAC1D,eAAW,+CAAmB,IAAI;AAAA,MACpC;AAAA,IACF;AAAA,IAEA,MAAM,YACJ,QAC+B;AAC/B,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,cAAc;AAAA,QAC3C,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,cAAc,OAAO,SAAS;AAAA,QAC/C;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,gBAAgB,OAAO;AAAA,UACvB,WAAW,OAAO;AAAA,UAClB,QAAQ,OAAO;AAAA,UACf,cAAc,OAAO;AAAA,UACrB,WAAW,OAAO;AAAA,QACpB,CAAC;AAAA,MACH,CAAC;AACD,UAAI,IAAI,WAAW,KAAK;AACtB,cAAMA,QAAO,UAAM,qCAAe,GAAG;AACrC,eAAO,EAAE,SAAS,cAAcA,OAAM,SAAS,EAAE;AAAA,MACnD;AACA,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,YAAM,OAAO,UAAM,qCAAe,GAAG;AACrC,aAAO,EAAE,SAAS,cAAc,MAAM,SAAS,EAAE;AAAA,IACnD;AAAA,IAEA,MAAM,YAAY,QAA0C;AAC1D,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,cAAc,OAAO,OAAO,IAAI;AAAA,QAC7D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,cAAc,OAAO,SAAS;AAAA,QAC/C;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,gBAAgB,OAAO;AAAA,UACvB,cAAc,OAAO;AAAA,QACvB,CAAC;AAAA,MACH,CAAC;AACD,UAAI,IAAI,WAAW,IAAK;AACxB,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AAAA,IACF;AAAA,IAEA,MAAM,iBAAiB,SAA+C;AACpE,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,8BAA8B,OAAO,EAAE;AACtE,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AAIA,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,oBACJ,QACuB;AACvB,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,sBAAsB;AAAA,QACnD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,QAAQ,OAAO,OAAO,CAAC;AAAA,MAChD,CAAC;AAGD,UAAI,IAAI,WAAW,OAAO,IAAI,WAAW,KAAK;AAC5C,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,gBACJ,QACgC;AAMhC,YAAM,OAAgC;AAAA,QACpC,cAAc,OAAO;AAAA,QACrB,QAAQ,OAAO;AAAA,QACf,MAAM,OAAO;AAAA,QACb,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,cAAc,OAAO;AAAA,MACvB;AACA,UAAI,OAAO,cAAc;AACvB,aAAK,cAAc,IAAI,OAAO;AAAA,MAChC;AACA,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,kBAAkB;AAAA,QAC/C,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,cAAc,OAAO,SAAS;AAAA,QAC/C;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AAAA,IAEA,MAAM,OAAO,QAA8C;AACzD,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,cAAc;AAAA,QAC3C,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA;AAAA;AAAA;AAAA,QAI9C,MAAM,KAAK,UAAU,UAAU,CAAC,CAAC;AAAA,MACnC,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,kBAAkB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,MAClE;AACA,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AAAA,EACF;AACF;","names":["body"]}