{"version":3,"sources":["../../src/direct/controller.ts"],"sourcesContent":["/**\n * Direct Data Controller — the server-side facade for the two-tab Data\n * Portability flow.\n *\n * @remarks\n * One controller owns an app's private key, source, scopes, app identity, and\n * payment flow. It exposes the three methods the builder guide documents:\n *\n * - {@link DirectDataController.createAccessRequest} — start an approval request.\n * - {@link DirectDataController.getAccessRequestStatus} — poll while the Vana tab is open.\n * - {@link DirectDataController.readApprovedData} — read from the Personal Server,\n *   handling 402 Payment Required.\n *\n * Access requests are created through the Vana Account access-request API; the\n * Personal Server read uses Web3Signed auth; and payment uses the DPv2 escrow\n * surface (`protocol/escrow`) — when a read returns `402`, the controller signs\n * a `GenericPayment` with the app key, settles it through the escrow gateway,\n * and retries.\n *\n * @category Direct\n * @module direct/controller\n */\n\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport type { Hex } from \"viem\";\nimport type { Web3SignedSignFn } from \"../auth/web3-signed-builder\";\nimport { parseScope } from \"../protocol/scopes\";\nimport { parseScopeEntry } from \"../protocol/scope-actions\";\nimport { createEscrowGatewayClient } from \"../protocol/escrow\";\nimport { CONTRACTS } from \"../generated/addresses\";\nimport {\n  createDefaultAccessRequestClient,\n  validateAccessRequestQuestions,\n  type FetchLike,\n} from \"./access-request-client\";\nimport {\n  getDirectDefaultNetwork,\n  getDirectEndpoints,\n  getDirectNetworkChainId,\n} from \"./endpoints\";\nimport {\n  AccessNotApprovedError,\n  DirectConfigError,\n  ScopeNotApprovedError,\n} from \"./errors\";\nimport {\n  type EscrowPaymentConfig,\n  type SignTypedDataFn,\n} from \"./escrow-payment\";\nimport {\n  readPersonalServerData,\n  type PersonalServerFetch,\n  type PersonalServerTransportRetryOptions,\n} from \"./personal-server-read\";\nimport type {\n  AccessRequest,\n  AccessRequestClient,\n  AccessRequestQuestion,\n  AccessRequestStatus,\n  AccessRequestStatusValue,\n  ApprovedDataResult,\n  AppIdentity,\n  DirectAppConfig,\n  DirectEnv,\n  DirectNetwork,\n  DirectPaymentResponseMetadata,\n  DirectServiceEndpoints,\n  ForegroundDelivery,\n  MultiScopeDataResult,\n} from \"./types\";\n\n/** Configuration for {@link createDirectDataController}. */\nexport interface DirectDataControllerConfig {\n  /** Target environment. Defaults to `\"production\"`. */\n  env?: DirectEnv;\n  /**\n   * Target Vana network for chain-aware defaults. Defaults to the selected\n   * environment's historical network (`mainnet` for production, `moksha` for\n   * dev). Use `network: \"moksha\"` with the default production env for\n   * production app/API URLs on testnet.\n   */\n  network?: DirectNetwork;\n  /**\n   * The app private key (`0x`-prefixed, 32 bytes). Server-side only — this key\n   * is the app's on-chain identity and is never exposed to the browser.\n   */\n  appPrivateKey?: string;\n  /**\n   * @deprecated Use {@link DirectDataControllerConfig.appPrivateKey}. Accepted as\n   * a backwards-compatible alias; if both are set, `appPrivateKey` wins.\n   */\n  builderPrivateKey?: string;\n  /** App identity advertised during approval. */\n  app: DirectAppConfig;\n  /** Data source key (e.g. `\"icloud_notes\"`). */\n  source: string;\n  /**\n   * Grant scope entries to request. At least one required.\n   *\n   * Each entry is `[operation:]scope` (see `parseScopeEntry`): a bare entry\n   * such as `\"icloud_notes.notes\"` requests read, and `\"write:coach.weekly\"`\n   * requests write. The entries are carried through to the access request\n   * verbatim and become the grant's `scopes`, so a request can mix both\n   * (`[\"oura.sleep\", \"coach.weekly\", \"write:coach.weekly\"]`).\n   *\n   * The scope part must be a concrete `{source}.{category}[.{subcategory}]`\n   * scope: this flow reads approved scopes back one by one, so wildcard\n   * patterns (`chatgpt.*`, `write:chatgpt.*`) are not accepted here for\n   * either operation.\n   */\n  scopes: string[];\n  /**\n   * Override the resolved service endpoints (partial). Useful for pointing at a\n   * non-standard deployment.\n   */\n  endpoints?: Partial<DirectServiceEndpoints>;\n  /**\n   * Client for the Vana Account access-request API. Defaults to a client against\n   * the resolved Vana Account endpoints; inject your own to point at a custom\n   * deployment or to supply a test double.\n   */\n  accessRequestClient?: AccessRequestClient;\n  /**\n   * Escrow settlement config used when a Personal Server read returns `402`.\n   *\n   * @remarks\n   * Wires the DPv2 escrow gateway (`protocol/escrow`). The controller supplies\n   * the EIP-712 `signTypedData` from the app key automatically.\n   *\n   * When omitted (or partially omitted), the SDK derives defaults from the\n   * per-network endpoints table and the contract registry:\n   * - `client` defaults to a gateway client at `endpoints.escrowGatewayUrl`\n   * - `escrowContract` defaults to `CONTRACTS.DataPortabilityEscrow.addresses[chainId]`\n   * - `chainId` defaults to the controller's resolved chain id\n   *\n   * Provide this field only to override a specific default.\n   */\n  escrow?: Partial<DirectEscrowConfig>;\n  /** `fetch` used by the default access-request client. Defaults to `globalThis.fetch`. */\n  fetchFn?: FetchLike;\n  /** `fetch` used for the Personal Server read. Defaults to `globalThis.fetch`. */\n  personalServerFetch?: PersonalServerFetch;\n  /**\n   * Transport-retry knobs for the Personal Server read\n   * ({@link PersonalServerTransportRetryOptions}). Defaults to 3 attempts with\n   * exponential backoff. Retries fire only when fetch throws (the browser-PS\n   * relay reconnect window), never on a received HTTP status, and never\n   * re-sign a payment.\n   */\n  personalServerTransportRetry?: PersonalServerTransportRetryOptions;\n}\n\n/**\n * Controller-level escrow config — the {@link EscrowPaymentConfig} minus the\n * `signTypedData` and `chainId` the controller injects itself.\n */\nexport interface DirectEscrowConfig extends Omit<\n  EscrowPaymentConfig,\n  \"signTypedData\" | \"chainId\"\n> {\n  /**\n   * Chain id for the EIP-712 domain. Defaults to the controller's environment\n   * (1480 for mainnet, 14800 for moksha).\n   */\n  chainId?: number;\n}\n\n/**\n * Server-side controller for the direct Data Portability flow.\n *\n * @typeParam T - Shape of the data returned by {@link DirectDataController.readApprovedData}.\n */\nexport interface DirectDataController {\n  /** The on-chain address of the app, derived from `appPrivateKey`. */\n  readonly appAddress: string;\n\n  /**\n   * The app's on-chain address — the address to fund and inspect in the Builder\n   * activity report. Equivalent to {@link DirectDataController.appAddress}.\n   *\n   * @returns The app's `0x`-prefixed address.\n   */\n  getAppAddress(): string;\n\n  /**\n   * The app's full identity: its configured id/name/homepage plus the derived\n   * on-chain address. Useful for telling builders which app address to fund or\n   * look up.\n   *\n   * @returns `{ id, name, homepageUrl, address }`.\n   */\n  getAppIdentity(): AppIdentity;\n\n  /**\n   * Create an access request the user can approve.\n   *\n   * @param input - The post-approval return URL and optional create retry key.\n   * @returns The request id, HTTPS approval URL, and — for a pending deep Direct\n   * request on mobile — an optional HTTPS `mobileContinuationUrl`.\n   */\n  createAccessRequest(input: {\n    returnUrl: string;\n    /** Optional foreground mobile delivery callback. */\n    foregroundDelivery?: ForegroundDelivery;\n    /**\n     * Derivative questions to carry on the request (1 to 4). Each question\n     * asks the user's Personal Server to compute its `derivedScope` from\n     * `sourceScopes` the app never reads; the derived scope must also appear\n     * in the controller's `scopes` as a bare read entry. Validated eagerly\n     * against the configured scopes before the request is sent. See\n     * {@link AccessRequestQuestion}.\n     */\n    questions?: AccessRequestQuestion[];\n    /**\n     * Stable retry key when the caller retries after an uncertain response.\n     * Each create without one gets its own generated key.\n     */\n    idempotencyKey?: string;\n  }): Promise<AccessRequest>;\n\n  /**\n   * Fetch the current status of an access request.\n   *\n   * @param requestId - The `dcr_*` id from {@link DirectDataController.createAccessRequest}.\n   * @returns `{ status, personalServerUrl?, grantId?, scope?, scopes? }`.\n   */\n  getAccessRequestStatus(requestId: string): Promise<AccessRequestStatus>;\n\n  /**\n   * Read the approved data from the user's Personal Server.\n   *\n   * @remarks\n   * Resolves the request to its grant + Personal Server and performs a Web3Signed\n   * read. Hides the `402 Payment Required` flow by default: if a read needs\n   * payment, it signs the Personal Server's payment challenge, retries with\n   * `X-PAYMENT`, and attaches shape-validated but unauthenticated\n   * {@link DirectPaymentResponseMetadata} under `payment` when the Personal\n   * Server returns it. After a successful read, the controller acknowledges\n   * the DCR so Vana Web can close/redirect the approval tab.\n   *\n   * A request can approve several scopes. This reads **one** of them — `scope`\n   * when given, otherwise the first approved scope. Use\n   * {@link DirectDataController.readAllApprovedData} to read them all.\n   *\n   * Acknowledging moves the DCR to `completed`, which is terminal and no longer\n   * read-ready. To read several scopes with your own loop, pass\n   * `acknowledge: false` on every call but the last.\n   *\n   * @param input - The `dcr_*` request id, the optional `scope` to read, and an\n   *   optional `acknowledge` flag (default `true`).\n   * @returns `{ scope, data, payment? }`.\n   * @throws {@link AccessNotApprovedError} if the request is not approved.\n   * @throws {@link ScopeNotApprovedError} if `scope` is not an approved scope.\n   * @throws {@link PaymentRequiredError} if payment is required but unsettled.\n   */\n  readApprovedData<T = unknown>(input: {\n    requestId: string;\n    scope?: string;\n    acknowledge?: boolean;\n  }): Promise<ApprovedDataResult<T>>;\n\n  /**\n   * Read every scope the user approved on a request.\n   *\n   * @remarks\n   * Reads the scopes in approval order, then acknowledges the DCR **once**,\n   * after the last read — acknowledging earlier would move the request to\n   * `completed` and make the remaining scopes unreadable.\n   *\n   * Each scope is a separate Personal Server read that settles its own\n   * `data_access` fee from escrow, so reading N scopes costs N times a\n   * single-scope read. The one-off registration fee is charged per grant, not\n   * per scope.\n   *\n   * A scope that fails does not abort the rest: successes land in `results` and\n   * failures in `errors`, because the fees for earlier scopes are already spent.\n   * If any scope fails the request is left unacknowledged, so the scopes that\n   * failed stay retryable — read them with `readApprovedData({ scope })` and\n   * acknowledge on the last one.\n   *\n   * @param input - The `dcr_*` request id to read.\n   * @returns `{ results, errors }`, both keyed by scope.\n   * @throws {@link AccessNotApprovedError} if the request is not approved.\n   */\n  readAllApprovedData<T = unknown>(input: {\n    requestId: string;\n  }): Promise<MultiScopeDataResult<T>>;\n}\n\nfunction isHexPrivateKey(value: string): value is Hex {\n  return /^0x[0-9a-fA-F]{64}$/.test(value);\n}\n\n// A DCR is read-ready only while the grant exists and the Personal Server is\n// still serving it: `approved` (durable PS) or `ready_for_read` (browser PS).\n// `completed` is terminal — the app already read and acknowledged, and the\n// browser PS may be gone — so it is deliberately excluded here.\nfunction isReadReadyStatus(status: AccessRequestStatusValue): boolean {\n  return status === \"approved\" || status === \"ready_for_read\";\n}\n\n/**\n * Create a {@link DirectDataController}.\n *\n * @param config - Controller configuration (env, key, app identity, source, scopes).\n * @returns A ready-to-use controller.\n * @throws {@link DirectConfigError} when the key is missing or malformed, when\n * `scopes` is empty, or when no escrow contract can be resolved.\n * @throws InvalidScopeEntryError when a `scopes` entry does not fit the\n * `[operation:]scope` grammar (an unknown operation prefix such as `delete:`).\n * @throws ZodError when the scope part of an entry is not a valid scope.\n */\nexport function createDirectDataController(\n  config: DirectDataControllerConfig,\n): DirectDataController {\n  // `appPrivateKey` is the documented field; `builderPrivateKey` is a\n  // deprecated alias kept for backwards compatibility.\n  const privateKey = config.appPrivateKey ?? config.builderPrivateKey;\n  if (!privateKey || !isHexPrivateKey(privateKey)) {\n    throw new DirectConfigError(\n      \"appPrivateKey must be a 0x-prefixed 32-byte hex string\",\n    );\n  }\n  if (!config.scopes || config.scopes.length === 0) {\n    throw new DirectConfigError(\"At least one scope is required\");\n  }\n  // Validate scopes eagerly so misconfiguration fails at construction. Each\n  // element is a grant scope entry (`[operation:]scope`), so the operation\n  // prefix is stripped first and only the scope part is checked against the\n  // scope grammar — `write:coach.weekly` is a valid write-grant request, and\n  // an unknown operation (`delete:x`) throws rather than being taken as read.\n  // The entries themselves are passed through to the access request verbatim,\n  // prefix included.\n  for (const entry of config.scopes) {\n    parseScope(parseScopeEntry(entry).scope);\n  }\n\n  const env: DirectEnv = config.env ?? \"production\";\n  const network: DirectNetwork = config.network ?? getDirectDefaultNetwork(env);\n  const defaultEndpoints = getDirectEndpoints(env);\n  const chainId = config.endpoints?.chainId ?? getDirectNetworkChainId(network);\n  const endpoints: DirectServiceEndpoints = {\n    ...defaultEndpoints,\n    ...config.endpoints,\n    chainId,\n  };\n\n  const account = privateKeyToAccount(privateKey as Hex);\n  const signMessage: Web3SignedSignFn = (message: string) =>\n    account.signMessage({ message });\n  // viem's account.signTypedData satisfies the structural SignTypedDataFn used\n  // by the escrow GenericPayment signer.\n  const signTypedData = account.signTypedData as unknown as SignTypedDataFn;\n  const accessRequestClient: AccessRequestClient =\n    config.accessRequestClient ??\n    createDefaultAccessRequestClient({\n      baseUrl: endpoints.accessRequestBaseUrl,\n      approvalBaseUrl: endpoints.approvalAppBaseUrl,\n      env,\n      fetchFn: config.fetchFn,\n      appAddress: account.address,\n      signMessage,\n    });\n\n  // Build the escrow payment config, defaulting from the per-network endpoints\n  // table and the contract registry when `config.escrow` is omitted or partial.\n  const escrowChainId = config.escrow?.chainId ?? chainId;\n  const defaultEscrowContract =\n    CONTRACTS.DataPortabilityEscrow.addresses[\n      escrowChainId as keyof typeof CONTRACTS.DataPortabilityEscrow.addresses\n    ] ?? undefined;\n  if (!config.escrow?.escrowContract && !defaultEscrowContract) {\n    throw new DirectConfigError(\n      `No DataPortabilityEscrow address found in the registry for chainId ${escrowChainId}. ` +\n        `Provide an explicit escrow.escrowContract in the controller config.`,\n    );\n  }\n  const escrow: EscrowPaymentConfig = {\n    client:\n      config.escrow?.client ??\n      createEscrowGatewayClient(endpoints.escrowGatewayUrl),\n    escrowContract:\n      config.escrow?.escrowContract ?? (defaultEscrowContract as `0x${string}`),\n    chainId: escrowChainId,\n    nonceSource: config.escrow?.nonceSource,\n    signTypedData,\n  };\n\n  return {\n    appAddress: account.address,\n\n    getAppAddress(): string {\n      return account.address;\n    },\n\n    getAppIdentity(): AppIdentity {\n      return {\n        id: config.app.id,\n        name: config.app.name,\n        homepageUrl: config.app.homepageUrl,\n        address: account.address,\n      };\n    },\n\n    async createAccessRequest(input): Promise<AccessRequest> {\n      // Fail fast even with an injected client: a malformed question would be\n      // rejected by the access-request service anyway, after a signed round\n      // trip.\n      if (input.questions !== undefined) {\n        validateAccessRequestQuestions(input.questions, config.scopes);\n      }\n      return accessRequestClient.createAccessRequest({\n        appAddress: account.address,\n        app: config.app,\n        source: config.source,\n        scopes: config.scopes,\n        returnUrl: input.returnUrl,\n        network,\n        ...(input.foregroundDelivery !== undefined\n          ? { foregroundDelivery: input.foregroundDelivery }\n          : {}),\n        ...(input.questions !== undefined\n          ? { questions: input.questions }\n          : {}),\n        ...(input.idempotencyKey !== undefined\n          ? { idempotencyKey: input.idempotencyKey }\n          : {}),\n      });\n    },\n\n    async getAccessRequestStatus(\n      requestId: string,\n    ): Promise<AccessRequestStatus> {\n      return accessRequestClient.getAccessRequestStatus(requestId);\n    },\n\n    async readApprovedData<T = unknown>(input: {\n      requestId: string;\n      scope?: string;\n      acknowledge?: boolean;\n    }): Promise<ApprovedDataResult<T>> {\n      const status = await requireReadReady(input.requestId);\n      const scope = resolveRequestedScope(status, input.scope);\n\n      const result = await readScope<T>(status, scope);\n      if (input.acknowledge !== false) {\n        await acknowledgeQuietly(input.requestId);\n      }\n      return result;\n    },\n\n    async readAllApprovedData<T = unknown>(input: {\n      requestId: string;\n    }): Promise<MultiScopeDataResult<T>> {\n      const status = await requireReadReady(input.requestId);\n      const scopes = approvedScopes(status);\n\n      const results: Record<string, ApprovedDataResult<T>> = {};\n      const errors: Record<string, Error> = {};\n      // Sequential, not parallel: each read settles its own escrow payment and\n      // the default nonce source is process-local, so concurrent reads would\n      // race on the payment nonce.\n      for (const scope of scopes) {\n        try {\n          results[scope] = await readScope<T>(status, scope);\n        } catch (error) {\n          errors[scope] =\n            error instanceof Error ? error : new Error(String(error));\n        }\n      }\n\n      // Acknowledge only after the last read, and only if every scope read —\n      // acking moves the DCR to `completed`, which is terminal and no longer\n      // read-ready, so acking on a partial failure would make the scope that\n      // failed impossible to retry.\n      if (Object.keys(errors).length === 0) {\n        await acknowledgeQuietly(input.requestId);\n      }\n\n      return { results, errors };\n    },\n  };\n\n  async function requireReadReady(\n    requestId: string,\n  ): Promise<AccessRequestStatus> {\n    const status = await accessRequestClient.getAccessRequestStatus(requestId);\n    // `scope` and `scopes` are both optional on the public status type, and a\n    // client may return either one — require at least one approved scope rather\n    // than the singular field specifically.\n    if (\n      !isReadReadyStatus(status.status) ||\n      !status.personalServerUrl ||\n      !status.grantId ||\n      approvedScopes(status).length === 0\n    ) {\n      throw new AccessNotApprovedError(\n        \"Request is not approved or is missing grantId/scope/personalServerUrl\",\n        {\n          requestId,\n          status: status.status,\n          hasPersonalServerUrl: Boolean(status.personalServerUrl),\n          hasGrantId: Boolean(status.grantId),\n          hasScope: approvedScopes(status).length > 0,\n        },\n      );\n    }\n    return status;\n  }\n\n  /** Approved scopes in approval order, falling back to the single `scope`. */\n  function approvedScopes(status: AccessRequestStatus): string[] {\n    if (status.scopes && status.scopes.length > 0) return status.scopes;\n    return status.scope ? [status.scope] : [];\n  }\n\n  /**\n   * Resolve which scope to read. Rejects an unapproved scope up front so it\n   * never reaches the Personal Server and never settles a fee.\n   */\n  function resolveRequestedScope(\n    status: AccessRequestStatus,\n    requested?: string,\n  ): string {\n    const scopes = approvedScopes(status);\n    if (requested === undefined) return scopes[0];\n    if (!scopes.includes(requested)) {\n      throw new ScopeNotApprovedError(\n        `Scope \"${requested}\" is not approved on this request`,\n        { requestedScope: requested, approvedScopes: scopes },\n      );\n    }\n    return requested;\n  }\n\n  async function readScope<T>(\n    status: AccessRequestStatus,\n    scope: string,\n  ): Promise<ApprovedDataResult<T>> {\n    const result = await readPersonalServerData({\n      personalServerUrl: status.personalServerUrl as string,\n      scope,\n      grantId: status.grantId as string,\n      payerAddress: account.address,\n      signMessage,\n      escrow,\n      fetchFn: config.personalServerFetch,\n      transportRetry: config.personalServerTransportRetry,\n    });\n    return { scope, data: result.data as T, payment: result.payment };\n  }\n\n  async function acknowledgeQuietly(requestId: string): Promise<void> {\n    try {\n      await accessRequestClient.acknowledgeRead?.(requestId);\n    } catch {\n      // The read already succeeded; ack only drives Vana Web completion UX.\n    }\n  }\n}\n"],"mappings":"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","names":[]}