@opendatalabs/vana-sdk 3.17.0 → 3.18.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.
Files changed (53) hide show
  1. package/README.md +6 -3
  2. package/dist/direct/personal-server-read.cjs +20 -1
  3. package/dist/direct/personal-server-read.cjs.map +1 -1
  4. package/dist/direct/personal-server-read.js +23 -1
  5. package/dist/direct/personal-server-read.js.map +1 -1
  6. package/dist/errors.cjs +27 -0
  7. package/dist/errors.cjs.map +1 -1
  8. package/dist/errors.d.ts +67 -0
  9. package/dist/errors.js +24 -0
  10. package/dist/errors.js.map +1 -1
  11. package/dist/index.browser.d.ts +2 -1
  12. package/dist/index.browser.js +731 -311
  13. package/dist/index.browser.js.map +4 -4
  14. package/dist/index.node.cjs +743 -313
  15. package/dist/index.node.cjs.map +4 -4
  16. package/dist/index.node.d.ts +2 -1
  17. package/dist/index.node.js +731 -311
  18. package/dist/index.node.js.map +4 -4
  19. package/dist/protocol/data-point-deletion.cjs +220 -0
  20. package/dist/protocol/data-point-deletion.cjs.map +1 -0
  21. package/dist/protocol/data-point-deletion.d.ts +180 -0
  22. package/dist/protocol/data-point-deletion.js +193 -0
  23. package/dist/protocol/data-point-deletion.js.map +1 -0
  24. package/dist/protocol/data-point-deletion.test.d.ts +1 -0
  25. package/dist/protocol/gateway.cjs +145 -32
  26. package/dist/protocol/gateway.cjs.map +1 -1
  27. package/dist/protocol/gateway.d.ts +42 -3
  28. package/dist/protocol/gateway.js +156 -32
  29. package/dist/protocol/gateway.js.map +1 -1
  30. package/dist/protocol/lineage.cjs +9 -4
  31. package/dist/protocol/lineage.cjs.map +1 -1
  32. package/dist/protocol/lineage.d.ts +21 -12
  33. package/dist/protocol/lineage.js +9 -4
  34. package/dist/protocol/lineage.js.map +1 -1
  35. package/dist/protocol/personal-server-data.cjs +20 -1
  36. package/dist/protocol/personal-server-data.cjs.map +1 -1
  37. package/dist/protocol/personal-server-data.js +23 -1
  38. package/dist/protocol/personal-server-data.js.map +1 -1
  39. package/dist/storage/index.cjs.map +1 -1
  40. package/dist/storage/index.d.ts +1 -1
  41. package/dist/storage/index.js.map +1 -1
  42. package/dist/storage/providers/vana-storage.cjs +66 -0
  43. package/dist/storage/providers/vana-storage.cjs.map +1 -1
  44. package/dist/storage/providers/vana-storage.d.ts +26 -0
  45. package/dist/storage/providers/vana-storage.js +66 -0
  46. package/dist/storage/providers/vana-storage.js.map +1 -1
  47. package/dist/utils/response-body.cjs +46 -0
  48. package/dist/utils/response-body.cjs.map +1 -0
  49. package/dist/utils/response-body.d.ts +26 -0
  50. package/dist/utils/response-body.js +20 -0
  51. package/dist/utils/response-body.js.map +1 -0
  52. package/dist/utils/response-body.test.d.ts +1 -0
  53. package/package.json +1 -1
@@ -1358,6 +1358,27 @@ var LineageReadError = class extends VanaError {
1358
1358
  errorCode;
1359
1359
  details;
1360
1360
  };
1361
+ var DataPointDeletedError = class extends VanaError {
1362
+ constructor(message, details = {}) {
1363
+ super(message, "DATA_POINT_DELETED");
1364
+ this.details = details;
1365
+ }
1366
+ details;
1367
+ };
1368
+ var DataPointNotFoundError = class extends VanaError {
1369
+ constructor(message, details = {}) {
1370
+ super(message, "DATA_POINT_NOT_FOUND");
1371
+ this.details = details;
1372
+ }
1373
+ details;
1374
+ };
1375
+ var DataPointVersionConflictError = class extends VanaError {
1376
+ constructor(message, details = {}) {
1377
+ super(message, "DATA_POINT_VERSION_CONFLICT");
1378
+ this.details = details;
1379
+ }
1380
+ details;
1381
+ };
1361
1382
 
1362
1383
  // src/contracts/contractController.ts
1363
1384
  import {
@@ -29120,6 +29141,22 @@ function getProtocolNetworkChainId(network) {
29120
29141
  return PROTOCOL_NETWORK_CHAIN_IDS[network];
29121
29142
  }
29122
29143
 
29144
+ // src/utils/response-body.ts
29145
+ function isPlainObject(value) {
29146
+ return typeof value === "object" && value !== null && !Array.isArray(value);
29147
+ }
29148
+ async function readJsonValue(res) {
29149
+ try {
29150
+ return await res.json();
29151
+ } catch {
29152
+ return null;
29153
+ }
29154
+ }
29155
+ async function readJsonObject(res) {
29156
+ const value = await readJsonValue(res);
29157
+ return isPlainObject(value) ? value : {};
29158
+ }
29159
+
29123
29160
  // src/storage/providers/vana-storage.ts
29124
29161
  var DEFAULT_ENDPOINT = "https://storage.vana.org";
29125
29162
  var LEGACY_BLOB_PATH_PREFIX = "/v1/blobs";
@@ -29291,6 +29328,65 @@ var VanaStorage = class {
29291
29328
  }
29292
29329
  return true;
29293
29330
  }
29331
+ /**
29332
+ * Delete every version's blob under `(owner, scope)` --
29333
+ * `DELETE {prefix}/{owner}/{scope}` on vana-storage, signed with the same
29334
+ * Web3Signed header as uploads (aud = endpoint origin, empty bodyHash).
29335
+ * The worker accepts the owner's own signature or a personal server the
29336
+ * owner registered with the gateway.
29337
+ *
29338
+ * @param ownerAddress - Must equal the provider's configured owner; a
29339
+ * mismatch throws before anything is signed so this wallet can never be
29340
+ * induced to sign a delete for another namespace.
29341
+ * @param scope - The scope segment, e.g. `"instagram.profile"`.
29342
+ */
29343
+ async deleteScope(ownerAddress, scope) {
29344
+ if (ownerAddress.toLowerCase() !== this.ownerAddress) {
29345
+ throw new StorageError(
29346
+ `deleteScope owner '${ownerAddress}' does not match the configured owner '${this.ownerAddress}'`,
29347
+ "INVALID_OWNER",
29348
+ "vana-storage"
29349
+ );
29350
+ }
29351
+ if (scope.length === 0 || scope.includes("/") || isTraversalSegment(scope)) {
29352
+ throw new StorageError(
29353
+ `scope must be a single non-empty path segment, got '${scope}'`,
29354
+ "INVALID_SCOPE",
29355
+ "vana-storage"
29356
+ );
29357
+ }
29358
+ const path = `${this.blobPathPrefix}/${this.ownerAddress}/${encodeURIComponent(scope)}`;
29359
+ const header = await this.signRequest("DELETE", path);
29360
+ let response;
29361
+ try {
29362
+ response = await this.fetchImpl(`${this.endpoint}${path}`, {
29363
+ method: "DELETE",
29364
+ headers: { authorization: header }
29365
+ });
29366
+ } catch (cause) {
29367
+ throw new StorageError(
29368
+ `vana-storage scope delete network error: ${describe(cause)}`,
29369
+ "DELETE_ERROR",
29370
+ "vana-storage",
29371
+ { cause: cause instanceof Error ? cause : void 0 }
29372
+ );
29373
+ }
29374
+ if (!response.ok) {
29375
+ const responseText = await safeText(response);
29376
+ throw new StorageError(
29377
+ `vana-storage scope delete failed: ${response.status} ${response.statusText} - ${responseText}`,
29378
+ "DELETE_FAILED",
29379
+ "vana-storage"
29380
+ );
29381
+ }
29382
+ const body = await readJsonObject(response);
29383
+ return {
29384
+ deleted: typeof body["deleted"] === "boolean" ? body["deleted"] : true,
29385
+ scope: typeof body["scope"] === "string" ? body["scope"] : scope,
29386
+ count: nonNegativeInteger(body["count"]) ?? 0,
29387
+ totalBytes: nonNegativeInteger(body["totalBytes"]) ?? 0
29388
+ };
29389
+ }
29294
29390
  getConfig() {
29295
29391
  return {
29296
29392
  name: "vana-storage",
@@ -29419,6 +29515,12 @@ function encodeRelativePath(filename) {
29419
29515
  }
29420
29516
  return parts.map((p) => encodeURIComponent(p)).join("/");
29421
29517
  }
29518
+ function isTraversalSegment(segment) {
29519
+ return segment === "." || segment === "..";
29520
+ }
29521
+ function nonNegativeInteger(value) {
29522
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : void 0;
29523
+ }
29422
29524
  function describe(value) {
29423
29525
  if (value instanceof Error) return value.message;
29424
29526
  return String(value);
@@ -33532,266 +33634,13 @@ function buildMarkDataPointUnavailableRequest(config, input) {
33532
33634
  });
33533
33635
  }
