@opendatalabs/vana-sdk 3.18.1 → 3.19.1
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/README.md +141 -0
- package/dist/auth/web3-signed-builder.cjs +3 -0
- package/dist/auth/web3-signed-builder.cjs.map +1 -1
- package/dist/auth/web3-signed-builder.d.ts +14 -0
- package/dist/auth/web3-signed-builder.js +3 -0
- package/dist/auth/web3-signed-builder.js.map +1 -1
- package/dist/errors.cjs +69 -0
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +117 -2
- package/dist/errors.js +60 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.js +577 -29
- package/dist/index.browser.js.map +4 -4
- package/dist/index.node.cjs +605 -29
- package/dist/index.node.cjs.map +4 -4
- package/dist/index.node.d.ts +1 -0
- package/dist/index.node.js +577 -29
- package/dist/index.node.js.map +4 -4
- package/dist/protocol/derivative-questions.cjs +518 -0
- package/dist/protocol/derivative-questions.cjs.map +1 -0
- package/dist/protocol/derivative-questions.d.ts +396 -0
- package/dist/protocol/derivative-questions.js +507 -0
- package/dist/protocol/derivative-questions.js.map +1 -0
- package/dist/protocol/derivative-questions.test.d.ts +1 -0
- package/dist/protocol/personal-server-write.cjs +12 -108
- package/dist/protocol/personal-server-write.cjs.map +1 -1
- package/dist/protocol/personal-server-write.d.ts +2 -17
- package/dist/protocol/personal-server-write.js +7 -98
- package/dist/protocol/personal-server-write.js.map +1 -1
- package/dist/protocol/write-request.cjs +156 -0
- package/dist/protocol/write-request.cjs.map +1 -0
- package/dist/protocol/write-request.d.ts +75 -0
- package/dist/protocol/write-request.js +124 -0
- package/dist/protocol/write-request.js.map +1 -0
- package/dist/tests/mock-personal-server.d.ts +54 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -431,6 +431,147 @@ scope from it; order and count are preserved, so a redacted node is identified
|
|
|
431
431
|
by its position. The SDK refuses a view whose redacted node carries anything
|
|
432
432
|
else. The gateway's `proof` over the served view is passed through.
|
|
433
433
|
|
|
434
|
+
## Derivative questions
|
|
435
|
+
|
|
436
|
+
A **question** is a standing prompt over the user's source scopes. The Personal
|
|
437
|
+
Server answers it locally (the raw sources never leave the machine except
|
|
438
|
+
through its inference call) and writes the answer into a derived scope as an
|
|
439
|
+
ordinary derivative record, with lineage pointing at the sources. The builder
|
|
440
|
+
reads that scope with its normal read grant. Every later change to a source
|
|
441
|
+
recomputes the question, so you register it once and keep reading a scope that
|
|
442
|
+
stays current.
|
|
443
|
+
|
|
444
|
+
One grant carries the whole pipeline, and it needs all three of:
|
|
445
|
+
|
|
446
|
+
- a bare read entry for **every source scope** (the answer exposes them, so a
|
|
447
|
+
registration whose sources are not read-granted is refused with
|
|
448
|
+
`DERIVATIVE_SOURCE_NOT_GRANTED`),
|
|
449
|
+
- a bare read entry for the **derived scope** (to read the answer back),
|
|
450
|
+
- `write:<derivedScope>` (the credential the question routes authorize
|
|
451
|
+
against).
|
|
452
|
+
|
|
453
|
+
For `coach.weekly` computed from `oura.sleep` and `chatgpt.conversations`:
|
|
454
|
+
|
|
455
|
+
```json
|
|
456
|
+
["oura.sleep", "chatgpt.conversations", "coach.weekly", "write:coach.weekly"]
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
The derived scope must not share its first dot-segment with any source scope
|
|
460
|
+
(the same naming rule as a derivative write), so keep derivatives in your app's
|
|
461
|
+
own namespace.
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
465
|
+
import {
|
|
466
|
+
askPersonalServer,
|
|
467
|
+
registerQuestion,
|
|
468
|
+
waitForQuestion,
|
|
469
|
+
listQuestions,
|
|
470
|
+
recomputeQuestion,
|
|
471
|
+
deleteQuestion,
|
|
472
|
+
} from "@opendatalabs/vana-sdk";
|
|
473
|
+
|
|
474
|
+
const signer = privateKeyToAccount(process.env.BUILDER_KEY as `0x${string}`);
|
|
475
|
+
const connection = {
|
|
476
|
+
personalServerUrl: "https://ps.example.com",
|
|
477
|
+
signer,
|
|
478
|
+
grantId, // the grant with the scopes above
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// The whole loop in one call: register, wait for the answer, read it.
|
|
482
|
+
const { registration, record } = await askPersonalServer({
|
|
483
|
+
...connection,
|
|
484
|
+
derivedScope: "coach.weekly",
|
|
485
|
+
sourceScopes: ["oura.sleep", "chatgpt.conversations"],
|
|
486
|
+
question: "How did my sleep relate to my mood this week?",
|
|
487
|
+
model: "z-ai/glm-5.2", // optional; the server has a default
|
|
488
|
+
});
|
|
489
|
+
console.log(record.data.answer);
|
|
490
|
+
|
|
491
|
+
// Or drive the steps yourself.
|
|
492
|
+
const question = await registerQuestion({
|
|
493
|
+
...connection,
|
|
494
|
+
derivedScope: "coach.weekly",
|
|
495
|
+
sourceScopes: ["oura.sleep"],
|
|
496
|
+
question: "How did my sleep trend this week?",
|
|
497
|
+
});
|
|
498
|
+
const settled = await waitForQuestion({
|
|
499
|
+
...connection,
|
|
500
|
+
questionId: question.questionId,
|
|
501
|
+
timeoutMs: 60_000,
|
|
502
|
+
});
|
|
503
|
+
if (settled.status === "failed") {
|
|
504
|
+
console.error(settled.error);
|
|
505
|
+
await recomputeQuestion({ ...connection, questionId: question.questionId });
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Later runs: the question is already registered, so just read the scope
|
|
509
|
+
// again, or list what this builder registered on it.
|
|
510
|
+
const mine = await listQuestions({
|
|
511
|
+
...connection,
|
|
512
|
+
derivedScope: "coach.weekly",
|
|
513
|
+
});
|
|
514
|
+
await deleteQuestion({ ...connection, questionId: question.questionId });
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
What the SDK does for you:
|
|
518
|
+
|
|
519
|
+
- Opens **one** write session per `{ signer, Personal Server, grant }`
|
|
520
|
+
(`POST /v1/write/session`) and reuses it for every question call, including
|
|
521
|
+
each poll of `waitForQuestion`.
|
|
522
|
+
- Signs a fresh, single-use `X-Vana-Write-Signature` proof for every request
|
|
523
|
+
(the grant id is a signed claim).
|
|
524
|
+
- Puts a fresh `nonce` claim on every proof. **Polling needs it**: a proof
|
|
525
|
+
payload is otherwise fully determined by
|
|
526
|
+
`{aud, method, uri, bodyHash, grantId, iat, exp}`, so two identical
|
|
527
|
+
`GET /questions/:id` polls signed inside the same second are byte-identical
|
|
528
|
+
and the Personal Server refuses the second as a replay
|
|
529
|
+
(`WRITE_ATTRIBUTION_REPLAY`). With a nonce the replay key is
|
|
530
|
+
`(builder, nonce)` instead, and each poll is distinct. Every helper here
|
|
531
|
+
does it for you, `waitForQuestion` included; a hand-built question request
|
|
532
|
+
must pass `nonce` to `buildWeb3SignedHeader` itself.
|
|
533
|
+
- Signs the whole request **target**, query string included, because
|
|
534
|
+
`?derivedScope=` is what the list route authorizes against. The target is
|
|
535
|
+
built once and used for both the signed `uri` claim and the URL, so the
|
|
536
|
+
signature and the request can never name different scopes.
|
|
537
|
+
- Re-opens the session once and replays the call when the Personal Server
|
|
538
|
+
answers a 401 the **session** is responsible for: it keeps sessions in
|
|
539
|
+
memory and forgets them when it restarts. A 401 about the **proof** (it
|
|
540
|
+
does not cover this request, its nonce is spent, it recovers to another
|
|
541
|
+
key) is surfaced as it is, since a new session would not change it.
|
|
542
|
+
- Sends bodies as compact JSON, which the server requires
|
|
543
|
+
(`WRITE_BODY_NOT_CANONICAL` otherwise).
|
|
544
|
+
- Validates the registration (scope list, question length, model id, the
|
|
545
|
+
naming rule) before anything is signed.
|
|
546
|
+
|
|
547
|
+
`waitForQuestion` polls until the question is `ready` or `failed` and returns
|
|
548
|
+
that state; a failed one carries a short `error` (never the prompt or the
|
|
549
|
+
data) and is retried with `recomputeQuestion`. `askPersonalServer` throws
|
|
550
|
+
`DerivativeQuestionFailedError` instead, since it has no record to return, and
|
|
551
|
+
reads the derived scope with the plain Web3Signed read; for a priced grant,
|
|
552
|
+
settle the 402 with the escrow-aware read from `@opendatalabs/vana-sdk/server`
|
|
553
|
+
and use `registerQuestion` + `waitForQuestion` directly.
|
|
554
|
+
|
|
555
|
+
Errors are typed and carry the server's `status`, `errorCode` and `details`:
|
|
556
|
+
`DerivativeSourceNotGrantedError` (403, `details.scopes` lists the uncovered
|
|
557
|
+
sources), `DerivativeCycleError` (409, the question would make the derived
|
|
558
|
+
scope a transitive source of itself), `DerivativeQuestionNotFoundError` (404,
|
|
559
|
+
including another builder's question on the same scope),
|
|
560
|
+
`DerivativeQuestionInvalidError` (400), `DerivativeDerivedScopeRequiredError`
|
|
561
|
+
(400 `DERIVATIVE_DERIVED_SCOPE_REQUIRED`, a builder list with no
|
|
562
|
+
`?derivedScope=`; the SDK refuses an empty one before signing),
|
|
563
|
+
`DerivativeComputeUnavailableError` (503, no compute layer on that server),
|
|
564
|
+
`DerivativeQuestionTimeoutError`, `DerivativeQuestionFailedError`, and
|
|
565
|
+
`DerivativeQuestionRejectedError` for anything else. Authentication failures
|
|
566
|
+
are the Write API's own `WriteUnauthorizedError`, `WriteForbiddenError`,
|
|
567
|
+
`WriteRequestError` (refused before sending) and `WriteTransportError`. An
|
|
568
|
+
**unknown** question id is a `DerivativeQuestionNotFoundError` (404), the
|
|
569
|
+
same as another builder's question.
|
|
570
|
+
|
|
571
|
+
These helpers require `personal-server-ts` main `d91124d` or later, which is
|
|
572
|
+
where the query-in-the-signed-uri rule, the `nonce` claim, the 404 for an
|
|
573
|
+
unknown id and the full-view `recompute` answer landed.
|
|
574
|
+
|
|
434
575
|
## Networks
|
|
435
576
|
|
|
436
577
|
| Network | Chain ID | RPC URL |
|
|
@@ -52,6 +52,9 @@ async function buildWeb3SignedHeader(params) {
|
|
|
52
52
|
if (params.grantId !== void 0) {
|
|
53
53
|
payload["grantId"] = params.grantId;
|
|
54
54
|
}
|
|
55
|
+
if (params.nonce !== void 0) {
|
|
56
|
+
payload["nonce"] = params.nonce;
|
|
57
|
+
}
|
|
55
58
|
const sortedPayload = Object.keys(payload).sort().reduce((acc, key) => {
|
|
56
59
|
acc[key] = payload[key];
|
|
57
60
|
return acc;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/web3-signed-builder.ts"],"sourcesContent":["/**\n * Builder for Web3Signed Authorization headers.\n *\n * @remarks\n * Ported from `personal-server-ts`\n * (`packages/core/src/signing/request-signer.ts`). The original was wired\n * to a Node-only `ServerAccount` and `node:crypto`. This isomorphic version\n * accepts any `signMessage` callback (viem accounts, wallet clients, etc.)\n * and uses `@noble/hashes` for SHA-256 so it runs in browsers and Workers.\n *\n * Wire format is identical to PS — payload is JSON with sorted keys,\n * base64url-encoded, signed via EIP-191.\n *\n * @category Auth\n */\n\nimport { sha256 } from \"@noble/hashes/sha2\";\nimport { bytesToHex } from \"viem\";\nimport { toBase64 } from \"../utils/encoding\";\n\n/**\n * Sign-message callback compatible with viem `LocalAccount`/`WalletClient`-style\n * signers. Must produce an EIP-191 (`personal_sign`) signature.\n */\nexport type Web3SignedSignFn = (message: string) => Promise<`0x${string}`>;\n\n/** SHA-256 of the empty string — bodyHash for empty bodies. */\nconst EMPTY_BODY_HASH =\n \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\n\n/** Default token lifetime (seconds). */\nconst DEFAULT_TTL_SECONDS = 300;\n\n/** Base64url encode bytes (no padding). */\nfunction base64urlEncode(input: Uint8Array): string {\n return toBase64(input)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/** Compute the `sha256:<hex>` bodyHash claim for a request body. */\nexport function computeBodyHash(body: Uint8Array | undefined): string {\n if (!body || body.length === 0) {\n return EMPTY_BODY_HASH;\n }\n const digest = sha256(body);\n return `sha256:${bytesToHex(digest).slice(2)}`;\n}\n\n/**\n * Build a Web3Signed Authorization header value.\n *\n * @returns The full header value (`\"Web3Signed <base64url>.<sig>\"`).\n */\nexport async function buildWeb3SignedHeader(params: {\n /** EIP-191 signer (e.g. viem `account.signMessage`). */\n signMessage: Web3SignedSignFn;\n /** Expected origin (e.g. `\"https://ps.example.com\"`). */\n aud: string;\n /** HTTP method (e.g. `\"GET\"`). */\n method: string;\n /** Request URI/path (e.g. `\"/v1/data/instagram.profile\"`). */\n uri: string;\n /** Optional request body — when present, used to compute `bodyHash`. */\n body?: Uint8Array;\n /** Issued-at (unix seconds). Defaults to now. */\n iat?: number;\n /** Expiry (unix seconds). Defaults to `iat + 300`. */\n exp?: number;\n /** Optional grant id, attached as the `grantId` claim. */\n grantId?: string;\n /** Pre-computed `bodyHash` claim — overrides `body`. */\n bodyHash?: string;\n}): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n const iat = params.iat ?? now;\n const exp = params.exp ?? iat + DEFAULT_TTL_SECONDS;\n\n const payload: Record<string, unknown> = {\n aud: params.aud,\n bodyHash: params.bodyHash ?? computeBodyHash(params.body),\n exp,\n iat,\n method: params.method,\n uri: params.uri,\n };\n\n if (params.grantId !== undefined) {\n payload[\"grantId\"] = params.grantId;\n }\n\n // Sort keys for deterministic serialization.\n const sortedPayload = Object.keys(payload)\n .sort()\n .reduce<Record<string, unknown>>((acc, key) => {\n acc[key] = payload[key];\n return acc;\n }, {});\n\n const payloadJson = JSON.stringify(sortedPayload);\n const payloadBytes = new TextEncoder().encode(payloadJson);\n const payloadBase64 = base64urlEncode(payloadBytes);\n\n const signature = await params.signMessage(payloadBase64);\n\n return `Web3Signed ${payloadBase64}.${signature}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,kBAAuB;AACvB,kBAA2B;AAC3B,sBAAyB;AASzB,MAAM,kBACJ;AAGF,MAAM,sBAAsB;AAG5B,SAAS,gBAAgB,OAA2B;AAClD,aAAO,0BAAS,KAAK,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,EAAE;AACtB;AAGO,SAAS,gBAAgB,MAAsC;AACpE,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,aAAS,oBAAO,IAAI;AAC1B,SAAO,cAAU,wBAAW,MAAM,EAAE,MAAM,CAAC,CAAC;AAC9C;AAOA,eAAsB,sBAAsB,
|
|
1
|
+
{"version":3,"sources":["../../src/auth/web3-signed-builder.ts"],"sourcesContent":["/**\n * Builder for Web3Signed Authorization headers.\n *\n * @remarks\n * Ported from `personal-server-ts`\n * (`packages/core/src/signing/request-signer.ts`). The original was wired\n * to a Node-only `ServerAccount` and `node:crypto`. This isomorphic version\n * accepts any `signMessage` callback (viem accounts, wallet clients, etc.)\n * and uses `@noble/hashes` for SHA-256 so it runs in browsers and Workers.\n *\n * Wire format is identical to PS — payload is JSON with sorted keys,\n * base64url-encoded, signed via EIP-191.\n *\n * @category Auth\n */\n\nimport { sha256 } from \"@noble/hashes/sha2\";\nimport { bytesToHex } from \"viem\";\nimport { toBase64 } from \"../utils/encoding\";\n\n/**\n * Sign-message callback compatible with viem `LocalAccount`/`WalletClient`-style\n * signers. Must produce an EIP-191 (`personal_sign`) signature.\n */\nexport type Web3SignedSignFn = (message: string) => Promise<`0x${string}`>;\n\n/** SHA-256 of the empty string — bodyHash for empty bodies. */\nconst EMPTY_BODY_HASH =\n \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\n\n/** Default token lifetime (seconds). */\nconst DEFAULT_TTL_SECONDS = 300;\n\n/** Base64url encode bytes (no padding). */\nfunction base64urlEncode(input: Uint8Array): string {\n return toBase64(input)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/** Compute the `sha256:<hex>` bodyHash claim for a request body. */\nexport function computeBodyHash(body: Uint8Array | undefined): string {\n if (!body || body.length === 0) {\n return EMPTY_BODY_HASH;\n }\n const digest = sha256(body);\n return `sha256:${bytesToHex(digest).slice(2)}`;\n}\n\n/**\n * Build a Web3Signed Authorization header value.\n *\n * @returns The full header value (`\"Web3Signed <base64url>.<sig>\"`).\n */\nexport async function buildWeb3SignedHeader(params: {\n /** EIP-191 signer (e.g. viem `account.signMessage`). */\n signMessage: Web3SignedSignFn;\n /** Expected origin (e.g. `\"https://ps.example.com\"`). */\n aud: string;\n /** HTTP method (e.g. `\"GET\"`). */\n method: string;\n /** Request URI/path (e.g. `\"/v1/data/instagram.profile\"`). */\n uri: string;\n /** Optional request body — when present, used to compute `bodyHash`. */\n body?: Uint8Array;\n /** Issued-at (unix seconds). Defaults to now. */\n iat?: number;\n /** Expiry (unix seconds). Defaults to `iat + 300`. */\n exp?: number;\n /** Optional grant id, attached as the `grantId` claim. */\n grantId?: string;\n /**\n * Optional uniqueness claim, attached as the `nonce` claim (a uuid is the\n * intended shape; the Personal Server bounds it at 128 characters).\n *\n * @remarks\n * A payload is otherwise fully determined by\n * `{ aud, bodyHash, exp, grantId, iat, method, uri }`, so two identical\n * requests signed inside the same second produce the same bytes and the\n * Personal Server refuses the second as a replay. With a nonce the replay\n * key becomes `(signer, nonce)` instead, which is what lets a poll loop\n * send the same request twice. The nonce is then single use itself:\n * re-using one is a replay even when the rest of the payload changed.\n */\n nonce?: string;\n /** Pre-computed `bodyHash` claim — overrides `body`. */\n bodyHash?: string;\n}): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n const iat = params.iat ?? now;\n const exp = params.exp ?? iat + DEFAULT_TTL_SECONDS;\n\n const payload: Record<string, unknown> = {\n aud: params.aud,\n bodyHash: params.bodyHash ?? computeBodyHash(params.body),\n exp,\n iat,\n method: params.method,\n uri: params.uri,\n };\n\n if (params.grantId !== undefined) {\n payload[\"grantId\"] = params.grantId;\n }\n\n // Merged before the sort, so the nonce sits in its alphabetical place like\n // every other claim and the payload stays deterministic.\n if (params.nonce !== undefined) {\n payload[\"nonce\"] = params.nonce;\n }\n\n // Sort keys for deterministic serialization.\n const sortedPayload = Object.keys(payload)\n .sort()\n .reduce<Record<string, unknown>>((acc, key) => {\n acc[key] = payload[key];\n return acc;\n }, {});\n\n const payloadJson = JSON.stringify(sortedPayload);\n const payloadBytes = new TextEncoder().encode(payloadJson);\n const payloadBase64 = base64urlEncode(payloadBytes);\n\n const signature = await params.signMessage(payloadBase64);\n\n return `Web3Signed ${payloadBase64}.${signature}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,kBAAuB;AACvB,kBAA2B;AAC3B,sBAAyB;AASzB,MAAM,kBACJ;AAGF,MAAM,sBAAsB;AAG5B,SAAS,gBAAgB,OAA2B;AAClD,aAAO,0BAAS,KAAK,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,EAAE;AACtB;AAGO,SAAS,gBAAgB,MAAsC;AACpE,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,aAAS,oBAAO,IAAI;AAC1B,SAAO,cAAU,wBAAW,MAAM,EAAE,MAAM,CAAC,CAAC;AAC9C;AAOA,eAAsB,sBAAsB,QAiCxB;AAClB,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAM,MAAM,OAAO,OAAO;AAC1B,QAAM,MAAM,OAAO,OAAO,MAAM;AAEhC,QAAM,UAAmC;AAAA,IACvC,KAAK,OAAO;AAAA,IACZ,UAAU,OAAO,YAAY,gBAAgB,OAAO,IAAI;AAAA,IACxD;AAAA,IACA;AAAA,IACA,QAAQ,OAAO;AAAA,IACf,KAAK,OAAO;AAAA,EACd;AAEA,MAAI,OAAO,YAAY,QAAW;AAChC,YAAQ,SAAS,IAAI,OAAO;AAAA,EAC9B;AAIA,MAAI,OAAO,UAAU,QAAW;AAC9B,YAAQ,OAAO,IAAI,OAAO;AAAA,EAC5B;AAGA,QAAM,gBAAgB,OAAO,KAAK,OAAO,EACtC,KAAK,EACL,OAAgC,CAAC,KAAK,QAAQ;AAC7C,QAAI,GAAG,IAAI,QAAQ,GAAG;AACtB,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEP,QAAM,cAAc,KAAK,UAAU,aAAa;AAChD,QAAM,eAAe,IAAI,YAAY,EAAE,OAAO,WAAW;AACzD,QAAM,gBAAgB,gBAAgB,YAAY;AAElD,QAAM,YAAY,MAAM,OAAO,YAAY,aAAa;AAExD,SAAO,cAAc,aAAa,IAAI,SAAS;AACjD;","names":[]}
|
|
@@ -42,6 +42,20 @@ export declare function buildWeb3SignedHeader(params: {
|
|
|
42
42
|
exp?: number;
|
|
43
43
|
/** Optional grant id, attached as the `grantId` claim. */
|
|
44
44
|
grantId?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Optional uniqueness claim, attached as the `nonce` claim (a uuid is the
|
|
47
|
+
* intended shape; the Personal Server bounds it at 128 characters).
|
|
48
|
+
*
|
|
49
|
+
* @remarks
|
|
50
|
+
* A payload is otherwise fully determined by
|
|
51
|
+
* `{ aud, bodyHash, exp, grantId, iat, method, uri }`, so two identical
|
|
52
|
+
* requests signed inside the same second produce the same bytes and the
|
|
53
|
+
* Personal Server refuses the second as a replay. With a nonce the replay
|
|
54
|
+
* key becomes `(signer, nonce)` instead, which is what lets a poll loop
|
|
55
|
+
* send the same request twice. The nonce is then single use itself:
|
|
56
|
+
* re-using one is a replay even when the rest of the payload changed.
|
|
57
|
+
*/
|
|
58
|
+
nonce?: string;
|
|
45
59
|
/** Pre-computed `bodyHash` claim — overrides `body`. */
|
|
46
60
|
bodyHash?: string;
|
|
47
61
|
}): Promise<string>;
|
|
@@ -28,6 +28,9 @@ async function buildWeb3SignedHeader(params) {
|
|
|
28
28
|
if (params.grantId !== void 0) {
|
|
29
29
|
payload["grantId"] = params.grantId;
|
|
30
30
|
}
|
|
31
|
+
if (params.nonce !== void 0) {
|
|
32
|
+
payload["nonce"] = params.nonce;
|
|
33
|
+
}
|
|
31
34
|
const sortedPayload = Object.keys(payload).sort().reduce((acc, key) => {
|
|
32
35
|
acc[key] = payload[key];
|
|
33
36
|
return acc;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/web3-signed-builder.ts"],"sourcesContent":["/**\n * Builder for Web3Signed Authorization headers.\n *\n * @remarks\n * Ported from `personal-server-ts`\n * (`packages/core/src/signing/request-signer.ts`). The original was wired\n * to a Node-only `ServerAccount` and `node:crypto`. This isomorphic version\n * accepts any `signMessage` callback (viem accounts, wallet clients, etc.)\n * and uses `@noble/hashes` for SHA-256 so it runs in browsers and Workers.\n *\n * Wire format is identical to PS — payload is JSON with sorted keys,\n * base64url-encoded, signed via EIP-191.\n *\n * @category Auth\n */\n\nimport { sha256 } from \"@noble/hashes/sha2\";\nimport { bytesToHex } from \"viem\";\nimport { toBase64 } from \"../utils/encoding\";\n\n/**\n * Sign-message callback compatible with viem `LocalAccount`/`WalletClient`-style\n * signers. Must produce an EIP-191 (`personal_sign`) signature.\n */\nexport type Web3SignedSignFn = (message: string) => Promise<`0x${string}`>;\n\n/** SHA-256 of the empty string — bodyHash for empty bodies. */\nconst EMPTY_BODY_HASH =\n \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\n\n/** Default token lifetime (seconds). */\nconst DEFAULT_TTL_SECONDS = 300;\n\n/** Base64url encode bytes (no padding). */\nfunction base64urlEncode(input: Uint8Array): string {\n return toBase64(input)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/** Compute the `sha256:<hex>` bodyHash claim for a request body. */\nexport function computeBodyHash(body: Uint8Array | undefined): string {\n if (!body || body.length === 0) {\n return EMPTY_BODY_HASH;\n }\n const digest = sha256(body);\n return `sha256:${bytesToHex(digest).slice(2)}`;\n}\n\n/**\n * Build a Web3Signed Authorization header value.\n *\n * @returns The full header value (`\"Web3Signed <base64url>.<sig>\"`).\n */\nexport async function buildWeb3SignedHeader(params: {\n /** EIP-191 signer (e.g. viem `account.signMessage`). */\n signMessage: Web3SignedSignFn;\n /** Expected origin (e.g. `\"https://ps.example.com\"`). */\n aud: string;\n /** HTTP method (e.g. `\"GET\"`). */\n method: string;\n /** Request URI/path (e.g. `\"/v1/data/instagram.profile\"`). */\n uri: string;\n /** Optional request body — when present, used to compute `bodyHash`. */\n body?: Uint8Array;\n /** Issued-at (unix seconds). Defaults to now. */\n iat?: number;\n /** Expiry (unix seconds). Defaults to `iat + 300`. */\n exp?: number;\n /** Optional grant id, attached as the `grantId` claim. */\n grantId?: string;\n /** Pre-computed `bodyHash` claim — overrides `body`. */\n bodyHash?: string;\n}): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n const iat = params.iat ?? now;\n const exp = params.exp ?? iat + DEFAULT_TTL_SECONDS;\n\n const payload: Record<string, unknown> = {\n aud: params.aud,\n bodyHash: params.bodyHash ?? computeBodyHash(params.body),\n exp,\n iat,\n method: params.method,\n uri: params.uri,\n };\n\n if (params.grantId !== undefined) {\n payload[\"grantId\"] = params.grantId;\n }\n\n // Sort keys for deterministic serialization.\n const sortedPayload = Object.keys(payload)\n .sort()\n .reduce<Record<string, unknown>>((acc, key) => {\n acc[key] = payload[key];\n return acc;\n }, {});\n\n const payloadJson = JSON.stringify(sortedPayload);\n const payloadBytes = new TextEncoder().encode(payloadJson);\n const payloadBase64 = base64urlEncode(payloadBytes);\n\n const signature = await params.signMessage(payloadBase64);\n\n return `Web3Signed ${payloadBase64}.${signature}`;\n}\n"],"mappings":"AAgBA,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AASzB,MAAM,kBACJ;AAGF,MAAM,sBAAsB;AAG5B,SAAS,gBAAgB,OAA2B;AAClD,SAAO,SAAS,KAAK,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,EAAE;AACtB;AAGO,SAAS,gBAAgB,MAAsC;AACpE,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,IAAI;AAC1B,SAAO,UAAU,WAAW,MAAM,EAAE,MAAM,CAAC,CAAC;AAC9C;AAOA,eAAsB,sBAAsB,
|
|
1
|
+
{"version":3,"sources":["../../src/auth/web3-signed-builder.ts"],"sourcesContent":["/**\n * Builder for Web3Signed Authorization headers.\n *\n * @remarks\n * Ported from `personal-server-ts`\n * (`packages/core/src/signing/request-signer.ts`). The original was wired\n * to a Node-only `ServerAccount` and `node:crypto`. This isomorphic version\n * accepts any `signMessage` callback (viem accounts, wallet clients, etc.)\n * and uses `@noble/hashes` for SHA-256 so it runs in browsers and Workers.\n *\n * Wire format is identical to PS — payload is JSON with sorted keys,\n * base64url-encoded, signed via EIP-191.\n *\n * @category Auth\n */\n\nimport { sha256 } from \"@noble/hashes/sha2\";\nimport { bytesToHex } from \"viem\";\nimport { toBase64 } from \"../utils/encoding\";\n\n/**\n * Sign-message callback compatible with viem `LocalAccount`/`WalletClient`-style\n * signers. Must produce an EIP-191 (`personal_sign`) signature.\n */\nexport type Web3SignedSignFn = (message: string) => Promise<`0x${string}`>;\n\n/** SHA-256 of the empty string — bodyHash for empty bodies. */\nconst EMPTY_BODY_HASH =\n \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\n\n/** Default token lifetime (seconds). */\nconst DEFAULT_TTL_SECONDS = 300;\n\n/** Base64url encode bytes (no padding). */\nfunction base64urlEncode(input: Uint8Array): string {\n return toBase64(input)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\n/** Compute the `sha256:<hex>` bodyHash claim for a request body. */\nexport function computeBodyHash(body: Uint8Array | undefined): string {\n if (!body || body.length === 0) {\n return EMPTY_BODY_HASH;\n }\n const digest = sha256(body);\n return `sha256:${bytesToHex(digest).slice(2)}`;\n}\n\n/**\n * Build a Web3Signed Authorization header value.\n *\n * @returns The full header value (`\"Web3Signed <base64url>.<sig>\"`).\n */\nexport async function buildWeb3SignedHeader(params: {\n /** EIP-191 signer (e.g. viem `account.signMessage`). */\n signMessage: Web3SignedSignFn;\n /** Expected origin (e.g. `\"https://ps.example.com\"`). */\n aud: string;\n /** HTTP method (e.g. `\"GET\"`). */\n method: string;\n /** Request URI/path (e.g. `\"/v1/data/instagram.profile\"`). */\n uri: string;\n /** Optional request body — when present, used to compute `bodyHash`. */\n body?: Uint8Array;\n /** Issued-at (unix seconds). Defaults to now. */\n iat?: number;\n /** Expiry (unix seconds). Defaults to `iat + 300`. */\n exp?: number;\n /** Optional grant id, attached as the `grantId` claim. */\n grantId?: string;\n /**\n * Optional uniqueness claim, attached as the `nonce` claim (a uuid is the\n * intended shape; the Personal Server bounds it at 128 characters).\n *\n * @remarks\n * A payload is otherwise fully determined by\n * `{ aud, bodyHash, exp, grantId, iat, method, uri }`, so two identical\n * requests signed inside the same second produce the same bytes and the\n * Personal Server refuses the second as a replay. With a nonce the replay\n * key becomes `(signer, nonce)` instead, which is what lets a poll loop\n * send the same request twice. The nonce is then single use itself:\n * re-using one is a replay even when the rest of the payload changed.\n */\n nonce?: string;\n /** Pre-computed `bodyHash` claim — overrides `body`. */\n bodyHash?: string;\n}): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n const iat = params.iat ?? now;\n const exp = params.exp ?? iat + DEFAULT_TTL_SECONDS;\n\n const payload: Record<string, unknown> = {\n aud: params.aud,\n bodyHash: params.bodyHash ?? computeBodyHash(params.body),\n exp,\n iat,\n method: params.method,\n uri: params.uri,\n };\n\n if (params.grantId !== undefined) {\n payload[\"grantId\"] = params.grantId;\n }\n\n // Merged before the sort, so the nonce sits in its alphabetical place like\n // every other claim and the payload stays deterministic.\n if (params.nonce !== undefined) {\n payload[\"nonce\"] = params.nonce;\n }\n\n // Sort keys for deterministic serialization.\n const sortedPayload = Object.keys(payload)\n .sort()\n .reduce<Record<string, unknown>>((acc, key) => {\n acc[key] = payload[key];\n return acc;\n }, {});\n\n const payloadJson = JSON.stringify(sortedPayload);\n const payloadBytes = new TextEncoder().encode(payloadJson);\n const payloadBase64 = base64urlEncode(payloadBytes);\n\n const signature = await params.signMessage(payloadBase64);\n\n return `Web3Signed ${payloadBase64}.${signature}`;\n}\n"],"mappings":"AAgBA,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AASzB,MAAM,kBACJ;AAGF,MAAM,sBAAsB;AAG5B,SAAS,gBAAgB,OAA2B;AAClD,SAAO,SAAS,KAAK,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,EAAE;AACtB;AAGO,SAAS,gBAAgB,MAAsC;AACpE,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,IAAI;AAC1B,SAAO,UAAU,WAAW,MAAM,EAAE,MAAM,CAAC,CAAC;AAC9C;AAOA,eAAsB,sBAAsB,QAiCxB;AAClB,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAM,MAAM,OAAO,OAAO;AAC1B,QAAM,MAAM,OAAO,OAAO,MAAM;AAEhC,QAAM,UAAmC;AAAA,IACvC,KAAK,OAAO;AAAA,IACZ,UAAU,OAAO,YAAY,gBAAgB,OAAO,IAAI;AAAA,IACxD;AAAA,IACA;AAAA,IACA,QAAQ,OAAO;AAAA,IACf,KAAK,OAAO;AAAA,EACd;AAEA,MAAI,OAAO,YAAY,QAAW;AAChC,YAAQ,SAAS,IAAI,OAAO;AAAA,EAC9B;AAIA,MAAI,OAAO,UAAU,QAAW;AAC9B,YAAQ,OAAO,IAAI,OAAO;AAAA,EAC5B;AAGA,QAAM,gBAAgB,OAAO,KAAK,OAAO,EACtC,KAAK,EACL,OAAgC,CAAC,KAAK,QAAQ;AAC7C,QAAI,GAAG,IAAI,QAAQ,GAAG;AACtB,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEP,QAAM,cAAc,KAAK,UAAU,aAAa;AAChD,QAAM,eAAe,IAAI,YAAY,EAAE,OAAO,WAAW;AACzD,QAAM,gBAAgB,gBAAgB,YAAY;AAElD,QAAM,YAAY,MAAM,OAAO,YAAY,aAAa;AAExD,SAAO,cAAc,aAAa,IAAI,SAAS;AACjD;","names":[]}
|
package/dist/errors.cjs
CHANGED
|
@@ -23,6 +23,15 @@ __export(errors_exports, {
|
|
|
23
23
|
DataPointDeletedError: () => DataPointDeletedError,
|
|
24
24
|
DataPointNotFoundError: () => DataPointNotFoundError,
|
|
25
25
|
DataPointVersionConflictError: () => DataPointVersionConflictError,
|
|
26
|
+
DerivativeComputeUnavailableError: () => DerivativeComputeUnavailableError,
|
|
27
|
+
DerivativeCycleError: () => DerivativeCycleError,
|
|
28
|
+
DerivativeDerivedScopeRequiredError: () => DerivativeDerivedScopeRequiredError,
|
|
29
|
+
DerivativeQuestionFailedError: () => DerivativeQuestionFailedError,
|
|
30
|
+
DerivativeQuestionInvalidError: () => DerivativeQuestionInvalidError,
|
|
31
|
+
DerivativeQuestionNotFoundError: () => DerivativeQuestionNotFoundError,
|
|
32
|
+
DerivativeQuestionRejectedError: () => DerivativeQuestionRejectedError,
|
|
33
|
+
DerivativeQuestionTimeoutError: () => DerivativeQuestionTimeoutError,
|
|
34
|
+
DerivativeSourceNotGrantedError: () => DerivativeSourceNotGrantedError,
|
|
26
35
|
InvalidConfigurationError: () => InvalidConfigurationError,
|
|
27
36
|
LineageReadError: () => LineageReadError,
|
|
28
37
|
NetworkError: () => NetworkError,
|
|
@@ -259,6 +268,57 @@ class LineageReadError extends VanaError {
|
|
|
259
268
|
errorCode;
|
|
260
269
|
details;
|
|
261
270
|
}
|
|
271
|
+
class DerivativeQuestionRejectedError extends PersonalServerWriteError {
|
|
272
|
+
constructor(message, status, errorCode = null, details) {
|
|
273
|
+
super(message, "DERIVATIVE_QUESTION_REJECTED", status, errorCode, details);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
class DerivativeQuestionInvalidError extends PersonalServerWriteError {
|
|
277
|
+
constructor(message, status = 400, errorCode = null, details) {
|
|
278
|
+
super(message, "DERIVATIVE_QUESTION_INVALID", status, errorCode, details);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
class DerivativeQuestionNotFoundError extends PersonalServerWriteError {
|
|
282
|
+
constructor(message, errorCode = null, details) {
|
|
283
|
+
super(message, "DERIVATIVE_QUESTION_NOT_FOUND", 404, errorCode, details);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
class DerivativeDerivedScopeRequiredError extends PersonalServerWriteError {
|
|
287
|
+
constructor(message, errorCode = null, details) {
|
|
288
|
+
super(
|
|
289
|
+
message,
|
|
290
|
+
"DERIVATIVE_DERIVED_SCOPE_REQUIRED",
|
|
291
|
+
400,
|
|
292
|
+
errorCode,
|
|
293
|
+
details
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
class DerivativeSourceNotGrantedError extends PersonalServerWriteError {
|
|
298
|
+
constructor(message, errorCode = null, details) {
|
|
299
|
+
super(message, "DERIVATIVE_SOURCE_NOT_GRANTED", 403, errorCode, details);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
class DerivativeCycleError extends PersonalServerWriteError {
|
|
303
|
+
constructor(message, errorCode = null, details) {
|
|
304
|
+
super(message, "DERIVATIVE_CYCLE", 409, errorCode, details);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
class DerivativeComputeUnavailableError extends PersonalServerWriteError {
|
|
308
|
+
constructor(message, errorCode = null, details) {
|
|
309
|
+
super(message, "DERIVATIVE_COMPUTE_UNAVAILABLE", 503, errorCode, details);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
class DerivativeQuestionTimeoutError extends PersonalServerWriteError {
|
|
313
|
+
constructor(message, details) {
|
|
314
|
+
super(message, "DERIVATIVE_QUESTION_TIMEOUT", void 0, null, details);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
class DerivativeQuestionFailedError extends PersonalServerWriteError {
|
|
318
|
+
constructor(message, details) {
|
|
319
|
+
super(message, "DERIVATIVE_QUESTION_FAILED", void 0, null, details);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
262
322
|
class DataPointDeletedError extends VanaError {
|
|
263
323
|
constructor(message, details = {}) {
|
|
264
324
|
super(message, "DATA_POINT_DELETED");
|
|
@@ -287,6 +347,15 @@ class DataPointVersionConflictError extends VanaError {
|
|
|
287
347
|
DataPointDeletedError,
|
|
288
348
|
DataPointNotFoundError,
|
|
289
349
|
DataPointVersionConflictError,
|
|
350
|
+
DerivativeComputeUnavailableError,
|
|
351
|
+
DerivativeCycleError,
|
|
352
|
+
DerivativeDerivedScopeRequiredError,
|
|
353
|
+
DerivativeQuestionFailedError,
|
|
354
|
+
DerivativeQuestionInvalidError,
|
|
355
|
+
DerivativeQuestionNotFoundError,
|
|
356
|
+
DerivativeQuestionRejectedError,
|
|
357
|
+
DerivativeQuestionTimeoutError,
|
|
358
|
+
DerivativeSourceNotGrantedError,
|
|
290
359
|
InvalidConfigurationError,
|
|
291
360
|
LineageReadError,
|
|
292
361
|
NetworkError,
|
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 | (string & {});\n\n/**\n * Base class for every Personal Server Write API failure.\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 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/**\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":[]}
|