@opendatalabs/vana-sdk 3.22.0 → 3.23.0-pr.211.1da7c1b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crypto/envelope/job.cjs +313 -0
- package/dist/crypto/envelope/job.cjs.map +1 -0
- package/dist/crypto/envelope/job.d.ts +122 -0
- package/dist/crypto/envelope/job.js +291 -0
- package/dist/crypto/envelope/job.js.map +1 -0
- package/dist/direct/access-request-client.cjs +4 -0
- package/dist/direct/access-request-client.cjs.map +1 -1
- package/dist/direct/access-request-client.js +4 -0
- package/dist/direct/access-request-client.js.map +1 -1
- package/dist/direct/connect-flow.cjs +43 -1
- package/dist/direct/connect-flow.cjs.map +1 -1
- package/dist/direct/connect-flow.d.ts +12 -0
- package/dist/direct/connect-flow.js +43 -1
- package/dist/direct/connect-flow.js.map +1 -1
- package/dist/direct/types.cjs.map +1 -1
- package/dist/direct/types.d.ts +7 -0
- package/dist/direct/types.js.map +1 -1
- package/dist/direct/use-direct-vana-connect.cjs +2 -1
- package/dist/direct/use-direct-vana-connect.cjs.map +1 -1
- package/dist/direct/use-direct-vana-connect.d.ts +3 -1
- package/dist/direct/use-direct-vana-connect.js +2 -1
- package/dist/direct/use-direct-vana-connect.js.map +1 -1
- package/dist/errors.cjs +84 -0
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +133 -0
- package/dist/errors.js +73 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.browser.d.ts +3 -0
- package/dist/index.browser.js +589 -24
- package/dist/index.browser.js.map +4 -4
- package/dist/index.node.cjs +1217 -111
- package/dist/index.node.cjs.map +4 -4
- package/dist/index.node.d.ts +4 -0
- package/dist/index.node.js +1181 -101
- package/dist/index.node.js.map +4 -4
- package/dist/protocol/identity.cjs +219 -0
- package/dist/protocol/identity.cjs.map +1 -0
- package/dist/protocol/identity.d.ts +193 -0
- package/dist/protocol/identity.js +183 -0
- package/dist/protocol/identity.js.map +1 -0
- package/dist/protocol/identity.test.d.ts +1 -0
- package/dist/protocol/identity.vector.test.d.ts +1 -0
- package/dist/protocol/jobs-client.cjs +540 -0
- package/dist/protocol/jobs-client.cjs.map +1 -0
- package/dist/protocol/jobs-client.d.ts +169 -0
- package/dist/protocol/jobs-client.js +547 -0
- package/dist/protocol/jobs-client.js.map +1 -0
- package/dist/protocol/jobs-client.test.d.ts +1 -0
- package/dist/protocol/jobs.cjs +64 -0
- package/dist/protocol/jobs.cjs.map +1 -0
- package/dist/protocol/jobs.d.ts +192 -0
- package/dist/protocol/jobs.js +31 -0
- package/dist/protocol/jobs.js.map +1 -0
- package/dist/protocol/jobs.test.d.ts +1 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js.map +1 -1
- package/package.json +7 -1
package/dist/direct/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/direct/types.ts"],"sourcesContent":["import type { EscrowAccessRecord } from \"../protocol/escrow\";\nimport type { ProtocolNetwork } from \"../protocol/networks\";\n\n/**\n * Shared types for the Direct Data Controller and the browser connect helper.\n *\n * @remarks\n * These types describe the \"two-tab\" Data Portability flow documented in the\n * builder guide: a backend controller creates an access request, the browser\n * opens Vana for user approval, and the backend reads the approved data from\n * the user's Personal Server (handling 402 Payment Required).\n *\n * @category Direct\n * @module direct/types\n */\n\n/**\n * Target environment for a {@link DirectDataController}.\n *\n * - `\"production\"` — Vana mainnet stack (default service URLs).\n * - `\"dev\"` — Vana internal dev stack. Use only when testing against\n * Vana's dev infrastructure.\n */\nexport type DirectEnv = \"dev\" | \"production\";\n\n/**\n * Vana network used for chain-aware Direct defaults.\n *\n * - `\"mainnet\"` — Vana mainnet (`chainId` 1480).\n * - `\"moksha\"` — Moksha testnet (`chainId` 14800).\n */\nexport type DirectNetwork = ProtocolNetwork;\n\n/**\n * App identity advertised to users during approval and attributed in Builder\n * League activity reports.\n */\nexport interface DirectAppConfig {\n /** Stable, human-readable app id (e.g. `\"notes-lens\"`). */\n id: string;\n /** Display name shown to the user in the Vana approval UI. */\n name: string;\n /** Public homepage URL for the app. */\n homepageUrl: string;\n}\n\n/**\n * Resolved app identity: the configured {@link DirectAppConfig} plus the app's\n * derived on-chain address (the address to fund and inspect).\n */\nexport interface AppIdentity extends DirectAppConfig {\n /** The app's `0x`-prefixed on-chain address (derived from `appPrivateKey`). */\n address: string;\n}\n\n/** One-time HTTPS callback used to deliver a foreground mobile Direct read. */\nexport interface ForegroundDelivery {\n /** Fixed, same-origin consumer callback URL. */\n url: string;\n /** High-entropy bearer capability, generated and retained by the consumer. */\n token: string;\n}\n\n/**\n * One derivative question carried on an access request.\n *\n * @remarks\n * A question asks the user's Personal Server to compute an answer scope\n * (`derivedScope`) from source scopes the app never reads. On approval, the\n * Vana app registers the question on the Personal Server as the owner and the\n * grant covers only the derived scope, so the raw sources stay private to the\n * user. The SDK validates each question before the create request is signed\n * (see `validateAccessRequestQuestions`); the access-request service remains\n * authoritative and re-validates server-side.\n */\nexport interface AccessRequestQuestion {\n /**\n * Concrete scope the computed answer is written to and read from (no\n * wildcards, no operation prefix). It must also appear verbatim in the\n * request `scopes` as a bare read entry, and its first dot-segment must\n * differ from the first dot-segment of every entry in\n * {@link AccessRequestQuestion.sourceScopes}.\n */\n derivedScope: string;\n /**\n * Concrete scopes the answer is computed from: 1 to 16 entries, no\n * duplicates, none equal to {@link AccessRequestQuestion.derivedScope}.\n * These scopes are never granted to the app.\n */\n sourceScopes: string[];\n /**\n * Natural-language question the Personal Server answers from the source\n * scopes. Must be 1 to 4000 characters after trimming.\n */\n question: string;\n /**\n * When the Personal Server recomputes the answer. `\"snapshot\"` computes\n * once at registration; `\"on-change\"` also recomputes when a source scope\n * changes. When omitted, the server-side default applies.\n */\n recompute?: \"snapshot\" | \"on-change\";\n}\n\n/**\n * Resolved service URLs and chain id for a given {@link DirectEnv}.\n *\n * @remarks\n * Centralizes the per-environment base URLs the controller talks to. Each can\n * be overridden via {@link DirectDataControllerConfig.endpoints} when pointing\n * at a non-standard deployment.\n */\nexport interface DirectServiceEndpoints {\n /** Vana chain id for this environment (1480 mainnet, 14800 moksha). */\n chainId: number;\n /** Base URL of the Vana Account access-request API that issues `dcr_*` ids. */\n accessRequestBaseUrl: string;\n /** Base URL users are sent to for approval (the Vana app). */\n approvalAppBaseUrl: string;\n /** Base URL of the DP RPC escrow gateway used to settle `402 Payment Required`. */\n escrowGatewayUrl: string;\n}\n\n/** Result of {@link DirectDataController.createAccessRequest}. */\nexport interface AccessRequest {\n /** Opaque request id (e.g. `\"dcr_123\"`). */\n requestId: string;\n /** URL the browser opens so the user can approve the requested scopes. */\n approvalUrl: string;\n /** On-chain address of the (registered or reused) app. */\n appAddress: string;\n /** Protocol network echoed by the access-request service. */\n network?: DirectNetwork;\n /** Authoritative ISO-8601 expiry for the access request. */\n expiresAt?: string;\n /**\n * HTTPS continuation URL for a deep Direct request on a mobile browser.\n *\n * @remarks\n * Present only for a server-classified deep Direct DCR while it remains\n * pending, and only when Mobile continuation is enabled. It is an ordinary\n * `https://open[-dev].vana.org/continue#<ticket>` link the mobile UI renders\n * as a primary \"Open Vana\" tap — iOS Universal Links / Android App Links\n * deliver it to Vana Mobile, and its web fallback recovers an absent app. The\n * SDK never launches it automatically and owns no persistence.\n */\n mobileContinuationUrl?: string;\n}\n\n/** Canonical mobile continuation link host per {@link DirectEnv}. */\nconst MOBILE_CONTINUATION_HOSTS: Record<DirectEnv, string> = {\n production: \"open.vana.org\",\n dev: \"open-dev.vana.org\",\n};\n\n/** URL-fragment-safe opaque ticket: no separators, query, or scheme chars. */\nconst MOBILE_CONTINUATION_TICKET = /^[A-Za-z0-9._~-]+$/;\n\n/**\n * @internal Strictly validate a mobile HTTPS continuation URL at the SDK\n * boundary.\n *\n * @remarks\n * Accepts only `https://open[-dev].vana.org/continue#<ticket>` with exactly one\n * well-formed opaque fragment ticket and no user info, port, or query. When\n * `env` is supplied only that environment's host is allowed; otherwise both\n * canonical hosts are accepted for structural (defense-in-depth) validation.\n *\n * @param value - The candidate URL from a create or status response.\n * @param env - Optional environment to pin the allowed host to.\n * @returns The canonical URL string, or `undefined` when it fails validation.\n */\nexport function normalizeMobileContinuationUrl(\n value: unknown,\n env?: DirectEnv,\n): string | undefined {\n if (typeof value !== \"string\" || value.length === 0) return undefined;\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return undefined;\n }\n if (url.protocol !== \"https:\") return undefined;\n const allowedHosts = env\n ? [MOBILE_CONTINUATION_HOSTS[env]]\n : Object.values(MOBILE_CONTINUATION_HOSTS);\n if (!allowedHosts.includes(url.hostname)) return undefined;\n if (url.pathname !== \"/continue\") return undefined;\n if (url.username !== \"\" || url.password !== \"\") return undefined;\n if (url.port !== \"\") return undefined;\n if (url.search !== \"\") return undefined;\n const ticket = url.hash.startsWith(\"#\") ? url.hash.slice(1) : \"\";\n if (!MOBILE_CONTINUATION_TICKET.test(ticket)) return undefined;\n return url.toString();\n}\n\n/**\n * Lifecycle status of an access request.\n *\n * @remarks\n * - `\"pending\"` — created, awaiting user approval.\n * - `\"approved\"` / `\"ready_for_read\"` — the grant exists and the Personal\n * Server is reachable; the data is read-ready (see {@link DirectDataController.readApprovedData}).\n * - `\"completed\"` — the app has already read the data and acknowledged it, so\n * the DCR is terminal. A `\"completed\"` request is **not** read-ready — the\n * browser Personal Server may no longer be serving it.\n * - `\"denied\"` / `\"expired\"` — terminal, no data was delivered.\n */\nexport type AccessRequestStatusValue =\n | \"pending\"\n | \"approved\"\n | \"ready_for_read\"\n | \"completed\"\n | \"denied\"\n | \"expired\";\n\n/** Result of {@link DirectDataController.getAccessRequestStatus}. */\nexport interface AccessRequestStatus {\n /** Current lifecycle status of the request. */\n status: AccessRequestStatusValue;\n /** Personal Server base URL — present once data is ready to read. */\n personalServerUrl?: string;\n /** Grant id covering the approved scope — present once data is ready to read. */\n grantId?: string;\n /**\n * The first approved scope — present once data is ready to read.\n *\n * @remarks\n * Kept for backwards compatibility. A request can approve many scopes; read\n * {@link AccessRequestStatus.scopes} to see all of them.\n */\n scope?: string;\n /**\n * Fresh HTTPS mobile continuation URL, returned only while the deep Direct\n * DCR is still pending. Its embedded ticket may rotate between polls.\n */\n mobileContinuationUrl?: string;\n /**\n * Every scope the user approved on this request — present once data is ready\n * to read.\n *\n * @remarks\n * A grant is keyed by `(user, app)` and carries a list of scopes, so a single\n * approval can cover several. Against an older Vana Account deployment that\n * only returns `scope`, this falls back to `[scope]`.\n */\n scopes?: string[];\n}\n\n/** Result of {@link DirectDataController.readApprovedData}. */\nexport interface ApprovedDataResult<T = unknown> {\n /** The scope the data was read for. */\n scope: string;\n /** The decoded payload returned by the Personal Server. */\n data: T;\n /**\n * Shape-validated but unauthenticated payment metadata echoed by the\n * Personal Server. Use for display/debugging, not accounting proof.\n */\n payment?: DirectPaymentResponseMetadata;\n}\n\n/**\n * Result of {@link DirectDataController.readApprovedData} across every approved\n * scope.\n *\n * @remarks\n * Successes and failures are reported side by side rather than as a thrown\n * error, because each scope read settles its own fee: throwing on the third\n * scope would discard data the app has already paid for. Check `errors` before\n * treating the read as complete.\n */\nexport interface MultiScopeDataResult<T = unknown> {\n /** Scopes that read successfully, keyed by scope. */\n results: Record<string, ApprovedDataResult<T>>;\n /** Scopes that failed, keyed by scope. Empty when every scope read. */\n errors: Record<string, Error>;\n}\n\n/**\n * Client for the Vana Account access-request API — the service that turns a\n * registered app + scopes into a `dcr_*` id and approval URL.\n *\n * @remarks\n * The controller uses a default client against the Vana Account endpoints. You\n * can inject your own implementation to point at a custom deployment or to\n * supply a test double.\n */\nexport interface AccessRequestClient {\n /**\n * Create an access request for the given app + scopes.\n *\n * @param input - App identity, source, scopes, network, and the post-approval return URL.\n * @returns The created {@link AccessRequest}.\n */\n createAccessRequest(input: {\n appAddress: string;\n app: DirectAppConfig;\n source: string;\n scopes: string[];\n returnUrl: string;\n /** Vana protocol network for this request (`\"mainnet\"` or `\"moksha\"`). */\n network: DirectNetwork;\n /** Optional foreground mobile delivery callback. */\n foregroundDelivery?: ForegroundDelivery;\n /**\n * Derivative questions to carry on the request (1 to 4). When present,\n * the array is validated client-side and serialized into the signed\n * create body verbatim. See {@link AccessRequestQuestion}.\n */\n questions?: AccessRequestQuestion[];\n /**\n * Optional retry key. The default client generates a fresh key per call\n * when omitted; pass a stable key to retry a create whose response was\n * lost without risking a duplicate DCR.\n */\n idempotencyKey?: string;\n }): Promise<AccessRequest>;\n\n /**\n * Fetch the current status of a previously created access request.\n *\n * @param requestId - The `dcr_*` id returned by {@link AccessRequestClient.createAccessRequest}.\n * @returns The current {@link AccessRequestStatus}.\n */\n getAccessRequestStatus(requestId: string): Promise<AccessRequestStatus>;\n\n /**\n * Acknowledge that the app successfully read the approved data.\n *\n * @remarks\n * Direct Vana Web DCRs remain in `ready_for_read` while the browser Personal\n * Server is serving the app. After a successful Personal Server read, the\n * controller calls this hook so Vana Web can mark the request completed and\n * close/redirect the approval tab.\n *\n * Optional so injected clients from older SDK integrations keep compiling;\n * the default HTTP client implements it.\n */\n acknowledgeRead?(requestId: string): Promise<void>;\n}\n\n/**\n * Op-type vocabulary used by the DPv2 escrow payment surface.\n *\n * @remarks\n * These are the operations the gateway prices and settles via\n * `POST /v1/escrow/pay` (`opType` field of the `GenericPayment` message). A\n * direct data read settles the {@link DirectOpType.DataAccess} op for the\n * approved grant; the other op types are listed here for completeness and to\n * give builders a typed vocabulary when inspecting fee breakdowns.\n *\n * GenericPayment uses `\"grant\"` for legacy grant lifecycle payments and\n * `\"data_access\"` for standalone receipt-bound reads.\n */\nexport const DirectOpType = {\n GrantRegistration: \"grant_registration\",\n DataAccess: \"data_access\",\n DataRegistration: \"data_registration\",\n ServerRegistration: \"server_registration\",\n BuilderRegistration: \"builder_registration\",\n} as const;\n\n/** A direct-flow op type (see {@link DirectOpType}). */\nexport type DirectOpTypeValue =\n (typeof DirectOpType)[keyof typeof DirectOpType];\n\n/**\n * What a Personal Server `402 Payment Required` tells the controller is owed for\n * a data read.\n *\n * @remarks\n * The PS read 402 body identifies the challenged operation and amount/asset.\n * The controller settles it via the DPv2 escrow gateway (`/v1/escrow/pay`). The\n * full unmodified body is preserved under\n * {@link PersonalServerPaymentRequired.raw}.\n */\nexport interface PersonalServerPaymentRequired {\n /** Grant id authorizing the Personal Server read. */\n grantId: string;\n /** X402 network advertised by the Personal Server challenge. */\n network?: string;\n /** Payment nonce requested by the 402 challenge. */\n paymentNonce?: string;\n /** Data-access receipt carrying a signature for the gateway to verify. */\n accessRecord?: EscrowAccessRecord;\n /** Asset address owed (zero address = native VANA). */\n asset: string;\n /** Amount owed, as a decimal base-unit string (preserves uint256 precision). */\n amount: string;\n /** The full, unmodified 402 response body. */\n raw: unknown;\n}\n\n/** A validated legacy grant payment challenge. */\nexport interface PersonalServerGrantPaymentOperation extends PersonalServerPaymentRequired {\n /** Escrow operation discriminator. */\n opType: \"grant\";\n /** Grant id settled by the escrow payment. */\n opId: string;\n}\n\n/** A validated receipt-bound data-access payment challenge. */\nexport interface PersonalServerDataAccessPaymentOperation extends PersonalServerPaymentRequired {\n /** Escrow operation discriminator. */\n opType: \"data_access\";\n /** Access-record id settled by the escrow payment. */\n opId: string;\n /** Complete receipt whose signature is verified later by the gateway. */\n accessRecord: EscrowAccessRecord;\n /** Positive uint256 nonce supplied by the Personal Server challenge. */\n paymentNonce: string;\n}\n\n/**\n * A Personal Server payment challenge whose escrow operation has been\n * validated.\n *\n * @remarks\n * Validation here is structural and binds operation ids to their receipt. It\n * does not cryptographically verify the receipt signature; the Personal\n * Server and Data Gateway perform that verification.\n */\nexport type PersonalServerPaymentOperation =\n | PersonalServerGrantPaymentOperation\n | PersonalServerDataAccessPaymentOperation;\n\n/** Shape-validated payment response returned directly by the escrow gateway. */\nexport interface DirectPaymentReceipt {\n /** Op type settled (the gateway `opType`, e.g. `\"grant\"`). */\n opType: string;\n /** Op id settled (a grant id or access-record id). */\n opId: string;\n /** Asset paid in (zero address = native VANA). */\n asset: string;\n /** Total amount paid, as a decimal base-unit string. */\n amount: string;\n /** Payment nonce used for this settlement. */\n paymentNonce: string;\n /** Fee breakdown reported by the gateway (registration vs data-access fee). */\n breakdown: DirectFeeBreakdown;\n /** ISO timestamp the gateway recorded the payment. */\n paidAt: string;\n}\n\n/**\n * Untrusted payment response metadata echoed by a Personal Server.\n *\n * @remarks\n * The SDK validates every field before exposing this shape, but the response\n * header is not signed by the gateway. Use it for display and debugging only,\n * never as accounting proof that a payment occurred.\n */\nexport type DirectPaymentResponseMetadata = DirectPaymentReceipt;\n\n/**\n * Per-op fee breakdown reported by the gateway.\n *\n * @remarks\n * Mirrors the escrow {@link PaymentBreakdown}: a one-time registration fee plus\n * the per-read data-access fee, and whether this settlement covered the\n * registration fee.\n */\nexport interface DirectFeeBreakdown {\n /** One-time registration fee for the op, as a decimal base-unit string. */\n registrationFee: string;\n /** Per-read data-access fee, as a decimal base-unit string. */\n dataAccessFee: string;\n /** True when this settlement paid the registration fee. */\n registrationPaid: boolean;\n}\n"],"mappings":"AAqJA,MAAM,4BAAuD;AAAA,EAC3D,YAAY;AAAA,EACZ,KAAK;AACP;AAGA,MAAM,6BAA6B;AAgB5B,SAAS,+BACd,OACA,KACoB;AACpB,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,EAAG,QAAO;AAC5D,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,KAAK;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,IAAI,aAAa,SAAU,QAAO;AACtC,QAAM,eAAe,MACjB,CAAC,0BAA0B,GAAG,CAAC,IAC/B,OAAO,OAAO,yBAAyB;AAC3C,MAAI,CAAC,aAAa,SAAS,IAAI,QAAQ,EAAG,QAAO;AACjD,MAAI,IAAI,aAAa,YAAa,QAAO;AACzC,MAAI,IAAI,aAAa,MAAM,IAAI,aAAa,GAAI,QAAO;AACvD,MAAI,IAAI,SAAS,GAAI,QAAO;AAC5B,MAAI,IAAI,WAAW,GAAI,QAAO;AAC9B,QAAM,SAAS,IAAI,KAAK,WAAW,GAAG,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI;AAC9D,MAAI,CAAC,2BAA2B,KAAK,MAAM,EAAG,QAAO;AACrD,SAAO,IAAI,SAAS;AACtB;AAiKO,MAAM,eAAe;AAAA,EAC1B,mBAAmB;AAAA,EACnB,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,qBAAqB;AACvB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/direct/types.ts"],"sourcesContent":["import type { EscrowAccessRecord } from \"../protocol/escrow\";\nimport type { ProtocolNetwork } from \"../protocol/networks\";\n\n/**\n * Shared types for the Direct Data Controller and the browser connect helper.\n *\n * @remarks\n * These types describe the \"two-tab\" Data Portability flow documented in the\n * builder guide: a backend controller creates an access request, the browser\n * opens Vana for user approval, and the backend reads the approved data from\n * the user's Personal Server (handling 402 Payment Required).\n *\n * @category Direct\n * @module direct/types\n */\n\n/**\n * Target environment for a {@link DirectDataController}.\n *\n * - `\"production\"` — Vana mainnet stack (default service URLs).\n * - `\"dev\"` — Vana internal dev stack. Use only when testing against\n * Vana's dev infrastructure.\n */\nexport type DirectEnv = \"dev\" | \"production\";\n\n/**\n * Vana network used for chain-aware Direct defaults.\n *\n * - `\"mainnet\"` — Vana mainnet (`chainId` 1480).\n * - `\"moksha\"` — Moksha testnet (`chainId` 14800).\n */\nexport type DirectNetwork = ProtocolNetwork;\n\n/**\n * App identity advertised to users during approval and attributed in Builder\n * League activity reports.\n */\nexport interface DirectAppConfig {\n /** Stable, human-readable app id (e.g. `\"notes-lens\"`). */\n id: string;\n /** Display name shown to the user in the Vana approval UI. */\n name: string;\n /** Public homepage URL for the app. */\n homepageUrl: string;\n}\n\n/**\n * Resolved app identity: the configured {@link DirectAppConfig} plus the app's\n * derived on-chain address (the address to fund and inspect).\n */\nexport interface AppIdentity extends DirectAppConfig {\n /** The app's `0x`-prefixed on-chain address (derived from `appPrivateKey`). */\n address: string;\n}\n\n/** One-time HTTPS callback used to deliver a foreground mobile Direct read. */\nexport interface ForegroundDelivery {\n /** Fixed, same-origin consumer callback URL. */\n url: string;\n /** High-entropy bearer capability, generated and retained by the consumer. */\n token: string;\n}\n\n/**\n * One derivative question carried on an access request.\n *\n * @remarks\n * A question asks the user's Personal Server to compute an answer scope\n * (`derivedScope`) from source scopes the app never reads. On approval, the\n * Vana app registers the question on the Personal Server as the owner and the\n * grant covers only the derived scope, so the raw sources stay private to the\n * user. The SDK validates each question before the create request is signed\n * (see `validateAccessRequestQuestions`); the access-request service remains\n * authoritative and re-validates server-side.\n */\nexport interface AccessRequestQuestion {\n /**\n * Concrete scope the computed answer is written to and read from (no\n * wildcards, no operation prefix). It must also appear verbatim in the\n * request `scopes` as a bare read entry, and its first dot-segment must\n * differ from the first dot-segment of every entry in\n * {@link AccessRequestQuestion.sourceScopes}.\n */\n derivedScope: string;\n /**\n * Concrete scopes the answer is computed from: 1 to 16 entries, no\n * duplicates, none equal to {@link AccessRequestQuestion.derivedScope}.\n * These scopes are never granted to the app.\n */\n sourceScopes: string[];\n /**\n * Natural-language question the Personal Server answers from the source\n * scopes. Must be 1 to 4000 characters after trimming.\n */\n question: string;\n /**\n * When the Personal Server recomputes the answer. `\"snapshot\"` computes\n * once at registration; `\"on-change\"` also recomputes when a source scope\n * changes. When omitted, the server-side default applies.\n */\n recompute?: \"snapshot\" | \"on-change\";\n}\n\n/**\n * Resolved service URLs and chain id for a given {@link DirectEnv}.\n *\n * @remarks\n * Centralizes the per-environment base URLs the controller talks to. Each can\n * be overridden via {@link DirectDataControllerConfig.endpoints} when pointing\n * at a non-standard deployment.\n */\nexport interface DirectServiceEndpoints {\n /** Vana chain id for this environment (1480 mainnet, 14800 moksha). */\n chainId: number;\n /** Base URL of the Vana Account access-request API that issues `dcr_*` ids. */\n accessRequestBaseUrl: string;\n /** Base URL users are sent to for approval (the Vana app). */\n approvalAppBaseUrl: string;\n /** Base URL of the DP RPC escrow gateway used to settle `402 Payment Required`. */\n escrowGatewayUrl: string;\n}\n\n/** Result of {@link DirectDataController.createAccessRequest}. */\nexport interface AccessRequest {\n /** Opaque request id (e.g. `\"dcr_123\"`). */\n requestId: string;\n /** URL the browser opens so the user can approve the requested scopes. */\n approvalUrl: string;\n /** On-chain address of the (registered or reused) app. */\n appAddress: string;\n /** Protocol network echoed by the access-request service. */\n network?: DirectNetwork;\n /** Authoritative ISO-8601 expiry for the access request. */\n expiresAt?: string;\n /**\n * HTTPS continuation URL for a deep Direct request on a mobile browser.\n *\n * @remarks\n * Present only for a server-classified deep Direct DCR while it remains\n * pending, and only when Mobile continuation is enabled. It is an ordinary\n * `https://open[-dev].vana.org/continue#<ticket>` link the mobile UI renders\n * as a primary \"Open Vana\" tap — iOS Universal Links / Android App Links\n * deliver it to Vana Mobile, and its web fallback recovers an absent app. The\n * SDK never launches it automatically and owns no persistence.\n */\n mobileContinuationUrl?: string;\n}\n\n/** Canonical mobile continuation link host per {@link DirectEnv}. */\nconst MOBILE_CONTINUATION_HOSTS: Record<DirectEnv, string> = {\n production: \"open.vana.org\",\n dev: \"open-dev.vana.org\",\n};\n\n/** URL-fragment-safe opaque ticket: no separators, query, or scheme chars. */\nconst MOBILE_CONTINUATION_TICKET = /^[A-Za-z0-9._~-]+$/;\n\n/**\n * @internal Strictly validate a mobile HTTPS continuation URL at the SDK\n * boundary.\n *\n * @remarks\n * Accepts only `https://open[-dev].vana.org/continue#<ticket>` with exactly one\n * well-formed opaque fragment ticket and no user info, port, or query. When\n * `env` is supplied only that environment's host is allowed; otherwise both\n * canonical hosts are accepted for structural (defense-in-depth) validation.\n *\n * @param value - The candidate URL from a create or status response.\n * @param env - Optional environment to pin the allowed host to.\n * @returns The canonical URL string, or `undefined` when it fails validation.\n */\nexport function normalizeMobileContinuationUrl(\n value: unknown,\n env?: DirectEnv,\n): string | undefined {\n if (typeof value !== \"string\" || value.length === 0) return undefined;\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return undefined;\n }\n if (url.protocol !== \"https:\") return undefined;\n const allowedHosts = env\n ? [MOBILE_CONTINUATION_HOSTS[env]]\n : Object.values(MOBILE_CONTINUATION_HOSTS);\n if (!allowedHosts.includes(url.hostname)) return undefined;\n if (url.pathname !== \"/continue\") return undefined;\n if (url.username !== \"\" || url.password !== \"\") return undefined;\n if (url.port !== \"\") return undefined;\n if (url.search !== \"\") return undefined;\n const ticket = url.hash.startsWith(\"#\") ? url.hash.slice(1) : \"\";\n if (!MOBILE_CONTINUATION_TICKET.test(ticket)) return undefined;\n return url.toString();\n}\n\n/**\n * Lifecycle status of an access request.\n *\n * @remarks\n * - `\"pending\"` — created, awaiting user approval.\n * - `\"approved\"` / `\"ready_for_read\"` — the grant exists and the Personal\n * Server is reachable; the data is read-ready (see {@link DirectDataController.readApprovedData}).\n * - `\"completed\"` — the app has already read the data and acknowledged it, so\n * the DCR is terminal. A `\"completed\"` request is **not** read-ready — the\n * browser Personal Server may no longer be serving it.\n * - `\"denied\"` / `\"expired\"` — terminal, no data was delivered.\n */\nexport type AccessRequestStatusValue =\n | \"pending\"\n | \"approved\"\n | \"ready_for_read\"\n | \"completed\"\n | \"denied\"\n | \"expired\";\n\n/** Delivery path reported once an access request is ready. */\nexport type AccessRequestDelivery = \"enclave\" | \"personal_server\";\n\n/** Result of {@link DirectDataController.getAccessRequestStatus}. */\nexport interface AccessRequestStatus {\n /** Current lifecycle status of the request. */\n status: AccessRequestStatusValue;\n /**\n * Present once ready. `\"enclave\"` reads through the Gateway jobs API\n * (`protocol/jobs` client), with no `personalServerUrl`.\n */\n delivery?: AccessRequestDelivery;\n /** Personal Server base URL — present once data is ready to read. */\n personalServerUrl?: string;\n /** Grant id covering the approved scope — present once data is ready to read. */\n grantId?: string;\n /**\n * The first approved scope — present once data is ready to read.\n *\n * @remarks\n * Kept for backwards compatibility. A request can approve many scopes; read\n * {@link AccessRequestStatus.scopes} to see all of them.\n */\n scope?: string;\n /**\n * Fresh HTTPS mobile continuation URL, returned only while the deep Direct\n * DCR is still pending. Its embedded ticket may rotate between polls.\n */\n mobileContinuationUrl?: string;\n /**\n * Every scope the user approved on this request — present once data is ready\n * to read.\n *\n * @remarks\n * A grant is keyed by `(user, app)` and carries a list of scopes, so a single\n * approval can cover several. Against an older Vana Account deployment that\n * only returns `scope`, this falls back to `[scope]`.\n */\n scopes?: string[];\n}\n\n/** Result of {@link DirectDataController.readApprovedData}. */\nexport interface ApprovedDataResult<T = unknown> {\n /** The scope the data was read for. */\n scope: string;\n /** The decoded payload returned by the Personal Server. */\n data: T;\n /**\n * Shape-validated but unauthenticated payment metadata echoed by the\n * Personal Server. Use for display/debugging, not accounting proof.\n */\n payment?: DirectPaymentResponseMetadata;\n}\n\n/**\n * Result of {@link DirectDataController.readApprovedData} across every approved\n * scope.\n *\n * @remarks\n * Successes and failures are reported side by side rather than as a thrown\n * error, because each scope read settles its own fee: throwing on the third\n * scope would discard data the app has already paid for. Check `errors` before\n * treating the read as complete.\n */\nexport interface MultiScopeDataResult<T = unknown> {\n /** Scopes that read successfully, keyed by scope. */\n results: Record<string, ApprovedDataResult<T>>;\n /** Scopes that failed, keyed by scope. Empty when every scope read. */\n errors: Record<string, Error>;\n}\n\n/**\n * Client for the Vana Account access-request API — the service that turns a\n * registered app + scopes into a `dcr_*` id and approval URL.\n *\n * @remarks\n * The controller uses a default client against the Vana Account endpoints. You\n * can inject your own implementation to point at a custom deployment or to\n * supply a test double.\n */\nexport interface AccessRequestClient {\n /**\n * Create an access request for the given app + scopes.\n *\n * @param input - App identity, source, scopes, network, and the post-approval return URL.\n * @returns The created {@link AccessRequest}.\n */\n createAccessRequest(input: {\n appAddress: string;\n app: DirectAppConfig;\n source: string;\n scopes: string[];\n returnUrl: string;\n /** Vana protocol network for this request (`\"mainnet\"` or `\"moksha\"`). */\n network: DirectNetwork;\n /** Optional foreground mobile delivery callback. */\n foregroundDelivery?: ForegroundDelivery;\n /**\n * Derivative questions to carry on the request (1 to 4). When present,\n * the array is validated client-side and serialized into the signed\n * create body verbatim. See {@link AccessRequestQuestion}.\n */\n questions?: AccessRequestQuestion[];\n /**\n * Optional retry key. The default client generates a fresh key per call\n * when omitted; pass a stable key to retry a create whose response was\n * lost without risking a duplicate DCR.\n */\n idempotencyKey?: string;\n }): Promise<AccessRequest>;\n\n /**\n * Fetch the current status of a previously created access request.\n *\n * @param requestId - The `dcr_*` id returned by {@link AccessRequestClient.createAccessRequest}.\n * @returns The current {@link AccessRequestStatus}.\n */\n getAccessRequestStatus(requestId: string): Promise<AccessRequestStatus>;\n\n /**\n * Acknowledge that the app successfully read the approved data.\n *\n * @remarks\n * Direct Vana Web DCRs remain in `ready_for_read` while the browser Personal\n * Server is serving the app. After a successful Personal Server read, the\n * controller calls this hook so Vana Web can mark the request completed and\n * close/redirect the approval tab.\n *\n * Optional so injected clients from older SDK integrations keep compiling;\n * the default HTTP client implements it.\n */\n acknowledgeRead?(requestId: string): Promise<void>;\n}\n\n/**\n * Op-type vocabulary used by the DPv2 escrow payment surface.\n *\n * @remarks\n * These are the operations the gateway prices and settles via\n * `POST /v1/escrow/pay` (`opType` field of the `GenericPayment` message). A\n * direct data read settles the {@link DirectOpType.DataAccess} op for the\n * approved grant; the other op types are listed here for completeness and to\n * give builders a typed vocabulary when inspecting fee breakdowns.\n *\n * GenericPayment uses `\"grant\"` for legacy grant lifecycle payments and\n * `\"data_access\"` for standalone receipt-bound reads.\n */\nexport const DirectOpType = {\n GrantRegistration: \"grant_registration\",\n DataAccess: \"data_access\",\n DataRegistration: \"data_registration\",\n ServerRegistration: \"server_registration\",\n BuilderRegistration: \"builder_registration\",\n} as const;\n\n/** A direct-flow op type (see {@link DirectOpType}). */\nexport type DirectOpTypeValue =\n (typeof DirectOpType)[keyof typeof DirectOpType];\n\n/**\n * What a Personal Server `402 Payment Required` tells the controller is owed for\n * a data read.\n *\n * @remarks\n * The PS read 402 body identifies the challenged operation and amount/asset.\n * The controller settles it via the DPv2 escrow gateway (`/v1/escrow/pay`). The\n * full unmodified body is preserved under\n * {@link PersonalServerPaymentRequired.raw}.\n */\nexport interface PersonalServerPaymentRequired {\n /** Grant id authorizing the Personal Server read. */\n grantId: string;\n /** X402 network advertised by the Personal Server challenge. */\n network?: string;\n /** Payment nonce requested by the 402 challenge. */\n paymentNonce?: string;\n /** Data-access receipt carrying a signature for the gateway to verify. */\n accessRecord?: EscrowAccessRecord;\n /** Asset address owed (zero address = native VANA). */\n asset: string;\n /** Amount owed, as a decimal base-unit string (preserves uint256 precision). */\n amount: string;\n /** The full, unmodified 402 response body. */\n raw: unknown;\n}\n\n/** A validated legacy grant payment challenge. */\nexport interface PersonalServerGrantPaymentOperation extends PersonalServerPaymentRequired {\n /** Escrow operation discriminator. */\n opType: \"grant\";\n /** Grant id settled by the escrow payment. */\n opId: string;\n}\n\n/** A validated receipt-bound data-access payment challenge. */\nexport interface PersonalServerDataAccessPaymentOperation extends PersonalServerPaymentRequired {\n /** Escrow operation discriminator. */\n opType: \"data_access\";\n /** Access-record id settled by the escrow payment. */\n opId: string;\n /** Complete receipt whose signature is verified later by the gateway. */\n accessRecord: EscrowAccessRecord;\n /** Positive uint256 nonce supplied by the Personal Server challenge. */\n paymentNonce: string;\n}\n\n/**\n * A Personal Server payment challenge whose escrow operation has been\n * validated.\n *\n * @remarks\n * Validation here is structural and binds operation ids to their receipt. It\n * does not cryptographically verify the receipt signature; the Personal\n * Server and Data Gateway perform that verification.\n */\nexport type PersonalServerPaymentOperation =\n | PersonalServerGrantPaymentOperation\n | PersonalServerDataAccessPaymentOperation;\n\n/** Shape-validated payment response returned directly by the escrow gateway. */\nexport interface DirectPaymentReceipt {\n /** Op type settled (the gateway `opType`, e.g. `\"grant\"`). */\n opType: string;\n /** Op id settled (a grant id or access-record id). */\n opId: string;\n /** Asset paid in (zero address = native VANA). */\n asset: string;\n /** Total amount paid, as a decimal base-unit string. */\n amount: string;\n /** Payment nonce used for this settlement. */\n paymentNonce: string;\n /** Fee breakdown reported by the gateway (registration vs data-access fee). */\n breakdown: DirectFeeBreakdown;\n /** ISO timestamp the gateway recorded the payment. */\n paidAt: string;\n}\n\n/**\n * Untrusted payment response metadata echoed by a Personal Server.\n *\n * @remarks\n * The SDK validates every field before exposing this shape, but the response\n * header is not signed by the gateway. Use it for display and debugging only,\n * never as accounting proof that a payment occurred.\n */\nexport type DirectPaymentResponseMetadata = DirectPaymentReceipt;\n\n/**\n * Per-op fee breakdown reported by the gateway.\n *\n * @remarks\n * Mirrors the escrow {@link PaymentBreakdown}: a one-time registration fee plus\n * the per-read data-access fee, and whether this settlement covered the\n * registration fee.\n */\nexport interface DirectFeeBreakdown {\n /** One-time registration fee for the op, as a decimal base-unit string. */\n registrationFee: string;\n /** Per-read data-access fee, as a decimal base-unit string. */\n dataAccessFee: string;\n /** True when this settlement paid the registration fee. */\n registrationPaid: boolean;\n}\n"],"mappings":"AAqJA,MAAM,4BAAuD;AAAA,EAC3D,YAAY;AAAA,EACZ,KAAK;AACP;AAGA,MAAM,6BAA6B;AAgB5B,SAAS,+BACd,OACA,KACoB;AACpB,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,EAAG,QAAO;AAC5D,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,KAAK;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,IAAI,aAAa,SAAU,QAAO;AACtC,QAAM,eAAe,MACjB,CAAC,0BAA0B,GAAG,CAAC,IAC/B,OAAO,OAAO,yBAAyB;AAC3C,MAAI,CAAC,aAAa,SAAS,IAAI,QAAQ,EAAG,QAAO;AACjD,MAAI,IAAI,aAAa,YAAa,QAAO;AACzC,MAAI,IAAI,aAAa,MAAM,IAAI,aAAa,GAAI,QAAO;AACvD,MAAI,IAAI,SAAS,GAAI,QAAO;AAC5B,MAAI,IAAI,WAAW,GAAI,QAAO;AAC9B,QAAM,SAAS,IAAI,KAAK,WAAW,GAAG,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI;AAC9D,MAAI,CAAC,2BAA2B,KAAK,MAAM,EAAG,QAAO;AACrD,SAAO,IAAI,SAAS;AACtB;AAyKO,MAAM,eAAe;AAAA,EAC1B,mBAAmB;AAAA,EACnB,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,qBAAqB;AACvB;","names":[]}
|
|
@@ -62,7 +62,8 @@ function useDirectVanaConnect(options) {
|
|
|
62
62
|
const reset = (0, import_react.useCallback)(() => {
|
|
63
63
|
flow.reset();
|
|
64
64
|
}, [flow]);
|
|
65
|
-
|
|
65
|
+
const retryRead = (0, import_react.useCallback)(() => flow.retryRead(), [flow]);
|
|
66
|
+
return { state, start, retryRead, reset };
|
|
66
67
|
}
|
|
67
68
|
// Annotate the CommonJS export names for ESM import in node:
|
|
68
69
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/direct/use-direct-vana-connect.ts"],"sourcesContent":["/**\n * React hook for the browser side of the direct Data Portability flow.\n *\n * @remarks\n * `useDirectVanaConnect` is a thin `useSyncExternalStore` binding over the\n * framework-agnostic {@link createDirectConnectFlow} store. The browser never\n * sees the app private key and never chooses scopes — it only calls the app's\n * own backend routes via the injected transports.\n *\n * This module is browser-safe and imports nothing Node-only. `react` is a peer\n * dependency.\n *\n * @category Direct\n * @module direct/use-direct-vana-connect\n */\n\nimport { useCallback, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport {\n createDirectConnectFlow,\n type DirectConnectOptions,\n type DirectConnectState,\n type DirectConnectTransports,\n} from \"./connect-flow\";\n\n/** Options for {@link useDirectVanaConnect}: transports plus flow tunables. */\nexport type UseDirectVanaConnectOptions<T = unknown> =\n DirectConnectTransports<T> & DirectConnectOptions;\n\n/** Return value of {@link useDirectVanaConnect}. */\nexport interface UseDirectVanaConnectResult<T = unknown> {\n /** Current flow state (`state.type` is `\"idle\"` until `start()` is called). */\n state: DirectConnectState<T>;\n /** Begin the connect flow (create request, open Vana, poll, read). */\n start: () => void;\n /** Reset back to `idle` and cancel any in-flight polling. */\n reset: () => void;\n}\n\n/**\n * Drive the two-tab connect flow from a React component.\n *\n * @param options - The `createRequest`/`getStatus`/`readResult` transports plus\n * optional polling/timeout tunables.\n * @returns `{ state, start, reset }`.\n *\n * @example\n * ```tsx\n * const connect = useDirectVanaConnect({\n * createRequest: () => fetch(\"/api/vana/request\", { method: \"POST\" }).then((r) => r.json()),\n * getStatus: (id) => fetch(`/api/vana/status?requestId=${id}`).then((r) => r.json()),\n * readResult: (id) => fetch(`/api/vana/data?requestId=${id}`).then((r) => r.json()),\n * });\n * return <button disabled={connect.state.type !== \"idle\"} onClick={connect.start}>Connect</button>;\n * ```\n */\nexport function useDirectVanaConnect<T = unknown>(\n options: UseDirectVanaConnectOptions<T>,\n): UseDirectVanaConnectResult<T> {\n // Keep the latest options in a ref so the store reads current callbacks\n // without being recreated on every render.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const flow = useMemo(\n () =>\n createDirectConnectFlow<T>(\n {\n createRequest: () => optionsRef.current.createRequest(),\n getStatus: (id) => optionsRef.current.getStatus(id),\n readResult: (id) => optionsRef.current.readResult(id),\n },\n {\n get pollIntervalMs() {\n return optionsRef.current.pollIntervalMs;\n },\n get timeoutMs() {\n return optionsRef.current.timeoutMs;\n },\n get openApprovalWindow() {\n return optionsRef.current.openApprovalWindow;\n },\n get browserPlatformPolicy() {\n return optionsRef.current.browserPlatformPolicy;\n },\n },\n ),\n // Created once per component instance; callbacks are read via optionsRef.\n [],\n );\n\n const state = useSyncExternalStore(\n flow.subscribe,\n flow.getState,\n flow.getState,\n );\n\n const start = useCallback(() => {\n void flow.start();\n }, [flow]);\n\n const reset = useCallback(() => {\n flow.reset();\n }, [flow]);\n\n return { state, start, reset };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,mBAAmE;AACnE,
|
|
1
|
+
{"version":3,"sources":["../../src/direct/use-direct-vana-connect.ts"],"sourcesContent":["/**\n * React hook for the browser side of the direct Data Portability flow.\n *\n * @remarks\n * `useDirectVanaConnect` is a thin `useSyncExternalStore` binding over the\n * framework-agnostic {@link createDirectConnectFlow} store. The browser never\n * sees the app private key and never chooses scopes — it only calls the app's\n * own backend routes via the injected transports.\n *\n * This module is browser-safe and imports nothing Node-only. `react` is a peer\n * dependency.\n *\n * @category Direct\n * @module direct/use-direct-vana-connect\n */\n\nimport { useCallback, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport {\n createDirectConnectFlow,\n type DirectConnectOptions,\n type DirectConnectRetryOutcome,\n type DirectConnectState,\n type DirectConnectTransports,\n} from \"./connect-flow\";\n\n/** Options for {@link useDirectVanaConnect}: transports plus flow tunables. */\nexport type UseDirectVanaConnectOptions<T = unknown> =\n DirectConnectTransports<T> & DirectConnectOptions;\n\n/** Return value of {@link useDirectVanaConnect}. */\nexport interface UseDirectVanaConnectResult<T = unknown> {\n /** Current flow state (`state.type` is `\"idle\"` until `start()` is called). */\n state: DirectConnectState<T>;\n /** Begin the connect flow (create request, open Vana, poll, read). */\n start: () => void;\n /** Retry the read and report whether prior consent could be reused. */\n retryRead: () => Promise<DirectConnectRetryOutcome>;\n /** Reset back to `idle` and cancel any in-flight polling. */\n reset: () => void;\n}\n\n/**\n * Drive the two-tab connect flow from a React component.\n *\n * @param options - The `createRequest`/`getStatus`/`readResult` transports plus\n * optional polling/timeout tunables.\n * @returns `{ state, start, reset }`.\n *\n * @example\n * ```tsx\n * const connect = useDirectVanaConnect({\n * createRequest: () => fetch(\"/api/vana/request\", { method: \"POST\" }).then((r) => r.json()),\n * getStatus: (id) => fetch(`/api/vana/status?requestId=${id}`).then((r) => r.json()),\n * readResult: (id) => fetch(`/api/vana/data?requestId=${id}`).then((r) => r.json()),\n * });\n * return <button disabled={connect.state.type !== \"idle\"} onClick={connect.start}>Connect</button>;\n * ```\n */\nexport function useDirectVanaConnect<T = unknown>(\n options: UseDirectVanaConnectOptions<T>,\n): UseDirectVanaConnectResult<T> {\n // Keep the latest options in a ref so the store reads current callbacks\n // without being recreated on every render.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const flow = useMemo(\n () =>\n createDirectConnectFlow<T>(\n {\n createRequest: () => optionsRef.current.createRequest(),\n getStatus: (id) => optionsRef.current.getStatus(id),\n readResult: (id) => optionsRef.current.readResult(id),\n },\n {\n get pollIntervalMs() {\n return optionsRef.current.pollIntervalMs;\n },\n get timeoutMs() {\n return optionsRef.current.timeoutMs;\n },\n get openApprovalWindow() {\n return optionsRef.current.openApprovalWindow;\n },\n get browserPlatformPolicy() {\n return optionsRef.current.browserPlatformPolicy;\n },\n },\n ),\n // Created once per component instance; callbacks are read via optionsRef.\n [],\n );\n\n const state = useSyncExternalStore(\n flow.subscribe,\n flow.getState,\n flow.getState,\n );\n\n const start = useCallback(() => {\n void flow.start();\n }, [flow]);\n\n const reset = useCallback(() => {\n flow.reset();\n }, [flow]);\n\n const retryRead = useCallback(() => flow.retryRead(), [flow]);\n\n return { state, start, retryRead, reset };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,mBAAmE;AACnE,0BAMO;AAmCA,SAAS,qBACd,SAC+B;AAG/B,QAAM,iBAAa,qBAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,WAAO;AAAA,IACX,UACE;AAAA,MACE;AAAA,QACE,eAAe,MAAM,WAAW,QAAQ,cAAc;AAAA,QACtD,WAAW,CAAC,OAAO,WAAW,QAAQ,UAAU,EAAE;AAAA,QAClD,YAAY,CAAC,OAAO,WAAW,QAAQ,WAAW,EAAE;AAAA,MACtD;AAAA,MACA;AAAA,QACE,IAAI,iBAAiB;AACnB,iBAAO,WAAW,QAAQ;AAAA,QAC5B;AAAA,QACA,IAAI,YAAY;AACd,iBAAO,WAAW,QAAQ;AAAA,QAC5B;AAAA,QACA,IAAI,qBAAqB;AACvB,iBAAO,WAAW,QAAQ;AAAA,QAC5B;AAAA,QACA,IAAI,wBAAwB;AAC1B,iBAAO,WAAW,QAAQ;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA;AAAA,IAEF,CAAC;AAAA,EACH;AAEA,QAAM,YAAQ;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EACP;AAEA,QAAM,YAAQ,0BAAY,MAAM;AAC9B,SAAK,KAAK,MAAM;AAAA,EAClB,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,YAAQ,0BAAY,MAAM;AAC9B,SAAK,MAAM;AAAA,EACb,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,gBAAY,0BAAY,MAAM,KAAK,UAAU,GAAG,CAAC,IAAI,CAAC;AAE5D,SAAO,EAAE,OAAO,OAAO,WAAW,MAAM;AAC1C;","names":[]}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @category Direct
|
|
14
14
|
* @module direct/use-direct-vana-connect
|
|
15
15
|
*/
|
|
16
|
-
import { type DirectConnectOptions, type DirectConnectState, type DirectConnectTransports } from "./connect-flow.js";
|
|
16
|
+
import { type DirectConnectOptions, type DirectConnectRetryOutcome, type DirectConnectState, type DirectConnectTransports } from "./connect-flow.js";
|
|
17
17
|
/** Options for {@link useDirectVanaConnect}: transports plus flow tunables. */
|
|
18
18
|
export type UseDirectVanaConnectOptions<T = unknown> = DirectConnectTransports<T> & DirectConnectOptions;
|
|
19
19
|
/** Return value of {@link useDirectVanaConnect}. */
|
|
@@ -22,6 +22,8 @@ export interface UseDirectVanaConnectResult<T = unknown> {
|
|
|
22
22
|
state: DirectConnectState<T>;
|
|
23
23
|
/** Begin the connect flow (create request, open Vana, poll, read). */
|
|
24
24
|
start: () => void;
|
|
25
|
+
/** Retry the read and report whether prior consent could be reused. */
|
|
26
|
+
retryRead: () => Promise<DirectConnectRetryOutcome>;
|
|
25
27
|
/** Reset back to `idle` and cancel any in-flight polling. */
|
|
26
28
|
reset: () => void;
|
|
27
29
|
}
|
|
@@ -41,7 +41,8 @@ function useDirectVanaConnect(options) {
|
|
|
41
41
|
const reset = useCallback(() => {
|
|
42
42
|
flow.reset();
|
|
43
43
|
}, [flow]);
|
|
44
|
-
|
|
44
|
+
const retryRead = useCallback(() => flow.retryRead(), [flow]);
|
|
45
|
+
return { state, start, retryRead, reset };
|
|
45
46
|
}
|
|
46
47
|
export {
|
|
47
48
|
useDirectVanaConnect
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/direct/use-direct-vana-connect.ts"],"sourcesContent":["/**\n * React hook for the browser side of the direct Data Portability flow.\n *\n * @remarks\n * `useDirectVanaConnect` is a thin `useSyncExternalStore` binding over the\n * framework-agnostic {@link createDirectConnectFlow} store. The browser never\n * sees the app private key and never chooses scopes — it only calls the app's\n * own backend routes via the injected transports.\n *\n * This module is browser-safe and imports nothing Node-only. `react` is a peer\n * dependency.\n *\n * @category Direct\n * @module direct/use-direct-vana-connect\n */\n\nimport { useCallback, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport {\n createDirectConnectFlow,\n type DirectConnectOptions,\n type DirectConnectState,\n type DirectConnectTransports,\n} from \"./connect-flow\";\n\n/** Options for {@link useDirectVanaConnect}: transports plus flow tunables. */\nexport type UseDirectVanaConnectOptions<T = unknown> =\n DirectConnectTransports<T> & DirectConnectOptions;\n\n/** Return value of {@link useDirectVanaConnect}. */\nexport interface UseDirectVanaConnectResult<T = unknown> {\n /** Current flow state (`state.type` is `\"idle\"` until `start()` is called). */\n state: DirectConnectState<T>;\n /** Begin the connect flow (create request, open Vana, poll, read). */\n start: () => void;\n /** Reset back to `idle` and cancel any in-flight polling. */\n reset: () => void;\n}\n\n/**\n * Drive the two-tab connect flow from a React component.\n *\n * @param options - The `createRequest`/`getStatus`/`readResult` transports plus\n * optional polling/timeout tunables.\n * @returns `{ state, start, reset }`.\n *\n * @example\n * ```tsx\n * const connect = useDirectVanaConnect({\n * createRequest: () => fetch(\"/api/vana/request\", { method: \"POST\" }).then((r) => r.json()),\n * getStatus: (id) => fetch(`/api/vana/status?requestId=${id}`).then((r) => r.json()),\n * readResult: (id) => fetch(`/api/vana/data?requestId=${id}`).then((r) => r.json()),\n * });\n * return <button disabled={connect.state.type !== \"idle\"} onClick={connect.start}>Connect</button>;\n * ```\n */\nexport function useDirectVanaConnect<T = unknown>(\n options: UseDirectVanaConnectOptions<T>,\n): UseDirectVanaConnectResult<T> {\n // Keep the latest options in a ref so the store reads current callbacks\n // without being recreated on every render.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const flow = useMemo(\n () =>\n createDirectConnectFlow<T>(\n {\n createRequest: () => optionsRef.current.createRequest(),\n getStatus: (id) => optionsRef.current.getStatus(id),\n readResult: (id) => optionsRef.current.readResult(id),\n },\n {\n get pollIntervalMs() {\n return optionsRef.current.pollIntervalMs;\n },\n get timeoutMs() {\n return optionsRef.current.timeoutMs;\n },\n get openApprovalWindow() {\n return optionsRef.current.openApprovalWindow;\n },\n get browserPlatformPolicy() {\n return optionsRef.current.browserPlatformPolicy;\n },\n },\n ),\n // Created once per component instance; callbacks are read via optionsRef.\n [],\n );\n\n const state = useSyncExternalStore(\n flow.subscribe,\n flow.getState,\n flow.getState,\n );\n\n const start = useCallback(() => {\n void flow.start();\n }, [flow]);\n\n const reset = useCallback(() => {\n flow.reset();\n }, [flow]);\n\n return { state, start, reset };\n}\n"],"mappings":"AAgBA,SAAS,aAAa,SAAS,QAAQ,4BAA4B;AACnE;AAAA,EACE;AAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/direct/use-direct-vana-connect.ts"],"sourcesContent":["/**\n * React hook for the browser side of the direct Data Portability flow.\n *\n * @remarks\n * `useDirectVanaConnect` is a thin `useSyncExternalStore` binding over the\n * framework-agnostic {@link createDirectConnectFlow} store. The browser never\n * sees the app private key and never chooses scopes — it only calls the app's\n * own backend routes via the injected transports.\n *\n * This module is browser-safe and imports nothing Node-only. `react` is a peer\n * dependency.\n *\n * @category Direct\n * @module direct/use-direct-vana-connect\n */\n\nimport { useCallback, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport {\n createDirectConnectFlow,\n type DirectConnectOptions,\n type DirectConnectRetryOutcome,\n type DirectConnectState,\n type DirectConnectTransports,\n} from \"./connect-flow\";\n\n/** Options for {@link useDirectVanaConnect}: transports plus flow tunables. */\nexport type UseDirectVanaConnectOptions<T = unknown> =\n DirectConnectTransports<T> & DirectConnectOptions;\n\n/** Return value of {@link useDirectVanaConnect}. */\nexport interface UseDirectVanaConnectResult<T = unknown> {\n /** Current flow state (`state.type` is `\"idle\"` until `start()` is called). */\n state: DirectConnectState<T>;\n /** Begin the connect flow (create request, open Vana, poll, read). */\n start: () => void;\n /** Retry the read and report whether prior consent could be reused. */\n retryRead: () => Promise<DirectConnectRetryOutcome>;\n /** Reset back to `idle` and cancel any in-flight polling. */\n reset: () => void;\n}\n\n/**\n * Drive the two-tab connect flow from a React component.\n *\n * @param options - The `createRequest`/`getStatus`/`readResult` transports plus\n * optional polling/timeout tunables.\n * @returns `{ state, start, reset }`.\n *\n * @example\n * ```tsx\n * const connect = useDirectVanaConnect({\n * createRequest: () => fetch(\"/api/vana/request\", { method: \"POST\" }).then((r) => r.json()),\n * getStatus: (id) => fetch(`/api/vana/status?requestId=${id}`).then((r) => r.json()),\n * readResult: (id) => fetch(`/api/vana/data?requestId=${id}`).then((r) => r.json()),\n * });\n * return <button disabled={connect.state.type !== \"idle\"} onClick={connect.start}>Connect</button>;\n * ```\n */\nexport function useDirectVanaConnect<T = unknown>(\n options: UseDirectVanaConnectOptions<T>,\n): UseDirectVanaConnectResult<T> {\n // Keep the latest options in a ref so the store reads current callbacks\n // without being recreated on every render.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const flow = useMemo(\n () =>\n createDirectConnectFlow<T>(\n {\n createRequest: () => optionsRef.current.createRequest(),\n getStatus: (id) => optionsRef.current.getStatus(id),\n readResult: (id) => optionsRef.current.readResult(id),\n },\n {\n get pollIntervalMs() {\n return optionsRef.current.pollIntervalMs;\n },\n get timeoutMs() {\n return optionsRef.current.timeoutMs;\n },\n get openApprovalWindow() {\n return optionsRef.current.openApprovalWindow;\n },\n get browserPlatformPolicy() {\n return optionsRef.current.browserPlatformPolicy;\n },\n },\n ),\n // Created once per component instance; callbacks are read via optionsRef.\n [],\n );\n\n const state = useSyncExternalStore(\n flow.subscribe,\n flow.getState,\n flow.getState,\n );\n\n const start = useCallback(() => {\n void flow.start();\n }, [flow]);\n\n const reset = useCallback(() => {\n flow.reset();\n }, [flow]);\n\n const retryRead = useCallback(() => flow.retryRead(), [flow]);\n\n return { state, start, retryRead, reset };\n}\n"],"mappings":"AAgBA,SAAS,aAAa,SAAS,QAAQ,4BAA4B;AACnE;AAAA,EACE;AAAA,OAKK;AAmCA,SAAS,qBACd,SAC+B;AAG/B,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,OAAO;AAAA,IACX,MACE;AAAA,MACE;AAAA,QACE,eAAe,MAAM,WAAW,QAAQ,cAAc;AAAA,QACtD,WAAW,CAAC,OAAO,WAAW,QAAQ,UAAU,EAAE;AAAA,QAClD,YAAY,CAAC,OAAO,WAAW,QAAQ,WAAW,EAAE;AAAA,MACtD;AAAA,MACA;AAAA,QACE,IAAI,iBAAiB;AACnB,iBAAO,WAAW,QAAQ;AAAA,QAC5B;AAAA,QACA,IAAI,YAAY;AACd,iBAAO,WAAW,QAAQ;AAAA,QAC5B;AAAA,QACA,IAAI,qBAAqB;AACvB,iBAAO,WAAW,QAAQ;AAAA,QAC5B;AAAA,QACA,IAAI,wBAAwB;AAC1B,iBAAO,WAAW,QAAQ;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA;AAAA,IAEF,CAAC;AAAA,EACH;AAEA,QAAM,QAAQ;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EACP;AAEA,QAAM,QAAQ,YAAY,MAAM;AAC9B,SAAK,KAAK,MAAM;AAAA,EAClB,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,QAAQ,YAAY,MAAM;AAC9B,SAAK,MAAM;AAAA,EACb,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,YAAY,YAAY,MAAM,KAAK,UAAU,GAAG,CAAC,IAAI,CAAC;AAE5D,SAAO,EAAE,OAAO,OAAO,WAAW,MAAM;AAC1C;","names":[]}
|
package/dist/errors.cjs
CHANGED
|
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var errors_exports = {};
|
|
20
20
|
__export(errors_exports, {
|
|
21
21
|
BlockchainError: () => BlockchainError,
|
|
22
|
+
BuilderUnknownError: () => BuilderUnknownError,
|
|
22
23
|
ContractNotFoundError: () => ContractNotFoundError,
|
|
23
24
|
DataPointDeletedError: () => DataPointDeletedError,
|
|
24
25
|
DataPointNotFoundError: () => DataPointNotFoundError,
|
|
@@ -32,10 +33,20 @@ __export(errors_exports, {
|
|
|
32
33
|
DerivativeQuestionRejectedError: () => DerivativeQuestionRejectedError,
|
|
33
34
|
DerivativeQuestionTimeoutError: () => DerivativeQuestionTimeoutError,
|
|
34
35
|
DerivativeSourceNotGrantedError: () => DerivativeSourceNotGrantedError,
|
|
36
|
+
GrantInvalidError: () => GrantInvalidError,
|
|
35
37
|
InvalidConfigurationError: () => InvalidConfigurationError,
|
|
38
|
+
JobIdTakenError: () => JobIdTakenError,
|
|
39
|
+
JobNotFoundError: () => JobNotFoundError,
|
|
40
|
+
JobRejectedError: () => JobRejectedError,
|
|
41
|
+
JobRequestTooLargeError: () => JobRequestTooLargeError,
|
|
42
|
+
JobResultIntegrityError: () => JobResultIntegrityError,
|
|
43
|
+
JobTimeoutError: () => JobTimeoutError,
|
|
44
|
+
JobTransportError: () => JobTransportError,
|
|
45
|
+
JobsClientError: () => JobsClientError,
|
|
36
46
|
LineageReadError: () => LineageReadError,
|
|
37
47
|
NetworkError: () => NetworkError,
|
|
38
48
|
NonceError: () => NonceError,
|
|
49
|
+
OwnerNotReadyError: () => OwnerNotReadyError,
|
|
39
50
|
PermissionError: () => PermissionError,
|
|
40
51
|
PersonalServerError: () => PersonalServerError,
|
|
41
52
|
PersonalServerWriteError: () => PersonalServerWriteError,
|
|
@@ -257,6 +268,68 @@ class WriteRejectedError extends PersonalServerWriteError {
|
|
|
257
268
|
super(message, "WRITE_REJECTED", status, errorCode, details);
|
|
258
269
|
}
|
|
259
270
|
}
|
|
271
|
+
class JobsClientError extends VanaError {
|
|
272
|
+
constructor(message, code, status, errorCode = null, details) {
|
|
273
|
+
super(message, code);
|
|
274
|
+
this.status = status;
|
|
275
|
+
this.errorCode = errorCode;
|
|
276
|
+
this.details = details;
|
|
277
|
+
}
|
|
278
|
+
status;
|
|
279
|
+
errorCode;
|
|
280
|
+
details;
|
|
281
|
+
}
|
|
282
|
+
class BuilderUnknownError extends JobsClientError {
|
|
283
|
+
constructor(message, details) {
|
|
284
|
+
super(message, "JOB_BUILDER_UNKNOWN", 403, "BUILDER_UNKNOWN", details);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
class GrantInvalidError extends JobsClientError {
|
|
288
|
+
constructor(message, details) {
|
|
289
|
+
super(message, "JOB_GRANT_INVALID", 403, "GRANT_INVALID", details);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
class OwnerNotReadyError extends JobsClientError {
|
|
293
|
+
constructor(message, details) {
|
|
294
|
+
super(message, "JOB_OWNER_NOT_READY", 403, "OWNER_NOT_READY", details);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
class JobIdTakenError extends JobsClientError {
|
|
298
|
+
constructor(message, details) {
|
|
299
|
+
super(message, "JOB_ID_TAKEN", 409, "JOB_ID_TAKEN", details);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
class JobNotFoundError extends JobsClientError {
|
|
303
|
+
constructor(message, details) {
|
|
304
|
+
super(message, "JOB_NOT_FOUND", 404, "JOB_NOT_FOUND", details);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
class JobRequestTooLargeError extends JobsClientError {
|
|
308
|
+
constructor(message, errorCode = "BODY_TOO_LARGE", details) {
|
|
309
|
+
super(message, "JOB_REQUEST_TOO_LARGE", 413, errorCode, details);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
class JobTimeoutError extends JobsClientError {
|
|
313
|
+
constructor(message, details) {
|
|
314
|
+
super(message, "JOB_TIMEOUT", void 0, null, details);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
class JobResultIntegrityError extends JobsClientError {
|
|
318
|
+
constructor(message, details) {
|
|
319
|
+
super(message, "JOB_RESULT_INTEGRITY", void 0, null, details);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
class JobRejectedError extends JobsClientError {
|
|
323
|
+
constructor(message, status, errorCode = null, details) {
|
|
324
|
+
super(message, "JOB_REJECTED", status, errorCode, details);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
class JobTransportError extends JobsClientError {
|
|
328
|
+
constructor(message, cause) {
|
|
329
|
+
super(message, "JOB_TRANSPORT_ERROR");
|
|
330
|
+
this.cause = cause;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
260
333
|
class LineageReadError extends VanaError {
|
|
261
334
|
constructor(message, status, errorCode = null, details) {
|
|
262
335
|
super(message, "LINEAGE_READ_ERROR");
|
|
@@ -343,6 +416,7 @@ class DataPointVersionConflictError extends VanaError {
|
|
|
343
416
|
// Annotate the CommonJS export names for ESM import in node:
|
|
344
417
|
0 && (module.exports = {
|
|
345
418
|
BlockchainError,
|
|
419
|
+
BuilderUnknownError,
|
|
346
420
|
ContractNotFoundError,
|
|
347
421
|
DataPointDeletedError,
|
|
348
422
|
DataPointNotFoundError,
|
|
@@ -356,10 +430,20 @@ class DataPointVersionConflictError extends VanaError {
|
|
|
356
430
|
DerivativeQuestionRejectedError,
|
|
357
431
|
DerivativeQuestionTimeoutError,
|
|
358
432
|
DerivativeSourceNotGrantedError,
|
|
433
|
+
GrantInvalidError,
|
|
359
434
|
InvalidConfigurationError,
|
|
435
|
+
JobIdTakenError,
|
|
436
|
+
JobNotFoundError,
|
|
437
|
+
JobRejectedError,
|
|
438
|
+
JobRequestTooLargeError,
|
|
439
|
+
JobResultIntegrityError,
|
|
440
|
+
JobTimeoutError,
|
|
441
|
+
JobTransportError,
|
|
442
|
+
JobsClientError,
|
|
360
443
|
LineageReadError,
|
|
361
444
|
NetworkError,
|
|
362
445
|
NonceError,
|
|
446
|
+
OwnerNotReadyError,
|
|
363
447
|
PermissionError,
|
|
364
448
|
PersonalServerError,
|
|
365
449
|
PersonalServerWriteError,
|
package/dist/errors.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base error class for all Vana SDK errors with structured error codes.\n *\n * @remarks\n * This abstract base class provides a foundation for all SDK-specific errors with\n * consistent error codes and stack trace handling. All Vana SDK errors extend this\n * class to provide structured error information that applications can handle\n * programmatically. The error code enables differentiation between error types\n * without relying on string matching.\n * @category Error Handling\n */\nexport class VanaError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n ) {\n super(message);\n this.name = this.constructor.name;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when gasless transaction submission via relayer fails.\n *\n * @remarks\n * This error occurs when the relayer service is unavailable, returns an error,\n * or fails to process a gasless transaction. It includes the HTTP status code\n * and response details when available to help with debugging relayer issues.\n * @category Error Handling\n */\nexport class RelayerError extends VanaError {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly response?: unknown,\n ) {\n super(message, \"RELAYER_ERROR\");\n }\n}\n\n/**\n * Thrown when the user rejects a wallet signature request.\n *\n * @remarks\n * This error occurs when users decline to sign transactions or typed data through\n * their wallet interface. It's a normal part of user interaction and should be\n * handled gracefully by applications without treating it as a system error.\n * @category Error Handling\n */\nexport class UserRejectedRequestError extends VanaError {\n constructor(message: string = \"User rejected the signature request\") {\n super(message, \"USER_REJECTED_REQUEST\");\n }\n}\n\n/**\n * Thrown when the SDK configuration contains invalid or missing parameters.\n *\n * @remarks\n * This error occurs during SDK initialization when required configuration\n * parameters are missing, invalid, or incompatible. Common causes include\n * missing wallet clients, invalid chain IDs, malformed storage provider\n * configurations, or incompatible parameter combinations.\n *\n * Applications should catch this error during initialization and provide\n * clear feedback to users about configuration requirements.\n *\n * @example\n * ```typescript\n * try {\n * const vana = Vana({\n * chainId: 999999, // Invalid chain ID\n * account: null // Missing account\n * });\n * } catch (error) {\n * if (error instanceof InvalidConfigurationError) {\n * console.error('Configuration error:', error.message);\n * // Show user-friendly configuration help\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class InvalidConfigurationError extends VanaError {\n constructor(message: string) {\n super(message, \"INVALID_CONFIGURATION\");\n }\n}\n\n/**\n * Thrown when a required Vana protocol contract is not deployed on the current chain.\n *\n * @remarks\n * This error occurs when attempting to interact with contracts that are not\n * available on the connected blockchain network. It includes the contract name\n * and chain ID to help identify deployment issues or incorrect network configuration.\n * @category Error Handling\n */\nexport class ContractNotFoundError extends VanaError {\n constructor(contractName: string, chainId: number) {\n super(\n `Contract ${contractName} not found on chain ${chainId}`,\n \"CONTRACT_NOT_FOUND\",\n );\n }\n}\n\n/**\n * Thrown when blockchain operations fail due to network, contract, or transaction issues.\n *\n * @remarks\n * This error encompasses various blockchain-related failures including network\n * connectivity issues, contract execution failures, insufficient gas, invalid\n * transaction parameters, or smart contract reverts. The original error is\n * preserved to provide detailed debugging information while maintaining a\n * consistent SDK error interface.\n *\n * Common causes:\n * - Network connectivity problems\n * - Insufficient gas or gas price too low\n * - Contract function reverts\n * - Invalid transaction parameters\n * - Blockchain congestion or downtime\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.grant({\n * grantee: '0x742d35...',\n * operation: 'read'\n * });\n * } catch (error) {\n * if (error instanceof BlockchainError) {\n * console.error('Blockchain operation failed:', error.message);\n *\n * // Check if it's a network issue\n * if (error.originalError?.message.includes('network')) {\n * // Retry with exponential backoff\n * await retryOperation();\n * }\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class BlockchainError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"BLOCKCHAIN_ERROR\");\n }\n}\n\n/**\n * Thrown when data serialization or deserialization operations fail.\n *\n * @remarks\n * This error occurs when the SDK cannot properly serialize parameters for\n * blockchain transactions, IPFS storage, or API calls. Common causes include\n * circular references in objects, unsupported data types, or malformed JSON.\n * It's typically encountered during grant file creation, storage operations,\n * or when preparing transaction data.\n *\n * @example\n * ```typescript\n * try {\n * // Object with circular reference causes serialization error\n * const obj = { name: 'test' };\n * obj.self = obj; // Circular reference\n *\n * await vana.data.upload({\n * content: obj,\n * filename: 'data.json'\n * });\n * } catch (error) {\n * if (error instanceof SerializationError) {\n * console.error('Data serialization failed:', error.message);\n * // Clean data before retry\n * const cleanedData = removeCircularReferences(obj);\n * await vana.data.upload({\n * content: cleanedData,\n * filename: 'data.json'\n * });\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class SerializationError extends VanaError {\n constructor(message: string) {\n super(message, \"SERIALIZATION_ERROR\");\n }\n}\n\n/**\n * Thrown when a signature operation fails or cannot be completed.\n *\n * @remarks\n * This error occurs when wallet signature operations fail due to disconnection,\n * locked accounts, or other wallet-related issues. It preserves the original\n * error for debugging while providing consistent error handling across the SDK.\n *\n * Recovery strategies:\n * - Check wallet connection and account unlock status\n * - Retry operation with explicit user interaction\n * - For gasless operations, consider switching to direct transactions\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.grant({ grantee: '0x...' });\n * } catch (error) {\n * if (error instanceof SignatureError) {\n * // Prompt user to unlock wallet\n * await promptWalletUnlock();\n * // Retry operation\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class SignatureError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"SIGNATURE_ERROR\");\n }\n}\n\n/**\n * Thrown when network communication fails during API calls or blockchain interactions.\n *\n * @remarks\n * This error encompasses network connectivity issues, API unavailability,\n * timeout errors, and CORS restrictions. It's commonly encountered during\n * IPFS operations, subgraph queries, or RPC calls.\n *\n * Recovery strategies:\n * - Check network connectivity\n * - Retry with exponential backoff\n * - Verify API endpoints are accessible\n * - Switch to alternative network providers or gateways\n *\n * @example\n * ```typescript\n * try {\n * const files = await vana.data.getUserFiles({ owner: '0x...' });\n * } catch (error) {\n * if (error instanceof NetworkError) {\n * // Implement retry with exponential backoff\n * await retryWithBackoff(() => vana.data.getUserFiles({ owner: '0x...' }));\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class NetworkError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"NETWORK_ERROR\");\n }\n}\n\n/**\n * Thrown when transaction nonce retrieval fails during gasless operations.\n *\n * @remarks\n * This error occurs when the SDK cannot retrieve the user's current nonce from\n * smart contracts, preventing gasless transaction submission. Nonces are critical\n * for preventing replay attacks in signed transactions.\n *\n * Recovery strategies:\n * - Retry nonce retrieval after brief delay\n * - Check wallet connection and account status\n * - Use manual nonce specification if supported by the operation\n * - Switch to direct transactions as fallback\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.grant({ grantee: '0x...' });\n * } catch (error) {\n * if (error instanceof NonceError) {\n * // Wait and retry\n * await delay(1000);\n * await vana.permissions.grant({ grantee: '0x...' });\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class NonceError extends VanaError {\n constructor(message: string) {\n super(message, \"NONCE_ERROR\");\n }\n}\n\n/**\n * Thrown when personal server operations fail or cannot be completed.\n *\n * @remarks\n * This error occurs during interactions with personal servers for computation\n * requests, identity retrieval, or operation status checks. Common causes include\n * server unavailability, untrusted server status, or invalid permission grants.\n *\n * Recovery strategies:\n * - Verify server URL accessibility\n * - Check server trust status via `vana.permissions.getTrustedServers()`\n * - Ensure valid permissions exist for the operation\n * - Retry after server becomes available\n *\n * @example\n * ```typescript\n * try {\n * const result = await vana.server.createOperation({ permissionId: 123 });\n * } catch (error) {\n * if (error instanceof PersonalServerError) {\n * // Check if server is trusted\n * const trustedServers = await vana.permissions.getTrustedServers();\n * if (!trustedServers.includes(serverId)) {\n * await vana.permissions.trustServer({ serverId });\n * }\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class PersonalServerError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"PERSONAL_SERVER_ERROR\");\n }\n}\n\n/**\n * Thrown when attempting to register a server with a URL different from its existing registration.\n *\n * @remarks\n * This error occurs when trying to add or trust a server that's already registered\n * on-chain with a different URL. Server URLs are immutable once registered to\n * maintain consistency and security. Applications should use the existing URL\n * or register a new server with a different ID.\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.addAndTrustServer({\n * serverId: 1,\n * serverUrl: 'https://new-url.com',\n * publicKey: '0x...'\n * });\n * } catch (error) {\n * if (error instanceof ServerUrlMismatchError) {\n * console.log(`Server already registered with: ${error.existingUrl}`);\n * // Use existing URL or register new server\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class ServerUrlMismatchError extends VanaError {\n constructor(existingUrl: string, providedUrl: string, serverId: string) {\n super(\n `Server ${serverId} is already registered with URL \"${existingUrl}\". Cannot change to \"${providedUrl}\".`,\n \"SERVER_URL_MISMATCH\",\n );\n this.existingUrl = existingUrl;\n this.providedUrl = providedUrl;\n this.serverId = serverId;\n }\n\n public readonly existingUrl: string;\n public readonly providedUrl: string;\n public readonly serverId: string;\n}\n\n/**\n * Thrown when permission grant, revoke, or validation operations fail.\n *\n * @remarks\n * This error occurs during permission management operations including grants,\n * revocations, and permission validation checks. Common causes include invalid\n * grantee addresses, expired permissions, or insufficient privileges.\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.revoke({ permissionId: 999999 });\n * } catch (error) {\n * if (error instanceof PermissionError) {\n * console.error('Permission operation failed:', error.message);\n * // Permission may not exist or user may not be owner\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class PermissionError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"PERMISSION_ERROR\");\n }\n}\n\n/**\n * Thrown when attempting to perform write operations without a wallet client.\n *\n * @remarks\n * This error occurs when trying to execute operations that require wallet\n * interaction (signing, encrypting, or submitting transactions) while the SDK\n * is initialized in read-only mode without a wallet client. To perform write\n * operations, the SDK must be initialized with a wallet client.\n *\n * Common operations that require a wallet:\n * - Signing transactions or typed data\n * - Encrypting or decrypting files\n * - Granting or revoking permissions\n * - Uploading data to IPFS\n * - Submitting blockchain transactions\n *\n * @example\n * ```typescript\n * try {\n * // This will throw if no wallet client is provided\n * await vana.data.decryptFile({ fileId: 'abc123' });\n * } catch (error) {\n * if (error instanceof ReadOnlyError) {\n * console.error(`Cannot ${error.operation}: ${error.message}`);\n * // Initialize with wallet client to enable write operations\n * const vanaWithWallet = Vana({\n * walletClient: createWalletClient(...)\n * });\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class ReadOnlyError extends VanaError {\n constructor(\n operation: string,\n suggestion: string = \"Initialize the SDK with a walletClient to perform this operation\",\n ) {\n super(\n `Operation '${operation}' requires a wallet client. ${suggestion}`,\n \"READ_ONLY_ERROR\",\n );\n this.operation = operation;\n this.suggestion = suggestion;\n }\n\n /** The operation that was attempted */\n public readonly operation: string;\n /** Suggested solution for fixing the error */\n public readonly suggestion: string;\n}\n\n/**\n * Thrown when a long-running transaction operation times out or fails during polling.\n *\n * @remarks\n * This error occurs when asynchronous relayer operations exceed the configured timeout\n * or encounter non-recoverable errors during status polling. It preserves the operation ID\n * to allow recovery and status checking at a later time.\n *\n * The error includes:\n * - Operation ID for recovery and status checking\n * - Last known status before failure\n * - Original error details\n *\n * Recovery strategies:\n * - Save the operation ID for later status checking\n * - Implement manual recovery flow using the operation ID\n * - Check transaction status through alternative means\n * - Contact support if operation remains stuck\n *\n * @example\n * ```typescript\n * try {\n * const result = await vana.permissions.grant({\n * grantee: '0x...',\n * files: [1, 2, 3]\n * });\n * } catch (error) {\n * if (error instanceof TransactionPendingError) {\n * // Save operation ID for recovery\n * localStorage.setItem('pending_operation', error.operationId);\n *\n * // Show recovery UI\n * showRecoveryDialog({\n * operationId: error.operationId,\n * lastStatus: error.lastKnownStatus\n * });\n *\n * // Attempt recovery later\n * const status = await vana.checkOperationStatus(error.operationId);\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class TransactionPendingError extends VanaError {\n constructor(\n /** The operation ID that can be used for status checking */\n public readonly operationId: string,\n message: string,\n /** The last known status of the operation before failure */\n public readonly lastKnownStatus?: unknown,\n ) {\n super(\n `Transaction operation pending: ${message} (operationId: ${operationId})`,\n \"TRANSACTION_PENDING\",\n );\n }\n\n /**\n * Converts the error to a JSON-serializable format.\n *\n * @remarks\n * Useful for logging, storage, or transmission of error details.\n *\n * @returns JSON representation of the error\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n operationId: this.operationId,\n lastKnownStatus: this.lastKnownStatus,\n };\n }\n}\n\n/**\n * Personal Server error codes a Write API call can surface in\n * {@link PersonalServerWriteError.errorCode}.\n *\n * @remarks\n * The `WRITE_*` and `LINEAGE_*` codes are specific to the Write API; the\n * rest are the shared protocol codes the write policy reuses. The string\n * escape hatch keeps codes introduced by a newer Personal Server readable.\n * @category Error Handling\n */\nexport type PersonalServerWriteErrorCode =\n | \"WRITE_SESSION_AUTH_FAILED\"\n | \"WRITE_SESSION_PROOF_REQUIRED\"\n | \"WRITE_SESSION_PROOF_REPLAY\"\n | \"GRANT_ID_REQUIRED\"\n | \"WRITE_ATTRIBUTION_REQUIRED\"\n | \"WRITE_ATTRIBUTION_INVALID\"\n | \"WRITE_ATTRIBUTION_SIGNER_MISMATCH\"\n | \"WRITE_ATTRIBUTION_GRANT_MISMATCH\"\n | \"WRITE_ATTRIBUTION_REPLAY\"\n | \"WRITE_BODY_NOT_CANONICAL\"\n | \"LINEAGE_INVALID\"\n | \"LINEAGE_SCOPE_UNDER_SOURCE_PREFIX\"\n | \"LINEAGE_SOURCE_UNKNOWN\"\n | \"LINEAGE_SOURCE_LOOKUP_FAILED\"\n | \"LINEAGE_FORBIDDEN\"\n | \"LINEAGE_GATEWAY_ERROR\"\n | \"LINEAGE_UNAVAILABLE\"\n | \"LINEAGE_CASCADE_UNAVAILABLE\"\n | \"LINEAGE_SIGNATURE_REQUIRED\"\n | \"LINEAGE_SIGNATURE_INVALID\"\n | \"INVALID_CASCADE\"\n | \"INVALID_VERSION\"\n | \"NOT_FOUND\"\n | \"MISSING_AUTH\"\n | \"INVALID_SIGNATURE\"\n | \"UNREGISTERED_BUILDER\"\n | \"GRANT_REQUIRED\"\n | \"GRANT_REVOKED\"\n | \"GRANT_EXPIRED\"\n | \"GRANT_OWNER_MISMATCH\"\n | \"SCOPE_MISMATCH\"\n | \"INVALID_BODY\"\n | \"CONTENT_TOO_LARGE\"\n | \"PS_UNAVAILABLE\"\n | \"SERVER_NOT_CONFIGURED\"\n | \"INTERNAL_ERROR\"\n | \"DERIVATIVE_QUESTION_INVALID\"\n | \"DERIVATIVE_QUESTION_NOT_FOUND\"\n | \"DERIVATIVE_DERIVED_SCOPE_REQUIRED\"\n | \"DERIVATIVE_CYCLE\"\n | \"DERIVATIVE_SOURCE_NOT_GRANTED\"\n | \"DERIVATIVE_COMPUTE_UNAVAILABLE\"\n | \"METHOD_NOT_ALLOWED\"\n | (string & {});\n\n/**\n * Base class for every Personal Server Write API failure, including the\n * derivative question routes that authenticate with the same credential.\n *\n * @remarks\n * `status` is the HTTP status the Personal Server answered with (absent for\n * failures raised before a request was sent or when no response arrived),\n * `errorCode` is the Personal Server's protocol error code when the body\n * carried one, and `details` is the server-supplied detail object.\n * @category Error Handling\n */\nexport class PersonalServerWriteError extends VanaError {\n constructor(\n message: string,\n code: string,\n public readonly status?: number,\n public readonly errorCode: PersonalServerWriteErrorCode | null = null,\n public readonly details?: Record<string, unknown>,\n ) {\n super(message, code);\n }\n}\n\n/**\n * Thrown before any request is sent when the write input is invalid: no\n * payload, a payload that is not a JSON object, a reserved `$writtenBy` /\n * `$lineage` key, a malformed lineage source id, or an unusable signer.\n * @category Error Handling\n */\nexport class WriteRequestError extends PersonalServerWriteError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"WRITE_INVALID_REQUEST\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when the transport failed (fetch threw) on every attempt.\n *\n * @remarks\n * A write whose response was lost may still have been stored: the Personal\n * Server commits before answering. Check the scope before re-sending the\n * same record.\n * @category Error Handling\n */\nexport class WriteTransportError extends PersonalServerWriteError {\n constructor(\n message: string,\n public readonly attempts: number,\n cause?: unknown,\n ) {\n super(message, \"WRITE_TRANSPORT_ERROR\", undefined, null, { attempts });\n this.cause = cause;\n }\n}\n\n/**\n * Thrown when `POST /v1/write/session` refused the handshake (any non-2xx),\n * or answered with a body the SDK cannot read.\n * @category Error Handling\n */\nexport class WriteSessionError extends PersonalServerWriteError {\n constructor(\n message: string,\n status?: number,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_SESSION_REJECTED\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown by {@link writeData} when the session's bearer token has passed its\n * `expires_in` lifetime. Open a new session; nothing was sent.\n * @category Error Handling\n */\nexport class WriteSessionExpiredError extends PersonalServerWriteError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"WRITE_SESSION_EXPIRED\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when a write answered 401.\n *\n * @remarks\n * `WRITE_ATTRIBUTION_*` codes describe the per-write proof. A plain\n * `INVALID_SIGNATURE` or `MISSING_AUTH` on a write usually means the session\n * token is no longer known to the Personal Server (expired, or the server\n * restarted and dropped its in-memory sessions): open a new session.\n * @category Error Handling\n */\nexport class WriteUnauthorizedError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_UNAUTHORIZED\", 401, errorCode, details);\n }\n}\n\n/**\n * Thrown when a write answered 403: the live grant no longer authorizes it\n * (revoked, expired, wrong owner) or the scope is outside its write patterns.\n * @category Error Handling\n */\nexport class WriteForbiddenError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_FORBIDDEN\", 403, errorCode, details);\n }\n}\n\n/**\n * Thrown when a write answered 409 (the record conflicts with server state).\n * @category Error Handling\n */\nexport class WriteConflictError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_CONFLICT\", 409, errorCode, details);\n }\n}\n\n/**\n * Thrown when the Personal Server rejected the write's lineage: 422\n * `LINEAGE_SOURCE_UNKNOWN` (`details.unknown` lists the offending ids), 400\n * `LINEAGE_INVALID` / `LINEAGE_SCOPE_UNDER_SOURCE_PREFIX`, or 502\n * `LINEAGE_SOURCE_LOOKUP_FAILED`.\n * @category Error Handling\n */\nexport class WriteLineageError extends PersonalServerWriteError {\n constructor(\n message: string,\n status = 422,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_LINEAGE_REJECTED\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown when a write answered any other non-2xx status (400 for a body the\n * server cannot store, 413 for an oversized payload, 5xx).\n * @category Error Handling\n */\nexport class WriteRejectedError extends PersonalServerWriteError {\n constructor(\n message: string,\n status: number,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_REJECTED\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown when a lineage read (Personal Server or gateway) fails: a non-2xx\n * answer, a body that is not a lineage graph, a malformed data point id, or\n * a transport failure.\n * @category Error Handling\n */\nexport class LineageReadError extends VanaError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly errorCode: PersonalServerWriteErrorCode | null = null,\n public readonly details?: Record<string, unknown>,\n ) {\n super(message, \"LINEAGE_READ_ERROR\");\n }\n}\n\n/**\n * Thrown when the Personal Server rejected a derivative question with a\n * status the more specific errors do not claim (405, 413\n * `CONTENT_TOO_LARGE`, 5xx), or answered a body the SDK cannot read.\n *\n * @remarks\n * The question routes share the Write API's credential, so their\n * authentication failures are the write errors: {@link WriteUnauthorizedError}\n * (401), {@link WriteForbiddenError} (403 on the derived scope),\n * {@link WriteConflictError} (409 that is not a cycle),\n * {@link WriteRequestError} (refused before sending),\n * {@link WriteTransportError} (`fetch` threw).\n * @category Error Handling\n */\nexport class DerivativeQuestionRejectedError extends PersonalServerWriteError {\n constructor(\n message: string,\n status: number,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_QUESTION_REJECTED\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown when the Personal Server refused a question registration as\n * invalid: 400 `DERIVATIVE_QUESTION_INVALID` (body shape, the scope grammar,\n * 1 to 16 distinct source scopes, an 8000 character question, a model id) or\n * 400 `LINEAGE_SCOPE_UNDER_SOURCE_PREFIX` (the derived scope shares its first\n * dot-segment with a source scope). `details.field` names the offending\n * field when the server sent one.\n * @category Error Handling\n */\nexport class DerivativeQuestionInvalidError extends PersonalServerWriteError {\n constructor(\n message: string,\n status = 400,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_QUESTION_INVALID\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown when a question id is unknown (404\n * `DERIVATIVE_QUESTION_NOT_FOUND`).\n *\n * @remarks\n * A builder only ever sees the questions it registered itself, so a question\n * another builder (or the owner) registered on the same derived scope is a\n * 404 too, not a 403. An id no Personal Server ever held is a 404 as well\n * for any authenticated caller (`personal-server-ts` d91124d and later),\n * where it used to fall through to the owner gate's 401.\n * @category Error Handling\n */\nexport class DerivativeQuestionNotFoundError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_QUESTION_NOT_FOUND\", 404, errorCode, details);\n }\n}\n\n/**\n * Thrown when a builder listed questions without naming a derived scope (400\n * `DERIVATIVE_DERIVED_SCOPE_REQUIRED`).\n *\n * @remarks\n * The unfiltered list is the owner's; a builder may only see its own\n * questions on a scope it may write, so `?derivedScope=` is what the call is\n * authorized against. The SDK refuses an empty `derivedScope` before\n * signing anything ({@link WriteRequestError}), so this is what a hand-built\n * request gets. It is a 400, not the 401 older servers answered, so a client\n * with a re-handshake-on-401 policy does not go through a pointless\n * handshake and then report an authentication problem it does not have.\n * @category Error Handling\n */\nexport class DerivativeDerivedScopeRequiredError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(\n message,\n \"DERIVATIVE_DERIVED_SCOPE_REQUIRED\",\n 400,\n errorCode,\n details,\n );\n }\n}\n\n/**\n * Thrown when a source scope of the question is not read-granted to the\n * builder (403 `DERIVATIVE_SOURCE_NOT_GRANTED`).\n *\n * @remarks\n * The answer exposes the sources to whoever may read the derived scope, so\n * the grant must carry a **bare** read entry for every source scope;\n * `write:` entries confer nothing. `details.scopes` lists the uncovered\n * ones.\n * @category Error Handling\n */\nexport class DerivativeSourceNotGrantedError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_SOURCE_NOT_GRANTED\", 403, errorCode, details);\n }\n}\n\n/**\n * Thrown when the registration would make the derived scope a transitive\n * source of itself through other registrations (409 `DERIVATIVE_CYCLE`), so\n * recompute would never settle. `details.path` is the offending chain.\n * @category Error Handling\n */\nexport class DerivativeCycleError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_CYCLE\", 409, errorCode, details);\n }\n}\n\n/**\n * Thrown when the Personal Server has no compute layer wired (503\n * `DERIVATIVE_COMPUTE_UNAVAILABLE`): it cannot answer questions at all.\n * @category Error Handling\n */\nexport class DerivativeComputeUnavailableError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_COMPUTE_UNAVAILABLE\", 503, errorCode, details);\n }\n}\n\n/**\n * Thrown when a question did not reach `ready` or `failed` within the\n * caller's budget. The question keeps computing on the server; poll it\n * again. `details.status` is the last status seen.\n * @category Error Handling\n */\nexport class DerivativeQuestionTimeoutError extends PersonalServerWriteError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"DERIVATIVE_QUESTION_TIMEOUT\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when a question settled as `failed`.\n *\n * @remarks\n * `details.error` is the Personal Server's short failure reason (a status\n * code, a scope name, an error class); the prompt and the data are never\n * part of it. A failed question is recomputed on the next source change or\n * an explicit recompute.\n * @category Error Handling\n */\nexport class DerivativeQuestionFailedError extends PersonalServerWriteError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"DERIVATIVE_QUESTION_FAILED\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when a DataRegistryV2 data point has been deleted (tombstoned).\n *\n * @remarks\n * Raised by gateway reads that hit HTTP 410, by Personal Server reads of a\n * deleted scope, and by any SDK read helper that would otherwise hand a\n * tombstone back to the caller as if it were data. Pass\n * `includeDeleted: true` to the gateway read helpers to opt in to seeing the\n * tombstone row (with its `deletedAt`) instead of this error.\n * @category Error Handling\n */\nexport class DataPointDeletedError extends VanaError {\n constructor(\n message: string,\n public readonly details: {\n dataPointId?: string;\n scope?: string;\n ownerAddress?: string;\n deletedAt?: string | null;\n } = {},\n ) {\n super(message, \"DATA_POINT_DELETED\");\n }\n}\n\n/**\n * Thrown when a data point operation targets a (owner, scope) the gateway\n * has no record of.\n * @category Error Handling\n */\nexport class DataPointNotFoundError extends VanaError {\n constructor(\n message: string,\n public readonly details: {\n dataPointId?: string;\n scope?: string;\n ownerAddress?: string;\n } = {},\n ) {\n super(message, \"DATA_POINT_NOT_FOUND\");\n }\n}\n\n/**\n * Thrown when the gateway rejects a data point write with HTTP 409 because\n * the signed `expectedVersion` is stale.\n *\n * @remarks\n * `currentExpectedVersion` is the version the gateway currently holds (when\n * the gateway surfaced it); re-sign against `currentExpectedVersion + 1`.\n * @category Error Handling\n */\nexport class DataPointVersionConflictError extends VanaError {\n constructor(\n message: string,\n public readonly details: {\n dataPointId?: string;\n scope?: string;\n ownerAddress?: string;\n expectedVersion?: string;\n currentExpectedVersion?: string;\n } = {},\n ) {\n super(message, \"DATA_POINT_VERSION_CONFLICT\");\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base error class for all Vana SDK errors with structured error codes.\n *\n * @remarks\n * This abstract base class provides a foundation for all SDK-specific errors with\n * consistent error codes and stack trace handling. All Vana SDK errors extend this\n * class to provide structured error information that applications can handle\n * programmatically. The error code enables differentiation between error types\n * without relying on string matching.\n * @category Error Handling\n */\nexport class VanaError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n ) {\n super(message);\n this.name = this.constructor.name;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when gasless transaction submission via relayer fails.\n *\n * @remarks\n * This error occurs when the relayer service is unavailable, returns an error,\n * or fails to process a gasless transaction. It includes the HTTP status code\n * and response details when available to help with debugging relayer issues.\n * @category Error Handling\n */\nexport class RelayerError extends VanaError {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly response?: unknown,\n ) {\n super(message, \"RELAYER_ERROR\");\n }\n}\n\n/**\n * Thrown when the user rejects a wallet signature request.\n *\n * @remarks\n * This error occurs when users decline to sign transactions or typed data through\n * their wallet interface. It's a normal part of user interaction and should be\n * handled gracefully by applications without treating it as a system error.\n * @category Error Handling\n */\nexport class UserRejectedRequestError extends VanaError {\n constructor(message: string = \"User rejected the signature request\") {\n super(message, \"USER_REJECTED_REQUEST\");\n }\n}\n\n/**\n * Thrown when the SDK configuration contains invalid or missing parameters.\n *\n * @remarks\n * This error occurs during SDK initialization when required configuration\n * parameters are missing, invalid, or incompatible. Common causes include\n * missing wallet clients, invalid chain IDs, malformed storage provider\n * configurations, or incompatible parameter combinations.\n *\n * Applications should catch this error during initialization and provide\n * clear feedback to users about configuration requirements.\n *\n * @example\n * ```typescript\n * try {\n * const vana = Vana({\n * chainId: 999999, // Invalid chain ID\n * account: null // Missing account\n * });\n * } catch (error) {\n * if (error instanceof InvalidConfigurationError) {\n * console.error('Configuration error:', error.message);\n * // Show user-friendly configuration help\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class InvalidConfigurationError extends VanaError {\n constructor(message: string) {\n super(message, \"INVALID_CONFIGURATION\");\n }\n}\n\n/**\n * Thrown when a required Vana protocol contract is not deployed on the current chain.\n *\n * @remarks\n * This error occurs when attempting to interact with contracts that are not\n * available on the connected blockchain network. It includes the contract name\n * and chain ID to help identify deployment issues or incorrect network configuration.\n * @category Error Handling\n */\nexport class ContractNotFoundError extends VanaError {\n constructor(contractName: string, chainId: number) {\n super(\n `Contract ${contractName} not found on chain ${chainId}`,\n \"CONTRACT_NOT_FOUND\",\n );\n }\n}\n\n/**\n * Thrown when blockchain operations fail due to network, contract, or transaction issues.\n *\n * @remarks\n * This error encompasses various blockchain-related failures including network\n * connectivity issues, contract execution failures, insufficient gas, invalid\n * transaction parameters, or smart contract reverts. The original error is\n * preserved to provide detailed debugging information while maintaining a\n * consistent SDK error interface.\n *\n * Common causes:\n * - Network connectivity problems\n * - Insufficient gas or gas price too low\n * - Contract function reverts\n * - Invalid transaction parameters\n * - Blockchain congestion or downtime\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.grant({\n * grantee: '0x742d35...',\n * operation: 'read'\n * });\n * } catch (error) {\n * if (error instanceof BlockchainError) {\n * console.error('Blockchain operation failed:', error.message);\n *\n * // Check if it's a network issue\n * if (error.originalError?.message.includes('network')) {\n * // Retry with exponential backoff\n * await retryOperation();\n * }\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class BlockchainError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"BLOCKCHAIN_ERROR\");\n }\n}\n\n/**\n * Thrown when data serialization or deserialization operations fail.\n *\n * @remarks\n * This error occurs when the SDK cannot properly serialize parameters for\n * blockchain transactions, IPFS storage, or API calls. Common causes include\n * circular references in objects, unsupported data types, or malformed JSON.\n * It's typically encountered during grant file creation, storage operations,\n * or when preparing transaction data.\n *\n * @example\n * ```typescript\n * try {\n * // Object with circular reference causes serialization error\n * const obj = { name: 'test' };\n * obj.self = obj; // Circular reference\n *\n * await vana.data.upload({\n * content: obj,\n * filename: 'data.json'\n * });\n * } catch (error) {\n * if (error instanceof SerializationError) {\n * console.error('Data serialization failed:', error.message);\n * // Clean data before retry\n * const cleanedData = removeCircularReferences(obj);\n * await vana.data.upload({\n * content: cleanedData,\n * filename: 'data.json'\n * });\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class SerializationError extends VanaError {\n constructor(message: string) {\n super(message, \"SERIALIZATION_ERROR\");\n }\n}\n\n/**\n * Thrown when a signature operation fails or cannot be completed.\n *\n * @remarks\n * This error occurs when wallet signature operations fail due to disconnection,\n * locked accounts, or other wallet-related issues. It preserves the original\n * error for debugging while providing consistent error handling across the SDK.\n *\n * Recovery strategies:\n * - Check wallet connection and account unlock status\n * - Retry operation with explicit user interaction\n * - For gasless operations, consider switching to direct transactions\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.grant({ grantee: '0x...' });\n * } catch (error) {\n * if (error instanceof SignatureError) {\n * // Prompt user to unlock wallet\n * await promptWalletUnlock();\n * // Retry operation\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class SignatureError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"SIGNATURE_ERROR\");\n }\n}\n\n/**\n * Thrown when network communication fails during API calls or blockchain interactions.\n *\n * @remarks\n * This error encompasses network connectivity issues, API unavailability,\n * timeout errors, and CORS restrictions. It's commonly encountered during\n * IPFS operations, subgraph queries, or RPC calls.\n *\n * Recovery strategies:\n * - Check network connectivity\n * - Retry with exponential backoff\n * - Verify API endpoints are accessible\n * - Switch to alternative network providers or gateways\n *\n * @example\n * ```typescript\n * try {\n * const files = await vana.data.getUserFiles({ owner: '0x...' });\n * } catch (error) {\n * if (error instanceof NetworkError) {\n * // Implement retry with exponential backoff\n * await retryWithBackoff(() => vana.data.getUserFiles({ owner: '0x...' }));\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class NetworkError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"NETWORK_ERROR\");\n }\n}\n\n/**\n * Thrown when transaction nonce retrieval fails during gasless operations.\n *\n * @remarks\n * This error occurs when the SDK cannot retrieve the user's current nonce from\n * smart contracts, preventing gasless transaction submission. Nonces are critical\n * for preventing replay attacks in signed transactions.\n *\n * Recovery strategies:\n * - Retry nonce retrieval after brief delay\n * - Check wallet connection and account status\n * - Use manual nonce specification if supported by the operation\n * - Switch to direct transactions as fallback\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.grant({ grantee: '0x...' });\n * } catch (error) {\n * if (error instanceof NonceError) {\n * // Wait and retry\n * await delay(1000);\n * await vana.permissions.grant({ grantee: '0x...' });\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class NonceError extends VanaError {\n constructor(message: string) {\n super(message, \"NONCE_ERROR\");\n }\n}\n\n/**\n * Thrown when personal server operations fail or cannot be completed.\n *\n * @remarks\n * This error occurs during interactions with personal servers for computation\n * requests, identity retrieval, or operation status checks. Common causes include\n * server unavailability, untrusted server status, or invalid permission grants.\n *\n * Recovery strategies:\n * - Verify server URL accessibility\n * - Check server trust status via `vana.permissions.getTrustedServers()`\n * - Ensure valid permissions exist for the operation\n * - Retry after server becomes available\n *\n * @example\n * ```typescript\n * try {\n * const result = await vana.server.createOperation({ permissionId: 123 });\n * } catch (error) {\n * if (error instanceof PersonalServerError) {\n * // Check if server is trusted\n * const trustedServers = await vana.permissions.getTrustedServers();\n * if (!trustedServers.includes(serverId)) {\n * await vana.permissions.trustServer({ serverId });\n * }\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class PersonalServerError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"PERSONAL_SERVER_ERROR\");\n }\n}\n\n/**\n * Thrown when attempting to register a server with a URL different from its existing registration.\n *\n * @remarks\n * This error occurs when trying to add or trust a server that's already registered\n * on-chain with a different URL. Server URLs are immutable once registered to\n * maintain consistency and security. Applications should use the existing URL\n * or register a new server with a different ID.\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.addAndTrustServer({\n * serverId: 1,\n * serverUrl: 'https://new-url.com',\n * publicKey: '0x...'\n * });\n * } catch (error) {\n * if (error instanceof ServerUrlMismatchError) {\n * console.log(`Server already registered with: ${error.existingUrl}`);\n * // Use existing URL or register new server\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class ServerUrlMismatchError extends VanaError {\n constructor(existingUrl: string, providedUrl: string, serverId: string) {\n super(\n `Server ${serverId} is already registered with URL \"${existingUrl}\". Cannot change to \"${providedUrl}\".`,\n \"SERVER_URL_MISMATCH\",\n );\n this.existingUrl = existingUrl;\n this.providedUrl = providedUrl;\n this.serverId = serverId;\n }\n\n public readonly existingUrl: string;\n public readonly providedUrl: string;\n public readonly serverId: string;\n}\n\n/**\n * Thrown when permission grant, revoke, or validation operations fail.\n *\n * @remarks\n * This error occurs during permission management operations including grants,\n * revocations, and permission validation checks. Common causes include invalid\n * grantee addresses, expired permissions, or insufficient privileges.\n *\n * @example\n * ```typescript\n * try {\n * await vana.permissions.revoke({ permissionId: 999999 });\n * } catch (error) {\n * if (error instanceof PermissionError) {\n * console.error('Permission operation failed:', error.message);\n * // Permission may not exist or user may not be owner\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class PermissionError extends VanaError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n ) {\n super(message, \"PERMISSION_ERROR\");\n }\n}\n\n/**\n * Thrown when attempting to perform write operations without a wallet client.\n *\n * @remarks\n * This error occurs when trying to execute operations that require wallet\n * interaction (signing, encrypting, or submitting transactions) while the SDK\n * is initialized in read-only mode without a wallet client. To perform write\n * operations, the SDK must be initialized with a wallet client.\n *\n * Common operations that require a wallet:\n * - Signing transactions or typed data\n * - Encrypting or decrypting files\n * - Granting or revoking permissions\n * - Uploading data to IPFS\n * - Submitting blockchain transactions\n *\n * @example\n * ```typescript\n * try {\n * // This will throw if no wallet client is provided\n * await vana.data.decryptFile({ fileId: 'abc123' });\n * } catch (error) {\n * if (error instanceof ReadOnlyError) {\n * console.error(`Cannot ${error.operation}: ${error.message}`);\n * // Initialize with wallet client to enable write operations\n * const vanaWithWallet = Vana({\n * walletClient: createWalletClient(...)\n * });\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class ReadOnlyError extends VanaError {\n constructor(\n operation: string,\n suggestion: string = \"Initialize the SDK with a walletClient to perform this operation\",\n ) {\n super(\n `Operation '${operation}' requires a wallet client. ${suggestion}`,\n \"READ_ONLY_ERROR\",\n );\n this.operation = operation;\n this.suggestion = suggestion;\n }\n\n /** The operation that was attempted */\n public readonly operation: string;\n /** Suggested solution for fixing the error */\n public readonly suggestion: string;\n}\n\n/**\n * Thrown when a long-running transaction operation times out or fails during polling.\n *\n * @remarks\n * This error occurs when asynchronous relayer operations exceed the configured timeout\n * or encounter non-recoverable errors during status polling. It preserves the operation ID\n * to allow recovery and status checking at a later time.\n *\n * The error includes:\n * - Operation ID for recovery and status checking\n * - Last known status before failure\n * - Original error details\n *\n * Recovery strategies:\n * - Save the operation ID for later status checking\n * - Implement manual recovery flow using the operation ID\n * - Check transaction status through alternative means\n * - Contact support if operation remains stuck\n *\n * @example\n * ```typescript\n * try {\n * const result = await vana.permissions.grant({\n * grantee: '0x...',\n * files: [1, 2, 3]\n * });\n * } catch (error) {\n * if (error instanceof TransactionPendingError) {\n * // Save operation ID for recovery\n * localStorage.setItem('pending_operation', error.operationId);\n *\n * // Show recovery UI\n * showRecoveryDialog({\n * operationId: error.operationId,\n * lastStatus: error.lastKnownStatus\n * });\n *\n * // Attempt recovery later\n * const status = await vana.checkOperationStatus(error.operationId);\n * }\n * }\n * ```\n * @category Error Handling\n */\nexport class TransactionPendingError extends VanaError {\n constructor(\n /** The operation ID that can be used for status checking */\n public readonly operationId: string,\n message: string,\n /** The last known status of the operation before failure */\n public readonly lastKnownStatus?: unknown,\n ) {\n super(\n `Transaction operation pending: ${message} (operationId: ${operationId})`,\n \"TRANSACTION_PENDING\",\n );\n }\n\n /**\n * Converts the error to a JSON-serializable format.\n *\n * @remarks\n * Useful for logging, storage, or transmission of error details.\n *\n * @returns JSON representation of the error\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n operationId: this.operationId,\n lastKnownStatus: this.lastKnownStatus,\n };\n }\n}\n\n/**\n * Personal Server error codes a Write API call can surface in\n * {@link PersonalServerWriteError.errorCode}.\n *\n * @remarks\n * The `WRITE_*` and `LINEAGE_*` codes are specific to the Write API; the\n * rest are the shared protocol codes the write policy reuses. The string\n * escape hatch keeps codes introduced by a newer Personal Server readable.\n * @category Error Handling\n */\nexport type PersonalServerWriteErrorCode =\n | \"WRITE_SESSION_AUTH_FAILED\"\n | \"WRITE_SESSION_PROOF_REQUIRED\"\n | \"WRITE_SESSION_PROOF_REPLAY\"\n | \"GRANT_ID_REQUIRED\"\n | \"WRITE_ATTRIBUTION_REQUIRED\"\n | \"WRITE_ATTRIBUTION_INVALID\"\n | \"WRITE_ATTRIBUTION_SIGNER_MISMATCH\"\n | \"WRITE_ATTRIBUTION_GRANT_MISMATCH\"\n | \"WRITE_ATTRIBUTION_REPLAY\"\n | \"WRITE_BODY_NOT_CANONICAL\"\n | \"LINEAGE_INVALID\"\n | \"LINEAGE_SCOPE_UNDER_SOURCE_PREFIX\"\n | \"LINEAGE_SOURCE_UNKNOWN\"\n | \"LINEAGE_SOURCE_LOOKUP_FAILED\"\n | \"LINEAGE_FORBIDDEN\"\n | \"LINEAGE_GATEWAY_ERROR\"\n | \"LINEAGE_UNAVAILABLE\"\n | \"LINEAGE_CASCADE_UNAVAILABLE\"\n | \"LINEAGE_SIGNATURE_REQUIRED\"\n | \"LINEAGE_SIGNATURE_INVALID\"\n | \"INVALID_CASCADE\"\n | \"INVALID_VERSION\"\n | \"NOT_FOUND\"\n | \"MISSING_AUTH\"\n | \"INVALID_SIGNATURE\"\n | \"UNREGISTERED_BUILDER\"\n | \"GRANT_REQUIRED\"\n | \"GRANT_REVOKED\"\n | \"GRANT_EXPIRED\"\n | \"GRANT_OWNER_MISMATCH\"\n | \"SCOPE_MISMATCH\"\n | \"INVALID_BODY\"\n | \"CONTENT_TOO_LARGE\"\n | \"PS_UNAVAILABLE\"\n | \"SERVER_NOT_CONFIGURED\"\n | \"INTERNAL_ERROR\"\n | \"DERIVATIVE_QUESTION_INVALID\"\n | \"DERIVATIVE_QUESTION_NOT_FOUND\"\n | \"DERIVATIVE_DERIVED_SCOPE_REQUIRED\"\n | \"DERIVATIVE_CYCLE\"\n | \"DERIVATIVE_SOURCE_NOT_GRANTED\"\n | \"DERIVATIVE_COMPUTE_UNAVAILABLE\"\n | \"METHOD_NOT_ALLOWED\"\n | (string & {});\n\n/**\n * Base class for every Personal Server Write API failure, including the\n * derivative question routes that authenticate with the same credential.\n *\n * @remarks\n * `status` is the HTTP status the Personal Server answered with (absent for\n * failures raised before a request was sent or when no response arrived),\n * `errorCode` is the Personal Server's protocol error code when the body\n * carried one, and `details` is the server-supplied detail object.\n * @category Error Handling\n */\nexport class PersonalServerWriteError extends VanaError {\n constructor(\n message: string,\n code: string,\n public readonly status?: number,\n public readonly errorCode: PersonalServerWriteErrorCode | null = null,\n public readonly details?: Record<string, unknown>,\n ) {\n super(message, code);\n }\n}\n\n/**\n * Thrown before any request is sent when the write input is invalid: no\n * payload, a payload that is not a JSON object, a reserved `$writtenBy` /\n * `$lineage` key, a malformed lineage source id, or an unusable signer.\n * @category Error Handling\n */\nexport class WriteRequestError extends PersonalServerWriteError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"WRITE_INVALID_REQUEST\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when the transport failed (fetch threw) on every attempt.\n *\n * @remarks\n * A write whose response was lost may still have been stored: the Personal\n * Server commits before answering. Check the scope before re-sending the\n * same record.\n * @category Error Handling\n */\nexport class WriteTransportError extends PersonalServerWriteError {\n constructor(\n message: string,\n public readonly attempts: number,\n cause?: unknown,\n ) {\n super(message, \"WRITE_TRANSPORT_ERROR\", undefined, null, { attempts });\n this.cause = cause;\n }\n}\n\n/**\n * Thrown when `POST /v1/write/session` refused the handshake (any non-2xx),\n * or answered with a body the SDK cannot read.\n * @category Error Handling\n */\nexport class WriteSessionError extends PersonalServerWriteError {\n constructor(\n message: string,\n status?: number,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_SESSION_REJECTED\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown by {@link writeData} when the session's bearer token has passed its\n * `expires_in` lifetime. Open a new session; nothing was sent.\n * @category Error Handling\n */\nexport class WriteSessionExpiredError extends PersonalServerWriteError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"WRITE_SESSION_EXPIRED\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when a write answered 401.\n *\n * @remarks\n * `WRITE_ATTRIBUTION_*` codes describe the per-write proof. A plain\n * `INVALID_SIGNATURE` or `MISSING_AUTH` on a write usually means the session\n * token is no longer known to the Personal Server (expired, or the server\n * restarted and dropped its in-memory sessions): open a new session.\n * @category Error Handling\n */\nexport class WriteUnauthorizedError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_UNAUTHORIZED\", 401, errorCode, details);\n }\n}\n\n/**\n * Thrown when a write answered 403: the live grant no longer authorizes it\n * (revoked, expired, wrong owner) or the scope is outside its write patterns.\n * @category Error Handling\n */\nexport class WriteForbiddenError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_FORBIDDEN\", 403, errorCode, details);\n }\n}\n\n/**\n * Thrown when a write answered 409 (the record conflicts with server state).\n * @category Error Handling\n */\nexport class WriteConflictError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_CONFLICT\", 409, errorCode, details);\n }\n}\n\n/**\n * Thrown when the Personal Server rejected the write's lineage: 422\n * `LINEAGE_SOURCE_UNKNOWN` (`details.unknown` lists the offending ids), 400\n * `LINEAGE_INVALID` / `LINEAGE_SCOPE_UNDER_SOURCE_PREFIX`, or 502\n * `LINEAGE_SOURCE_LOOKUP_FAILED`.\n * @category Error Handling\n */\nexport class WriteLineageError extends PersonalServerWriteError {\n constructor(\n message: string,\n status = 422,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_LINEAGE_REJECTED\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown when a write answered any other non-2xx status (400 for a body the\n * server cannot store, 413 for an oversized payload, 5xx).\n * @category Error Handling\n */\nexport class WriteRejectedError extends PersonalServerWriteError {\n constructor(\n message: string,\n status: number,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"WRITE_REJECTED\", status, errorCode, details);\n }\n}\n\n/** Gateway error codes surfaced by the builder jobs client. */\nexport type JobGatewayErrorCode =\n | \"INVALID_WAIT\"\n | \"INVALID_BODY\"\n | \"BUILDER_UNKNOWN\"\n | \"GRANT_INVALID\"\n | \"OWNER_NOT_READY\"\n | \"BODY_TOO_LARGE\"\n | \"JOB_ID_MISMATCH\"\n | \"JOB_ID_TAKEN\"\n | \"JOB_NOT_FOUND\"\n | (string & {});\n\n/**\n * Base class for failures raised by the builder jobs client.\n *\n * @remarks\n * `status` is the Gateway HTTP status when a response arrived, `errorCode`\n * is the Gateway protocol code when one was supplied, and `details` retains\n * structured response or client context for diagnostics.\n *\n * @param message - Human-readable failure description.\n * @param code - Stable SDK error code.\n * @param status - Gateway HTTP status, when available.\n * @param errorCode - Gateway protocol error code, when available.\n * @param details - Additional structured context.\n * @category Error Handling\n */\nexport class JobsClientError extends VanaError {\n constructor(\n message: string,\n code: string,\n public readonly status?: number,\n public readonly errorCode: JobGatewayErrorCode | null = null,\n public readonly details?: Record<string, unknown>,\n ) {\n super(message, code);\n }\n}\n\n/**\n * Thrown when the Gateway does not recognize the signing builder (403\n * `BUILDER_UNKNOWN`).\n *\n * @param message - Gateway failure description.\n * @param details - Additional structured Gateway context.\n * @category Error Handling\n */\nexport class BuilderUnknownError extends JobsClientError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"JOB_BUILDER_UNKNOWN\", 403, \"BUILDER_UNKNOWN\", details);\n }\n}\n\n/**\n * Thrown when the supplied grant does not authorize the requested raw read\n * (403 `GRANT_INVALID`).\n *\n * @param message - Gateway failure description.\n * @param details - Additional structured Gateway context.\n * @category Error Handling\n */\nexport class GrantInvalidError extends JobsClientError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"JOB_GRANT_INVALID\", 403, \"GRANT_INVALID\", details);\n }\n}\n\n/**\n * Thrown when the owner's enclave identity is not ready to accept encrypted\n * jobs, either locally after the identity lookup or as a 403 Gateway answer.\n *\n * @param message - Identity readiness failure description.\n * @param details - Additional identity or Gateway context.\n * @category Error Handling\n */\nexport class OwnerNotReadyError extends JobsClientError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"JOB_OWNER_NOT_READY\", 403, \"OWNER_NOT_READY\", details);\n }\n}\n\n/**\n * Thrown when a freshly generated job id already exists at the Gateway (409\n * `JOB_ID_TAKEN`).\n *\n * @param message - Gateway conflict description.\n * @param details - Additional structured Gateway context.\n * @category Error Handling\n */\nexport class JobIdTakenError extends JobsClientError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"JOB_ID_TAKEN\", 409, \"JOB_ID_TAKEN\", details);\n }\n}\n\n/**\n * Thrown when a job is unknown or belongs to another builder (404\n * `JOB_NOT_FOUND`).\n *\n * @param message - Gateway not-found description.\n * @param details - Additional structured Gateway context.\n * @category Error Handling\n */\nexport class JobNotFoundError extends JobsClientError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"JOB_NOT_FOUND\", 404, \"JOB_NOT_FOUND\", details);\n }\n}\n\n/**\n * Thrown when a job submission exceeds the Gateway request limit (413).\n *\n * @param message - Gateway size-limit description.\n * @param errorCode - Gateway protocol error code.\n * @param details - Additional structured Gateway context.\n * @category Error Handling\n */\nexport class JobRequestTooLargeError extends JobsClientError {\n constructor(\n message: string,\n errorCode: JobGatewayErrorCode | null = \"BODY_TOO_LARGE\",\n details?: Record<string, unknown>,\n ) {\n super(message, \"JOB_REQUEST_TOO_LARGE\", 413, errorCode, details);\n }\n}\n\n/**\n * Thrown when a job does not reach a terminal state within the caller's wait\n * budget or before the job's own deadline.\n *\n * @param message - Timeout description.\n * @param details - Last known job state and timing context.\n * @category Error Handling\n */\nexport class JobTimeoutError extends JobsClientError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"JOB_TIMEOUT\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when fetched job-result bytes do not match their object handle.\n *\n * @param message - Integrity failure description.\n * @param details - Expected and actual result metadata.\n * @category Error Handling\n */\nexport class JobResultIntegrityError extends JobsClientError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"JOB_RESULT_INTEGRITY\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when the Gateway rejects a jobs request, returns an undocumented\n * response, or client input cannot form a valid jobs request.\n *\n * @param message - Rejection description.\n * @param status - Gateway HTTP status, when available.\n * @param errorCode - Gateway protocol error code, when available.\n * @param details - Additional structured context.\n * @category Error Handling\n */\nexport class JobRejectedError extends JobsClientError {\n constructor(\n message: string,\n status?: number,\n errorCode: JobGatewayErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"JOB_REJECTED\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown when a jobs client HTTP request fails before a response arrives.\n *\n * @param message - Human-readable transport failure.\n * @param cause - Original value thrown by `fetch`.\n * @category Error Handling\n */\nexport class JobTransportError extends JobsClientError {\n constructor(message: string, cause?: unknown) {\n super(message, \"JOB_TRANSPORT_ERROR\");\n this.cause = cause;\n }\n}\n\n/**\n * Thrown when a lineage read (Personal Server or gateway) fails: a non-2xx\n * answer, a body that is not a lineage graph, a malformed data point id, or\n * a transport failure.\n * @category Error Handling\n */\nexport class LineageReadError extends VanaError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly errorCode: PersonalServerWriteErrorCode | null = null,\n public readonly details?: Record<string, unknown>,\n ) {\n super(message, \"LINEAGE_READ_ERROR\");\n }\n}\n\n/**\n * Thrown when the Personal Server rejected a derivative question with a\n * status the more specific errors do not claim (405, 413\n * `CONTENT_TOO_LARGE`, 5xx), or answered a body the SDK cannot read.\n *\n * @remarks\n * The question routes share the Write API's credential, so their\n * authentication failures are the write errors: {@link WriteUnauthorizedError}\n * (401), {@link WriteForbiddenError} (403 on the derived scope),\n * {@link WriteConflictError} (409 that is not a cycle),\n * {@link WriteRequestError} (refused before sending),\n * {@link WriteTransportError} (`fetch` threw).\n * @category Error Handling\n */\nexport class DerivativeQuestionRejectedError extends PersonalServerWriteError {\n constructor(\n message: string,\n status: number,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_QUESTION_REJECTED\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown when the Personal Server refused a question registration as\n * invalid: 400 `DERIVATIVE_QUESTION_INVALID` (body shape, the scope grammar,\n * 1 to 16 distinct source scopes, an 8000 character question, a model id) or\n * 400 `LINEAGE_SCOPE_UNDER_SOURCE_PREFIX` (the derived scope shares its first\n * dot-segment with a source scope). `details.field` names the offending\n * field when the server sent one.\n * @category Error Handling\n */\nexport class DerivativeQuestionInvalidError extends PersonalServerWriteError {\n constructor(\n message: string,\n status = 400,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_QUESTION_INVALID\", status, errorCode, details);\n }\n}\n\n/**\n * Thrown when a question id is unknown (404\n * `DERIVATIVE_QUESTION_NOT_FOUND`).\n *\n * @remarks\n * A builder only ever sees the questions it registered itself, so a question\n * another builder (or the owner) registered on the same derived scope is a\n * 404 too, not a 403. An id no Personal Server ever held is a 404 as well\n * for any authenticated caller (`personal-server-ts` d91124d and later),\n * where it used to fall through to the owner gate's 401.\n * @category Error Handling\n */\nexport class DerivativeQuestionNotFoundError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_QUESTION_NOT_FOUND\", 404, errorCode, details);\n }\n}\n\n/**\n * Thrown when a builder listed questions without naming a derived scope (400\n * `DERIVATIVE_DERIVED_SCOPE_REQUIRED`).\n *\n * @remarks\n * The unfiltered list is the owner's; a builder may only see its own\n * questions on a scope it may write, so `?derivedScope=` is what the call is\n * authorized against. The SDK refuses an empty `derivedScope` before\n * signing anything ({@link WriteRequestError}), so this is what a hand-built\n * request gets. It is a 400, not the 401 older servers answered, so a client\n * with a re-handshake-on-401 policy does not go through a pointless\n * handshake and then report an authentication problem it does not have.\n * @category Error Handling\n */\nexport class DerivativeDerivedScopeRequiredError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(\n message,\n \"DERIVATIVE_DERIVED_SCOPE_REQUIRED\",\n 400,\n errorCode,\n details,\n );\n }\n}\n\n/**\n * Thrown when a source scope of the question is not read-granted to the\n * builder (403 `DERIVATIVE_SOURCE_NOT_GRANTED`).\n *\n * @remarks\n * The answer exposes the sources to whoever may read the derived scope, so\n * the grant must carry a **bare** read entry for every source scope;\n * `write:` entries confer nothing. `details.scopes` lists the uncovered\n * ones.\n * @category Error Handling\n */\nexport class DerivativeSourceNotGrantedError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_SOURCE_NOT_GRANTED\", 403, errorCode, details);\n }\n}\n\n/**\n * Thrown when the registration would make the derived scope a transitive\n * source of itself through other registrations (409 `DERIVATIVE_CYCLE`), so\n * recompute would never settle. `details.path` is the offending chain.\n * @category Error Handling\n */\nexport class DerivativeCycleError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_CYCLE\", 409, errorCode, details);\n }\n}\n\n/**\n * Thrown when the Personal Server has no compute layer wired (503\n * `DERIVATIVE_COMPUTE_UNAVAILABLE`): it cannot answer questions at all.\n * @category Error Handling\n */\nexport class DerivativeComputeUnavailableError extends PersonalServerWriteError {\n constructor(\n message: string,\n errorCode: PersonalServerWriteErrorCode | null = null,\n details?: Record<string, unknown>,\n ) {\n super(message, \"DERIVATIVE_COMPUTE_UNAVAILABLE\", 503, errorCode, details);\n }\n}\n\n/**\n * Thrown when a question did not reach `ready` or `failed` within the\n * caller's budget. The question keeps computing on the server; poll it\n * again. `details.status` is the last status seen.\n * @category Error Handling\n */\nexport class DerivativeQuestionTimeoutError extends PersonalServerWriteError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"DERIVATIVE_QUESTION_TIMEOUT\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when a question settled as `failed`.\n *\n * @remarks\n * `details.error` is the Personal Server's short failure reason (a status\n * code, a scope name, an error class); the prompt and the data are never\n * part of it. A failed question is recomputed on the next source change or\n * an explicit recompute.\n * @category Error Handling\n */\nexport class DerivativeQuestionFailedError extends PersonalServerWriteError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, \"DERIVATIVE_QUESTION_FAILED\", undefined, null, details);\n }\n}\n\n/**\n * Thrown when a DataRegistryV2 data point has been deleted (tombstoned).\n *\n * @remarks\n * Raised by gateway reads that hit HTTP 410, by Personal Server reads of a\n * deleted scope, and by any SDK read helper that would otherwise hand a\n * tombstone back to the caller as if it were data. Pass\n * `includeDeleted: true` to the gateway read helpers to opt in to seeing the\n * tombstone row (with its `deletedAt`) instead of this error.\n * @category Error Handling\n */\nexport class DataPointDeletedError extends VanaError {\n constructor(\n message: string,\n public readonly details: {\n dataPointId?: string;\n scope?: string;\n ownerAddress?: string;\n deletedAt?: string | null;\n } = {},\n ) {\n super(message, \"DATA_POINT_DELETED\");\n }\n}\n\n/**\n * Thrown when a data point operation targets a (owner, scope) the gateway\n * has no record of.\n * @category Error Handling\n */\nexport class DataPointNotFoundError extends VanaError {\n constructor(\n message: string,\n public readonly details: {\n dataPointId?: string;\n scope?: string;\n ownerAddress?: string;\n } = {},\n ) {\n super(message, \"DATA_POINT_NOT_FOUND\");\n }\n}\n\n/**\n * Thrown when the gateway rejects a data point write with HTTP 409 because\n * the signed `expectedVersion` is stale.\n *\n * @remarks\n * `currentExpectedVersion` is the version the gateway currently holds (when\n * the gateway surfaced it); re-sign against `currentExpectedVersion + 1`.\n * @category Error Handling\n */\nexport class DataPointVersionConflictError extends VanaError {\n constructor(\n message: string,\n public readonly details: {\n dataPointId?: string;\n scope?: string;\n ownerAddress?: string;\n expectedVersion?: string;\n currentExpectedVersion?: string;\n } = {},\n ) {\n super(message, \"DATA_POINT_VERSION_CONFLICT\");\n }\n}\n"],"mappings":"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","names":[]}
|