33534
33636
 
33535
- // src/protocol/data-file.ts
33536
- import { z } from "zod";
33537
- var DataFileEnvelopeSchema = z.object({
33538
- $schema: z.string().url().optional(),
33539
- version: z.literal("1.0"),
33540
- scope: z.string(),
33541
- schemaId: z.string().optional(),
33542
- collectedAt: z.string().datetime(),
33543
- data: z.record(z.string(), z.unknown())
33544
- });
33545
- function createDataFileEnvelope(scope, collectedAt, data, schemaUrl, schemaId) {
33546
- return {
33547
- ...schemaUrl !== void 0 && { $schema: schemaUrl },
33548
- ...schemaId !== void 0 && { schemaId },
33549
- version: "1.0",
33550
- scope,
33551
- collectedAt,
33552
- data
33553
- };
33554
- }
33555
- var IngestResponseSchema = z.object({
33556
- scope: z.string(),
33557
- collectedAt: z.string().datetime(),
33558
- status: z.enum(["stored", "syncing"])
33559
- });
33560
-
33561
- // src/protocol/personal-server-data.ts
33562
- function personalServerDataReadPath(scope) {
33563
- return `/v1/data/${encodeURIComponent(scope)}`;
33564
- }
33565
- async function buildPersonalServerDataReadRequest(params) {
33566
- const path = personalServerDataReadPath(params.scope);
33567
- const baseUrl = params.personalServerUrl.replace(/\/+$/, "");
33568
- const audience = params.audience ?? baseUrl;
33569
- const headers = new Headers(params.headers);
33570
- headers.set(
33571
- "Authorization",
33572
- await buildWeb3SignedHeader({
33573
- aud: audience,
33574
- grantId: params.grantId,
33575
- method: "GET",
33576
- signMessage: params.signMessage,
33577
- uri: path
33578
- })
33579
- );
33580
- return new Request(`${baseUrl}${path}`, {
33581
- headers,
33582
- method: "GET"
33583
- });
33584
- }
33585
- async function readPersonalServerData(params) {
33586
- const fetchFn = params.fetch ?? globalThis.fetch;
33587
- if (fetchFn === void 0) {
33588
- throw new Error("No fetch implementation available");
33589
- }
33590
- const request = await buildPersonalServerDataReadRequest(params);
33591
- const response = await fetchFn(request);
33592
- if (!response.ok) {
33593
- throw new Error(
33594
- `Personal Server data read failed: ${response.status} ${response.statusText}`
33595
- );
33596
- }
33597
- return DataFileEnvelopeSchema.parse(await response.json());
33598
- }
33599
-
33600
- // src/protocol/scopes.ts
33601
- import { z as z2 } from "zod";
33602
- var SOURCE_RE = /^[a-z0-9][a-z0-9_]*$/;
33603
- var TAIL_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9_]*$/;
33604
- var ScopeSchema = z2.string().refine(
33605
- (scope) => {
33606
- const parts = scope.split(".");
33607
- if (parts.length < 2 || parts.length > 3) return false;
33608
- const [source, ...tail] = parts;
33609
- return SOURCE_RE.test(source) && tail.every((part) => TAIL_SEGMENT_RE.test(part));
33610
- },
33611
- {
33612
- message: "Scope must be {source}.{category}[.{subcategory}]; source lowercase, tail may keep the historical camelCase form (e.g. spotify.savedTracks)"
33613
- }
33614
- );
33615
- function parseScope(scope) {
33616
- const validated = ScopeSchema.parse(scope);
33617
- const parts = validated.split(".");
33618
- return {
33619
- source: parts[0],
33620
- category: parts[1],
33621
- subcategory: parts[2],
33622
- raw: validated
33623
- };
33624
- }
33625
- function scopeToPathSegments(scope) {
33626
- const parsed = parseScope(scope);
33627
- const segments = [parsed.source, parsed.category];
33628
- if (parsed.subcategory) {
33629
- segments.push(parsed.subcategory);
33630
- }
33631
- return segments;
33632
- }
33633
- function scopeMatchesPattern(requestedScope, grantPattern) {
33634
- if (grantPattern === "*") return true;
33635
- if (grantPattern.endsWith(".*")) {
33636
- const prefix = grantPattern.slice(0, -1);
33637
- return requestedScope.startsWith(prefix);
33638
- }
33639
- return requestedScope === grantPattern;
33640
- }
33641
- function scopeCoveredByGrant(requestedScope, grantedScopes) {
33642
- return grantedScopes.some(
33643
- (pattern) => scopeMatchesPattern(requestedScope, pattern)
33644
- );
33645
- }
33646
-
33647
- // src/protocol/scope-actions.ts
33648
- var SCOPE_ACTIONS = ["read", "write"];
33649
- var InvalidScopeEntryError = class extends Error {
33650
- /** The offending entry, verbatim (unknown because it may not be a string). */
33651
- entry;
33652
- constructor(entry, reason) {
33653
- super(`Invalid scope entry ${describeValue(entry)}: ${reason}`);
33654
- this.name = "InvalidScopeEntryError";
33655
- this.entry = entry;
33656
- }
33657
- };
33658
- var OPERATION_SEPARATOR = ":";
33659
- function describeValue(value) {
33660
- if (typeof value === "string") return JSON.stringify(value);
33661
- if (value === null) return "null";
33662
- return `[${typeof value}]`;
33663
- }
33664
- var OPERATION_BY_PREFIX = {
33665
- write: "write"
33666
- };
33667
- function assertScopePart(entry, scope) {
33668
- if (scope.length === 0) {
33669
- throw new InvalidScopeEntryError(entry, "scope part is empty");
33670
- }
33671
- if (scope.includes(OPERATION_SEPARATOR)) {
33672
- throw new InvalidScopeEntryError(
33673
- entry,
33674
- `scope part must not contain "${OPERATION_SEPARATOR}"`
33675
- );
33676
- }
33677
- }
33678
- function parseScopeEntry(entry) {
33679
- const raw = entry;
33680
- if (typeof raw !== "string") {
33681
- throw new InvalidScopeEntryError(raw, "entry must be a string");
33682
- }
33683
- const separatorIndex = entry.indexOf(OPERATION_SEPARATOR);
33684
- if (separatorIndex === -1) {
33685
- assertScopePart(entry, entry);
33686
- return { scope: entry, action: "read" };
33687
- }
33688
- const prefix = entry.slice(0, separatorIndex);
33689
- const scope = entry.slice(separatorIndex + 1);
33690
- const action = Object.hasOwn(OPERATION_BY_PREFIX, prefix) ? OPERATION_BY_PREFIX[prefix] : void 0;
33691
- if (action === void 0) {
33692
- throw new InvalidScopeEntryError(
33693
- entry,
33694
- `unknown operation "${prefix}" (known: ${Object.keys(OPERATION_BY_PREFIX).join(", ")}; read has no prefix)`
33695
- );
33696
- }
33697
- assertScopePart(entry, scope);
33698
- return { scope, action };
33699
- }
33700
- function formatScopeEntry(parsed) {
33701
- const { scope, action } = parsed;
33702
- assertScopePart(scope, scope);
33703
- if (action === "read") return scope;
33704
- const prefix = Object.entries(OPERATION_BY_PREFIX).find(
33705
- ([, candidate]) => candidate === action
33706
- )?.[0];
33707
- if (prefix === void 0) {
33708
- throw new InvalidScopeEntryError(
33709
- scope,
33710
- `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
33711
- );
33712
- }
33713
- return `${prefix}${OPERATION_SEPARATOR}${scope}`;
33714
- }
33715
- function compareScopes(a, b) {
33716
- if (a < b) return -1;
33717
- if (a > b) return 1;
33718
- return 0;
33719
- }
33720
- function sortActions(actions) {
33721
- const present = new Set(actions);
33722
- return SCOPE_ACTIONS.filter((action) => present.has(action));
33723
- }
33724
- function grantPermissions(scopes) {
33725
- const byScope = /* @__PURE__ */ new Map();
33726
- for (const entry of scopes) {
33727
- const { scope, action } = parseScopeEntry(entry);
33728
- let actions = byScope.get(scope);
33729
- if (actions === void 0) {
33730
- actions = /* @__PURE__ */ new Set();
33731
- byScope.set(scope, actions);
33732
- }
33733
- actions.add(action);
33734
- }
33735
- return [...byScope.keys()].sort(compareScopes).map((scope) => ({
33736
- scope,
33737
- actions: sortActions(byScope.get(scope) ?? [])
33738
- }));
33739
- }
33740
- function permissionsToScopes(permissions) {
33741
- const byScope = /* @__PURE__ */ new Map();
33742
- for (const { scope, actions } of permissions) {
33743
- let merged = byScope.get(scope);
33744
- if (merged === void 0) {
33745
- merged = /* @__PURE__ */ new Set();
33746
- byScope.set(scope, merged);
33747
- }
33748
- for (const action of actions) {
33749
- if (!SCOPE_ACTIONS.includes(action)) {
33750
- throw new InvalidScopeEntryError(
33751
- scope,
33752
- `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
33753
- );
33754
- }
33755
- merged.add(action);
33756
- }
33757
- }
33758
- const entries = [];
33759
- for (const scope of [...byScope.keys()].sort(compareScopes)) {
33760
- for (const action of sortActions(byScope.get(scope) ?? [])) {
33761
- entries.push(formatScopeEntry({ scope, action }));
33762
- }
33763
- }
33764
- return entries;
33765
- }
33766
- function hasAction(scopes, scope, action) {
33767
- if (scope.includes(OPERATION_SEPARATOR)) return false;
33768
- for (const entry of scopes) {
33769
- let parsed;
33770
- try {
33771
- parsed = parseScopeEntry(entry);
33772
- } catch (error) {
33773
- if (error instanceof InvalidScopeEntryError) continue;
33774
- throw error;
33775
- }
33776
- if (parsed.action === action && scopeMatchesPattern(scope, parsed.scope)) {
33777
- return true;
33778
- }
33779
- }
33780
- return false;
33781
- }
33782
- function tryGrantPermissions(scopes) {
33783
- try {
33784
- return grantPermissions(scopes);
33785
- } catch (error) {
33786
- if (error instanceof InvalidScopeEntryError) return void 0;
33787
- throw error;
33788
- }
33789
- }
33790
-
33791
- // src/protocol/personal-server-write.ts
33792
- import { sha256 as sha2565 } from "@noble/hashes/sha2";
33793
- import { bytesToHex as bytesToHex2, isAddress as isAddress5 } from "viem";
33794
- import { z as z4 } from "zod";
33637
+ // src/protocol/data-point-deletion.ts
33638
+ import {
33639
+ isAddress as isAddress5,
33640
+ keccak256 as keccak2562,
33641
+ maxUint256,
33642
+ stringToBytes as stringToBytes3
33643
+ } from "viem";
33795
33644
 
33796
33645
  // src/protocol/lineage.ts
33797
33646
  import {
@@ -33799,7 +33648,7 @@ import {
33799
33648
  isAddress as isAddress4,
33800
33649
  keccak256
33801
33650
  } from "viem";
33802
- import { z as z3 } from "zod";
33651
+ import { z } from "zod";
33803
33652
 
33804
33653
  // src/protocol/personal-server-error-body.ts
33805
33654
  function isRecord2(value) {
@@ -33891,10 +33740,10 @@ function deriveDataPointId(ownerAddress, scope) {
33891
33740
  )
33892
33741
  );
33893
33742
  }
33894
- var DataPointIdSchema = z3.string().regex(DATA_POINT_ID_PATTERN).transform((value) => value.toLowerCase());
33743
+ var DataPointIdSchema = z.string().regex(DATA_POINT_ID_PATTERN).transform((value) => value.toLowerCase());
33895
33744
  var VERSION_PATTERN = /^[1-9]\d*$/;
33896
33745
  var NODE_VERSION_PATTERN = /^(0|[1-9]\d*)$/;
33897
- var VersionSchema = z3.union([z3.string(), z3.number()]).transform(String).refine((value) => NODE_VERSION_PATTERN.test(value), {
33746
+ var VersionSchema = z.union([z.string(), z.number()]).transform(String).refine((value) => NODE_VERSION_PATTERN.test(value), {
33898
33747
  message: "version must be a decimal integer"
33899
33748
  });
33900
33749
  var ViewVersionSchema = VersionSchema.refine(
@@ -33918,44 +33767,49 @@ function assertDerivedScopeNaming(derivedScope, sourceScopes) {
33918
33767
  }
33919
33768
  }
33920
33769
  }
33921
- var LineageNodeSchema = z3.object({
33770
+ var LineageNodeSchema = z.object({
33922
33771
  dataPointId: DataPointIdSchema,
33923
- scope: z3.string(),
33772
+ scope: z.string(),
33924
33773
  /**
33925
33774
  * The node's current version, decimal string; `"0"` for a source that no
33926
33775
  * longer resolves to a registered data point.
33927
33776
  */
33928
33777
  version: VersionSchema,
33929
33778
  /** The node's tombstone time, or `null` when live. */
33930
- deletedAt: z3.string().nullable()
33779
+ deletedAt: z.string().nullable(),
33780
+ /**
33781
+ * Never present on a visible node. Declared so a node that carries
33782
+ * `redacted: true` next to an id, scope and version cannot slip through
33783
+ * this branch of {@link LineageEntrySchema} with the key stripped.
33784
+ */
33785
+ redacted: z.never().optional()
33931
33786
  });
33932
- var RedactedLineageNodeSchema = z3.object({
33933
- dataPointId: DataPointIdSchema,
33934
- redacted: z3.literal(true)
33787
+ var RedactedLineageNodeSchema = z.strictObject({
33788
+ redacted: z.literal(true)
33935
33789
  });
33936
- var LineageEntrySchema = z3.union([
33790
+ var LineageEntrySchema = z.union([
33937
33791
  RedactedLineageNodeSchema,
33938
33792
  LineageNodeSchema
33939
33793
  ]);
33940
- var LineageGraphSchema = z3.object({
33794
+ var LineageGraphSchema = z.object({
33941
33795
  dataPointId: DataPointIdSchema,
33942
33796
  /** The data point owner; every node in the view belongs to it. */
33943
- ownerAddress: z3.string().optional(),
33944
- scope: z3.string(),
33797
+ ownerAddress: z.string().optional(),
33798
+ scope: z.string(),
33945
33799
  /**
33946
33800
  * The derived record's version whose lineage is shown: the requested one,
33947
33801
  * else the current one, else (current is a tombstone) the last version
33948
33802
  * that carried lineage.
33949
33803
  */
33950
33804
  version: ViewVersionSchema,
33951
- deletedAt: z3.string().nullable(),
33952
- sources: z3.array(LineageEntrySchema),
33953
- derivatives: z3.array(LineageEntrySchema),
33805
+ deletedAt: z.string().nullable(),
33806
+ sources: z.array(LineageEntrySchema),
33807
+ derivatives: z.array(LineageEntrySchema),
33954
33808
  /** `true` when `derivatives` was cut at the server's cap (1000). */
33955
- derivativesTruncated: z3.boolean().optional()
33809
+ derivativesTruncated: z.boolean().optional()
33956
33810
  });
33957
33811
  function isRedactedLineageNode(entry) {
33958
- return "redacted" in entry && entry.redacted === true;
33812
+ return "redacted" in entry && entry.redacted === true && Object.keys(entry).length === 1;
33959
33813
  }
33960
33814
  function personalServerLineagePath(scope, version) {
33961
33815
  return `/v1/data/${encodeURIComponent(scope)}/lineage${version === void 0 ? "" : `/${String(version)}`}`;
@@ -34097,7 +33951,449 @@ function getLineage(params) {
34097
33951
  return "personalServerUrl" in params ? getPersonalServerLineage(params) : getGatewayLineage(params);
34098
33952
  }
34099
33953
 
33954
+ // src/protocol/data-point-deletion.ts
33955
+ var TOMBSTONE_DATA_HASH_PREIMAGE = "vana.data-point.tombstone.v1";
33956
+ var TOMBSTONE_METADATA_HASH_PREIMAGE = "vana.data-point.tombstone.metadata.v1";
33957
+ var TOMBSTONE_DATA_HASH = "0x30c45ee72fe56d1927701316925ab7ceacd3b6f9267061735d59396f075c6222";
33958
+ var TOMBSTONE_METADATA_HASH = "0xc5255a141acd6a2ae55971b62c0a85977c2511989dc114ad2abc2b7644f57d90";
33959
+ function computeTombstoneHash(preimage) {
33960
+ return keccak2562(stringToBytes3(preimage));
33961
+ }
33962
+ function isTombstoneHashes(dataHash, metadataHash) {
33963
+ return typeof dataHash === "string" && typeof metadataHash === "string" && dataHash.toLowerCase() === TOMBSTONE_DATA_HASH && metadataHash.toLowerCase() === TOMBSTONE_METADATA_HASH;
33964
+ }
33965
+ function isDataPointTombstone(value) {
33966
+ if (!isPlainObject(value)) return false;
33967
+ if (typeof value["deletedAt"] === "string") return true;
33968
+ return isTombstoneHashes(
33969
+ typeof value["dataHash"] === "string" ? value["dataHash"] : void 0,
33970
+ typeof value["metadataHash"] === "string" ? value["metadataHash"] : void 0
33971
+ );
33972
+ }
33973
+ function tombstoneDeletedAt(value) {
33974
+ if (!isPlainObject(value)) return null;
33975
+ const deletedAt = value["deletedAt"];
33976
+ return typeof deletedAt === "string" ? deletedAt : null;
33977
+ }
33978
+ function assertAddress4(value, name) {
33979
+ if (!isAddress5(value)) {
33980
+ throw new Error(`${name} must be a valid EVM address`);
33981
+ }
33982
+ }
33983
+ function assertUint256(value, name) {
33984
+ if (value < 0n || value > maxUint256) {
33985
+ throw new Error(`${name} must fit in uint256, got ${value}`);
33986
+ }
33987
+ }
33988
+ function getAccountAddress3(account) {
33989
+ if (!account) return void 0;
33990
+ return typeof account === "string" ? account : account.address;
33991
+ }
33992
+ function isDataPointDeletionSigner(source) {
33993
+ return "address" in source && typeof source.signTypedData === "function";
33994
+ }
33995
+ function createViemDataPointDeletionSigner(source, options = {}) {
33996
+ if (isDataPointDeletionSigner(source)) {
33997
+ return source;
33998
+ }
33999
+ const accountAddress2 = getAccountAddress3(options.account) ?? getAccountAddress3(source.account);
34000
+ if (accountAddress2) {
34001
+ return {
34002
+ address: accountAddress2,
34003
+ signTypedData: (typedData) => source.signTypedData({
34004
+ ...typedData,
34005
+ account: options.account ?? source.account ?? accountAddress2
34006
+ })
34007
+ };
34008
+ }
34009
+ throw new Error(
34010
+ "Viem wallet client requires an account option or account property"
34011
+ );
34012
+ }
34013
+ function buildDataPointDeletionTypedData(input) {
34014
+ assertAddress4(input.ownerAddress, "ownerAddress");
34015
+ if (input.scope.length === 0) {
34016
+ throw new Error("scope must be a non-empty string");
34017
+ }
34018
+ if (input.expectedVersion <= 0n) {
34019
+ throw new Error("expectedVersion must be a positive version number");
34020
+ }
34021
+ assertUint256(input.expectedVersion, "expectedVersion");
34022
+ return {
34023
+ domain: dataRegistryDomain(input.config),
34024
+ types: ADD_DATA_TYPES,
34025
+ primaryType: "AddData",
34026
+ message: {
34027
+ ownerAddress: input.ownerAddress,
34028
+ scope: input.scope,
34029
+ dataHash: TOMBSTONE_DATA_HASH,
34030
+ metadataHash: TOMBSTONE_METADATA_HASH,
34031
+ expectedVersion: input.expectedVersion
34032
+ }
34033
+ };
34034
+ }
34035
+ async function buildDataPointDeletionSignature(input) {
34036
+ const typedData = buildDataPointDeletionTypedData({
34037
+ ownerAddress: input.signer.address,
34038
+ scope: input.scope,
34039
+ expectedVersion: input.expectedVersion,
34040
+ config: input.config
34041
+ });
34042
+ const signature = await input.signer.signTypedData(typedData);
34043
+ return {
34044
+ signature,
34045
+ signerAddress: input.signer.address,
34046
+ typedData
34047
+ };
34048
+ }
34049
+ function toError(value) {
34050
+ return value instanceof Error ? value : new Error(String(value));
34051
+ }
34052
+ function parseExpectedVersion(value) {
34053
+ if (typeof value !== "string" || !/^\d+$/.test(value)) {
34054
+ throw new Error(
34055
+ `Gateway returned a malformed expectedVersion: ${JSON.stringify(value)}`
34056
+ );
34057
+ }
34058
+ const parsed = BigInt(value);
34059
+ assertUint256(parsed, "Gateway expectedVersion");
34060
+ return parsed;
34061
+ }
34062
+ async function deleteDataPoint(input) {
34063
+ const ownerAddress = input.signer.address;
34064
+ const dataPointId = deriveDataPointId(ownerAddress, input.scope);
34065
+ let currentVersion = input.currentVersion;
34066
+ if (currentVersion === void 0) {
34067
+ const record = await input.gateway.getDataPoint(dataPointId);
34068
+ if (record === null) {
34069
+ throw new DataPointNotFoundError(
34070
+ `No data point registered for scope '${input.scope}' owned by ${ownerAddress}`,
34071
+ { dataPointId, scope: input.scope, ownerAddress }
34072
+ );
34073
+ }
34074
+ if (isDataPointTombstone(record)) {
34075
+ throw new DataPointDeletedError(
34076
+ `Data point ${dataPointId} (scope '${input.scope}') is already deleted`,
34077
+ {
34078
+ dataPointId,
34079
+ scope: input.scope,
34080
+ ownerAddress,
34081
+ deletedAt: tombstoneDeletedAt(record)
34082
+ }
34083
+ );
34084
+ }
34085
+ currentVersion = parseExpectedVersion(record.expectedVersion);
34086
+ }
34087
+ if (currentVersion < 0n || currentVersion >= maxUint256) {
34088
+ throw new Error(
34089
+ `currentVersion ${currentVersion} cannot be incremented to a uint256 tombstone version`
34090
+ );
34091
+ }
34092
+ const tombstoneVersion = currentVersion + 1n;
34093
+ const signed = await buildDataPointDeletionSignature({
34094
+ signer: input.signer,
34095
+ scope: input.scope,
34096
+ expectedVersion: tombstoneVersion,
34097
+ config: input.config
34098
+ });
34099
+ const tombstone = await input.gateway.deleteDataPoint({
34100
+ ownerAddress,
34101
+ scope: input.scope,
34102
+ expectedVersion: tombstoneVersion.toString(),
34103
+ signature: signed.signature
34104
+ });
34105
+ const base = {
34106
+ dataPointId,
34107
+ ownerAddress,
34108
+ scope: input.scope,
34109
+ version: tombstoneVersion.toString(),
34110
+ signature: signed.signature,
34111
+ tombstone
34112
+ };
34113
+ try {
34114
+ const storage = await input.storage.deleteScope(ownerAddress, input.scope);
34115
+ return { ...base, status: "deleted", storage };
34116
+ } catch (cause) {
34117
+ return { ...base, status: "partial", storageError: toError(cause) };
34118
+ }
34119
+ }
34120
+
34121
+ // src/protocol/data-file.ts
34122
+ import { z as z2 } from "zod";
34123
+ var DataFileEnvelopeSchema = z2.object({
34124
+ $schema: z2.string().url().optional(),
34125
+ version: z2.literal("1.0"),
34126
+ scope: z2.string(),
34127
+ schemaId: z2.string().optional(),
34128
+ collectedAt: z2.string().datetime(),
34129
+ data: z2.record(z2.string(), z2.unknown())
34130
+ });
34131
+ function createDataFileEnvelope(scope, collectedAt, data, schemaUrl, schemaId) {
34132
+ return {
34133
+ ...schemaUrl !== void 0 && { $schema: schemaUrl },
34134
+ ...schemaId !== void 0 && { schemaId },
34135
+ version: "1.0",
34136
+ scope,
34137
+ collectedAt,
34138
+ data
34139
+ };
34140
+ }
34141
+ var IngestResponseSchema = z2.object({
34142
+ scope: z2.string(),
34143
+ collectedAt: z2.string().datetime(),
34144
+ status: z2.enum(["stored", "syncing"])
34145
+ });
34146
+
34147
+ // src/protocol/personal-server-data.ts
34148
+ function personalServerDataReadPath(scope) {
34149
+ return `/v1/data/${encodeURIComponent(scope)}`;
34150
+ }
34151
+ async function buildPersonalServerDataReadRequest(params) {
34152
+ const path = personalServerDataReadPath(params.scope);
34153
+ const baseUrl = params.personalServerUrl.replace(/\/+$/, "");
34154
+ const audience = params.audience ?? baseUrl;
34155
+ const headers = new Headers(params.headers);
34156
+ headers.set(
34157
+ "Authorization",
34158
+ await buildWeb3SignedHeader({
34159
+ aud: audience,
34160
+ grantId: params.grantId,
34161
+ method: "GET",
34162
+ signMessage: params.signMessage,
34163
+ uri: path
34164
+ })
34165
+ );
34166
+ return new Request(`${baseUrl}${path}`, {
34167
+ headers,
34168
+ method: "GET"
34169
+ });
34170
+ }
34171
+ async function readPersonalServerData(params) {
34172
+ const fetchFn = params.fetch ?? globalThis.fetch;
34173
+ if (fetchFn === void 0) {
34174
+ throw new Error("No fetch implementation available");
34175
+ }
34176
+ const request = await buildPersonalServerDataReadRequest(params);
34177
+ const response = await fetchFn(request);
34178
+ if (response.status === 410) {
34179
+ throw new DataPointDeletedError(
34180
+ `Personal Server scope '${params.scope}' has been deleted`,
34181
+ {
34182
+ scope: params.scope,
34183
+ deletedAt: tombstoneDeletedAt(await readJsonValue(response))
34184
+ }
34185
+ );
34186
+ }
34187
+ if (!response.ok) {
34188
+ throw new Error(
34189
+ `Personal Server data read failed: ${response.status} ${response.statusText}`
34190
+ );
34191
+ }
34192
+ const body = await response.json();
34193
+ if (isDataPointTombstone(body)) {
34194
+ throw new DataPointDeletedError(
34195
+ `Personal Server scope '${params.scope}' has been deleted`,
34196
+ { scope: params.scope, deletedAt: tombstoneDeletedAt(body) }
34197
+ );
34198
+ }
34199
+ return DataFileEnvelopeSchema.parse(body);
34200
+ }
34201
+
34202
+ // src/protocol/scopes.ts
34203
+ import { z as z3 } from "zod";
34204
+ var SOURCE_RE = /^[a-z0-9][a-z0-9_]*$/;
34205
+ var TAIL_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9_]*$/;
34206
+ var ScopeSchema = z3.string().refine(
34207
+ (scope) => {
34208
+ const parts = scope.split(".");
34209
+ if (parts.length < 2 || parts.length > 3) return false;
34210
+ const [source, ...tail] = parts;
34211
+ return SOURCE_RE.test(source) && tail.every((part) => TAIL_SEGMENT_RE.test(part));
34212
+ },
34213
+ {
34214
+ message: "Scope must be {source}.{category}[.{subcategory}]; source lowercase, tail may keep the historical camelCase form (e.g. spotify.savedTracks)"
34215
+ }
34216
+ );
34217
+ function parseScope(scope) {
34218
+ const validated = ScopeSchema.parse(scope);
34219
+ const parts = validated.split(".");
34220
+ return {
34221
+ source: parts[0],
34222
+ category: parts[1],
34223
+ subcategory: parts[2],
34224
+ raw: validated
34225
+ };
34226
+ }
34227
+ function scopeToPathSegments(scope) {
34228
+ const parsed = parseScope(scope);
34229
+ const segments = [parsed.source, parsed.category];
34230
+ if (parsed.subcategory) {
34231
+ segments.push(parsed.subcategory);
34232
+ }
34233
+ return segments;
34234
+ }
34235
+ function scopeMatchesPattern(requestedScope, grantPattern) {
34236
+ if (grantPattern === "*") return true;
34237
+ if (grantPattern.endsWith(".*")) {
34238
+ const prefix = grantPattern.slice(0, -1);
34239
+ return requestedScope.startsWith(prefix);
34240
+ }
34241
+ return requestedScope === grantPattern;
34242
+ }
34243
+ function scopeCoveredByGrant(requestedScope, grantedScopes) {
34244
+ return grantedScopes.some(
34245
+ (pattern) => scopeMatchesPattern(requestedScope, pattern)
34246
+ );
34247
+ }
34248
+
34249
+ // src/protocol/scope-actions.ts
34250
+ var SCOPE_ACTIONS = ["read", "write"];
34251
+ var InvalidScopeEntryError = class extends Error {
34252
+ /** The offending entry, verbatim (unknown because it may not be a string). */
34253
+ entry;
34254
+ constructor(entry, reason) {
34255
+ super(`Invalid scope entry ${describeValue(entry)}: ${reason}`);
34256
+ this.name = "InvalidScopeEntryError";
34257
+ this.entry = entry;
34258
+ }
34259
+ };
34260
+ var OPERATION_SEPARATOR = ":";
34261
+ function describeValue(value) {
34262
+ if (typeof value === "string") return JSON.stringify(value);
34263
+ if (value === null) return "null";
34264
+ return `[${typeof value}]`;
34265
+ }
34266
+ var OPERATION_BY_PREFIX = {
34267
+ write: "write"
34268
+ };
34269
+ function assertScopePart(entry, scope) {
34270
+ if (scope.length === 0) {
34271
+ throw new InvalidScopeEntryError(entry, "scope part is empty");
34272
+ }
34273
+ if (scope.includes(OPERATION_SEPARATOR)) {
34274
+ throw new InvalidScopeEntryError(
34275
+ entry,
34276
+ `scope part must not contain "${OPERATION_SEPARATOR}"`
34277
+ );
34278
+ }
34279
+ }
34280
+ function parseScopeEntry(entry) {
34281
+ const raw = entry;
34282
+ if (typeof raw !== "string") {
34283
+ throw new InvalidScopeEntryError(raw, "entry must be a string");
34284
+ }
34285
+ const separatorIndex = entry.indexOf(OPERATION_SEPARATOR);
34286
+ if (separatorIndex === -1) {
34287
+ assertScopePart(entry, entry);
34288
+ return { scope: entry, action: "read" };
34289
+ }
34290
+ const prefix = entry.slice(0, separatorIndex);
34291
+ const scope = entry.slice(separatorIndex + 1);
34292
+ const action = Object.hasOwn(OPERATION_BY_PREFIX, prefix) ? OPERATION_BY_PREFIX[prefix] : void 0;
34293
+ if (action === void 0) {
34294
+ throw new InvalidScopeEntryError(
34295
+ entry,
34296
+ `unknown operation "${prefix}" (known: ${Object.keys(OPERATION_BY_PREFIX).join(", ")}; read has no prefix)`
34297
+ );
34298
+ }
34299
+ assertScopePart(entry, scope);
34300
+ return { scope, action };
34301
+ }
34302
+ function formatScopeEntry(parsed) {
34303
+ const { scope, action } = parsed;
34304
+ assertScopePart(scope, scope);
34305
+ if (action === "read") return scope;
34306
+ const prefix = Object.entries(OPERATION_BY_PREFIX).find(
34307
+ ([, candidate]) => candidate === action
34308
+ )?.[0];
34309
+ if (prefix === void 0) {
34310
+ throw new InvalidScopeEntryError(
34311
+ scope,
34312
+ `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
34313
+ );
34314
+ }
34315
+ return `${prefix}${OPERATION_SEPARATOR}${scope}`;
34316
+ }
34317
+ function compareScopes(a, b) {
34318
+ if (a < b) return -1;
34319
+ if (a > b) return 1;
34320
+ return 0;
34321
+ }
34322
+ function sortActions(actions) {
34323
+ const present = new Set(actions);
34324
+ return SCOPE_ACTIONS.filter((action) => present.has(action));
34325
+ }
34326
+ function grantPermissions(scopes) {
34327
+ const byScope = /* @__PURE__ */ new Map();
34328
+ for (const entry of scopes) {
34329
+ const { scope, action } = parseScopeEntry(entry);
34330
+ let actions = byScope.get(scope);
34331
+ if (actions === void 0) {
34332
+ actions = /* @__PURE__ */ new Set();
34333
+ byScope.set(scope, actions);
34334
+ }
34335
+ actions.add(action);
34336
+ }
34337
+ return [...byScope.keys()].sort(compareScopes).map((scope) => ({
34338
+ scope,
34339
+ actions: sortActions(byScope.get(scope) ?? [])
34340
+ }));
34341
+ }
34342
+ function permissionsToScopes(permissions) {
34343
+ const byScope = /* @__PURE__ */ new Map();
34344
+ for (const { scope, actions } of permissions) {
34345
+ let merged = byScope.get(scope);
34346
+ if (merged === void 0) {
34347
+ merged = /* @__PURE__ */ new Set();
34348
+ byScope.set(scope, merged);
34349
+ }
34350
+ for (const action of actions) {
34351
+ if (!SCOPE_ACTIONS.includes(action)) {
34352
+ throw new InvalidScopeEntryError(
34353
+ scope,
34354
+ `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
34355
+ );
34356
+ }
34357
+ merged.add(action);
34358
+ }
34359
+ }
34360
+ const entries = [];
34361
+ for (const scope of [...byScope.keys()].sort(compareScopes)) {
34362
+ for (const action of sortActions(byScope.get(scope) ?? [])) {
34363
+ entries.push(formatScopeEntry({ scope, action }));
34364
+ }
34365
+ }
34366
+ return entries;
34367
+ }
34368
+ function hasAction(scopes, scope, action) {
34369
+ if (scope.includes(OPERATION_SEPARATOR)) return false;
34370
+ for (const entry of scopes) {
34371
+ let parsed;
34372
+ try {
34373
+ parsed = parseScopeEntry(entry);
34374
+ } catch (error) {
34375
+ if (error instanceof InvalidScopeEntryError) continue;
34376
+ throw error;
34377
+ }
34378
+ if (parsed.action === action && scopeMatchesPattern(scope, parsed.scope)) {
34379
+ return true;
34380
+ }
34381
+ }
34382
+ return false;
34383
+ }
34384
+ function tryGrantPermissions(scopes) {
34385
+ try {
34386
+ return grantPermissions(scopes);
34387
+ } catch (error) {
34388
+ if (error instanceof InvalidScopeEntryError) return void 0;
34389
+ throw error;
34390
+ }
34391
+ }
34392
+
34100
34393
  // src/protocol/personal-server-write.ts
34394
+ import { sha256 as sha2565 } from "@noble/hashes/sha2";
34395
+ import { bytesToHex as bytesToHex2, isAddress as isAddress6 } from "viem";
34396
+ import { z as z4 } from "zod";
34101
34397
  var WRITE_SESSION_PATH = "/v1/write/session";
34102
34398
  var WRITE_SIGNATURE_HEADER = "X-Vana-Write-Signature";
34103
34399
  var WRITE_METADATA_HEADER = "X-Vana-Metadata";
@@ -34400,7 +34696,7 @@ function normalizeLineage(lineage, derivedScope) {
34400
34696
  for (const entry of lineage) {
34401
34697
  let id;
34402
34698
  if (isLineagePair(entry)) {
34403
- if (!isAddress5(entry.ownerAddress, { strict: false })) {
34699
+ if (!isAddress6(entry.ownerAddress, { strict: false })) {
34404
34700
  throw new WriteRequestError(
34405
34701
  "lineage source ownerAddress must be an EVM address",
34406
34702
  { ownerAddress: entry.ownerAddress }
@@ -34662,14 +34958,44 @@ function withGrantPermissions(grant) {
34662
34958
  }
34663
34959
  function createGatewayClient(baseUrl) {
34664
34960
  const base = baseUrl.replace(/\/+$/, "");
34961
+ function malformedBody(res) {
34962
+ return new Error(
34963
+ `Gateway error: ${res.status} malformed response body (expected a JSON envelope)`
34964
+ );
34965
+ }
34966
+ async function readEnvelope(res) {
34967
+ const envelope = await readJsonValue(res);
34968
+ if (!isPlainObject(envelope) || !("data" in envelope)) {
34969
+ throw malformedBody(res);
34970
+ }
34971
+ return envelope;
34972
+ }
34665
34973
  async function unwrapEnvelope(res) {
34666
- const envelope = await res.json();
34667
- return envelope.data;
34974
+ return (await readEnvelope(res)).data;
34668
34975
  }
34669
34976
  function getMutationId(body, key) {
34977
+ if (!isPlainObject(body)) return void 0;
34670
34978
  const value = body[key] ?? body["id"];
34671
34979
  return typeof value === "string" ? value : void 0;
34672
34980
  }
34981
+ async function readBody(res) {
34982
+ const raw = await readJsonObject(res);
34983
+ const data = raw["data"];
34984
+ if (isPlainObject(data) && "proof" in raw) {
34985
+ return data;
34986
+ }
34987
+ return raw;
34988
+ }
34989
+ function stringOrUndefined(value) {
34990
+ return typeof value === "string" ? value : void 0;
34991
+ }
34992
+ async function deletedError(res, details) {
34993
+ const body = await readBody(res);
34994
+ return new DataPointDeletedError(
34995
+ `Data point ${details.dataPointId ?? details.scope ?? ""} has been deleted`,
34996
+ { ...details, deletedAt: tombstoneDeletedAt(body) }
34997
+ );
34998
+ }
34673
34999
  return {
34674
35000
  async isRegisteredBuilder(address) {
34675
35001
  const builder = await this.getBuilder(address);
@@ -34726,13 +35052,29 @@ function createGatewayClient(baseUrl) {
34726
35052
  }
34727
35053
  return await res.json();
34728
35054
  },
34729
- async getDataPoint(dataPointId) {
34730
- const res = await fetch(`${base}/v1/data/${dataPointId}`);
35055
+ async getDataPoint(dataPointId, options) {
35056
+ const query = options?.includeDeleted ? "?includeDeleted=true" : "";
35057
+ const res = await fetch(`${base}/v1/data/${dataPointId}${query}`);
34731
35058
  if (res.status === 404) return null;
35059
+ if (res.status === 410) {
35060
+ throw await deletedError(res, { dataPointId });
35061
+ }
34732
35062
  if (!res.ok) {
34733
35063
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
34734
35064
  }
34735
- return unwrapEnvelope(res);
35065
+ const record = await unwrapEnvelope(res);
35066
+ if (!options?.includeDeleted && isDataPointTombstone(record)) {
35067
+ throw new DataPointDeletedError(
35068
+ `Data point ${dataPointId} has been deleted`,
35069
+ {
35070
+ dataPointId,
35071
+ scope: record.scope,
35072
+ ownerAddress: record.ownerAddress,
35073
+ deletedAt: tombstoneDeletedAt(record)
35074
+ }
35075
+ );
35076
+ }
35077
+ return record;
34736
35078
  },
34737
35079
  async listDataPointsByOwner(owner, cursor, options) {
34738
35080
  const params = new URLSearchParams({ user: owner });
@@ -34745,14 +35087,24 @@ function createGatewayClient(baseUrl) {
34745
35087
  if (options?.limit !== void 0) {
34746
35088
  params.set("limit", String(options.limit));
34747
35089
  }
35090
+ if (options?.includeDeleted) {
35091
+ params.set("includeDeleted", "true");
35092
+ }
34748
35093
  const res = await fetch(`${base}/v1/data?${params.toString()}`);
34749
35094
  if (!res.ok) {
34750
35095
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
34751
35096
  }
34752
- const envelope = await res.json();
34753
- const nextCursor = envelope.pagination?.hasMore === false ? null : envelope.pagination?.nextCursor ?? null;
35097
+ const envelope = await readEnvelope(res);
35098
+ if (!isPlainObject(envelope.data) || !Array.isArray(envelope.data["dataPoints"])) {
35099
+ throw malformedBody(res);
35100
+ }
35101
+ const rows = envelope.data["dataPoints"];
35102
+ const pagination = isPlainObject(envelope["pagination"]) ? envelope["pagination"] : void 0;
35103
+ const rawCursor = pagination?.["nextCursor"];
35104
+ const nextCursor = pagination?.["hasMore"] === false || typeof rawCursor !== "string" ? null : rawCursor;
35105
+ const dataPoints = options?.includeDeleted ? rows : rows.filter((row) => !isDataPointTombstone(row));
34754
35106
  return {
34755
- dataPoints: envelope.data.dataPoints,
35107
+ dataPoints,
34756
35108
  cursor: nextCursor
34757
35109
  };
34758
35110
  },
@@ -34779,7 +35131,7 @@ function createGatewayClient(baseUrl) {
34779
35131
  })
34780
35132
  });
34781
35133
  if (res.status === 409) {
34782
- const body2 = await res.json().catch(() => ({}));
35134
+ const body2 = await readJsonObject(res);
34783
35135
  return {
34784
35136
  serverId: getMutationId(body2, "serverId"),
34785
35137
  alreadyRegistered: true
@@ -34788,7 +35140,7 @@ function createGatewayClient(baseUrl) {
34788
35140
  if (!res.ok) {
34789
35141
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
34790
35142
  }
34791
- const body = await res.json().catch(() => ({}));
35143
+ const body = await readJsonObject(res);
34792
35144
  return {
34793
35145
  serverId: getMutationId(body, "serverId"),
34794
35146
  alreadyRegistered: false
@@ -34809,19 +35161,16 @@ function createGatewayClient(baseUrl) {
34809
35161
  })
34810
35162
  });
34811
35163
  if (res.status === 409) {
34812
- const body2 = await res.json().catch(() => ({}));
35164
+ const body2 = await readJsonObject(res);
34813
35165
  return {
34814
- builderId: getMutationId(
34815
- body2,
34816
- "builderId"
34817
- ),
35166
+ builderId: getMutationId(body2, "builderId"),
34818
35167
  alreadyRegistered: true
34819
35168
  };
34820
35169
  }
34821
35170
  if (!res.ok) {
34822
35171
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
34823
35172
  }
34824
- const body = await res.json().catch(() => ({}));
35173
+ const body = await readJsonObject(res);
34825
35174
  return {
34826
35175
  builderId: getMutationId(body, "builderId"),
34827
35176
  alreadyRegistered: false
@@ -34843,17 +35192,77 @@ function createGatewayClient(baseUrl) {
34843
35192
  })
34844
35193
  });
34845
35194
  if (!res.ok) {
34846
- const body2 = await res.json().catch(() => ({}));
34847
- const detail = body2.error ?? res.statusText;
35195
+ const body2 = await readJsonObject(res);
35196
+ const detail = stringOrUndefined(body2["error"]) ?? res.statusText;
34848
35197
  throw new Error(`Gateway error: ${res.status} ${detail}`);
34849
35198
  }
34850
- const body = await res.json().catch(() => ({}));
35199
+ const body = await readJsonObject(res);
34851
35200
  return {
34852
- dataPointId: getMutationId(
34853
- body,
34854
- "dataPointId"
34855
- ),
34856
- expectedVersion: body.expectedVersion
35201
+ dataPointId: getMutationId(body, "dataPointId"),
35202
+ expectedVersion: stringOrUndefined(body["expectedVersion"])
35203
+ };
35204
+ },
35205
+ async deleteDataPoint(params) {
35206
+ const dataPointId = deriveDataPointId(
35207
+ params.ownerAddress,
35208
+ params.scope
35209
+ );
35210
+ const details = {
35211
+ dataPointId,
35212
+ scope: params.scope,
35213
+ ownerAddress: params.ownerAddress
35214
+ };
35215
+ const res = await fetch(`${base}/v1/data/${dataPointId}`, {
35216
+ method: "DELETE",
35217
+ headers: {
35218
+ "Content-Type": "application/json",
35219
+ Authorization: `Web3Signed ${params.signature}`
35220
+ },
35221
+ body: JSON.stringify({
35222
+ ownerAddress: params.ownerAddress,
35223
+ scope: params.scope,
35224
+ expectedVersion: params.expectedVersion,
35225
+ signature: params.signature
35226
+ })
35227
+ });
35228
+ if (res.status === 404) {
35229
+ throw new DataPointNotFoundError(
35230
+ `Data point ${dataPointId} (scope '${params.scope}') is not registered`,
35231
+ details
35232
+ );
35233
+ }
35234
+ if (res.status === 409) {
35235
+ const body2 = await readBody(res);
35236
+ const currentExpectedVersion = stringOrUndefined(
35237
+ body2["currentExpectedVersion"]
35238
+ );
35239
+ const detail = stringOrUndefined(body2["error"]) ?? res.statusText;
35240
+ throw new DataPointVersionConflictError(
35241
+ `Gateway error: 409 ${detail}`,
35242
+ {
35243
+ ...details,
35244
+ expectedVersion: params.expectedVersion,
35245
+ currentExpectedVersion
35246
+ }
35247
+ );
35248
+ }
35249
+ if (res.status === 410) {
35250
+ throw await deletedError(res, details);
35251
+ }
35252
+ if (!res.ok) {
35253
+ const body2 = await readBody(res);
35254
+ const detail = stringOrUndefined(body2["error"]) ?? res.statusText;
35255
+ throw new Error(`Gateway error: ${res.status} ${detail}`);
35256
+ }
35257
+ const body = await readBody(res);
35258
+ return {
35259
+ dataPointId: getMutationId(body, "dataPointId") ?? dataPointId,
35260
+ ownerAddress: stringOrUndefined(body["ownerAddress"]),
35261
+ scope: stringOrUndefined(body["scope"]),
35262
+ dataHash: stringOrUndefined(body["dataHash"]),
35263
+ metadataHash: stringOrUndefined(body["metadataHash"]),
35264
+ expectedVersion: stringOrUndefined(body["expectedVersion"]),
35265
+ deletedAt: tombstoneDeletedAt(body)
34857
35266
  };
34858
35267
  },
34859
35268
  async createGrant(params) {
@@ -34872,18 +35281,14 @@ function createGatewayClient(baseUrl) {
34872
35281
  })
34873
35282
  });
34874
35283
  if (res.status === 409) {
34875
- const body2 = await res.json().catch(() => ({}));
34876
- return {
34877
- grantId: getMutationId(body2, "grantId")
34878
- };
35284
+ const body2 = await readJsonObject(res);
35285
+ return { grantId: getMutationId(body2, "grantId") };
34879
35286
  }
34880
35287
  if (!res.ok) {
34881
35288
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
34882
35289
  }
34883
- const body = await res.json();
34884
- return {
34885
- grantId: getMutationId(body, "grantId")
34886
- };
35290
+ const body = await readJsonObject(res);
35291
+ return { grantId: getMutationId(body, "grantId") };
34887
35292
  },
34888
35293
  async revokeGrant(params) {
34889
35294
  const res = await fetch(`${base}/v1/grants/${params.grantId}`, {
@@ -35621,7 +36026,10 @@ export {
35621
36026
  DATA_ACCESS_OP_TYPE,
35622
36027
  DATA_REGISTRY_STATUS_ABI,
35623
36028
  DataFileEnvelopeSchema,
36029
+ DataPointDeletedError,
36030
+ DataPointNotFoundError,
35624
36031
  DataPointStatus,
36032
+ DataPointVersionConflictError,
35625
36033
  DropboxStorage,
35626
36034
  ECIESError,
35627
36035
  ESCROW_DEPOSIT_ABI2 as ESCROW_DEPOSIT_ABI,
@@ -35681,6 +36089,10 @@ export {
35681
36089
  SignatureError,
35682
36090
  StorageError,
35683
36091
  StorageManager,
36092
+ TOMBSTONE_DATA_HASH,
36093
+ TOMBSTONE_DATA_HASH_PREIMAGE,
36094
+ TOMBSTONE_METADATA_HASH,
36095
+ TOMBSTONE_METADATA_HASH_PREIMAGE,
35684
36096
  TransactionPendingError,
35685
36097
  UserRejectedRequestError,
35686
36098
  VanaError,
@@ -35705,6 +36117,8 @@ export {
35705
36117
  authorizeEscrowPayment,
35706
36118
  authorizeGrantPayment,
35707
36119
  binaryWriteSignedBytes,
36120
+ buildDataPointDeletionSignature,
36121
+ buildDataPointDeletionTypedData,
35708
36122
  buildDepositNativeRequest,
35709
36123
  buildDepositTokenRequest,
35710
36124
  buildEscrowPaymentHeader,
@@ -35722,6 +36136,7 @@ export {
35722
36136
  clearContractCache,
35723
36137
  computeBodyHash,
35724
36138
  computePkceChallenge,
36139
+ computeTombstoneHash,
35725
36140
  contractCacheForTesting,
35726
36141
  createBrowserPlatformAdapter,
35727
36142
  createDataFileEnvelope,
@@ -35733,11 +36148,13 @@ export {
35733
36148
  createPlatformAdapterFor,
35734
36149
  createPlatformAdapterSafe,
35735
36150
  createVanaStorageProvider,
36151
+ createViemDataPointDeletionSigner,
35736
36152
  createViemPersonalServerLiteOwnerBindingSigner,
35737
36153
  createViemPersonalServerRegistrationSigner,
35738
36154
  dataRegistryContractAddress,
35739
36155
  dataRegistryDomain,
35740
36156
  decryptWithPassword,
36157
+ deleteDataPoint,
35741
36158
  deriveDataPointId,
35742
36159
  deriveMasterKey,
35743
36160
  deriveScopeKey,
@@ -35773,10 +36190,12 @@ export {
35773
36190
  grantRevocationDomain,
35774
36191
  hasAction,
35775
36192
  isDataPointId,
36193
+ isDataPointTombstone,
35776
36194
  isDataPortabilityGatewayConfig,
35777
36195
  isECIESEncrypted,
35778
36196
  isPlatformSupported,
35779
36197
  isRedactedLineageNode,
36198
+ isTombstoneHashes,
35780
36199
  mainnetServices,
35781
36200
  moksha,
35782
36201
  mokshaServices,
@@ -35811,6 +36230,7 @@ export {
35811
36230
  signPersonalServerRegistrationWithAccount,
35812
36231
  toDirectFeeBreakdown,
35813
36232
  toDirectPaymentReceipt,
36233
+ tombstoneDeletedAt,
35814
36234
  tryGrantPermissions,
35815
36235
  vanaMainnet2 as vanaMainnet,
35816
36236
  verifyGrantRegistration,