@opendatalabs/vana-sdk 3.17.0 → 3.18.0

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 (47) hide show
  1. package/dist/direct/personal-server-read.cjs +20 -1
  2. package/dist/direct/personal-server-read.cjs.map +1 -1
  3. package/dist/direct/personal-server-read.js +23 -1
  4. package/dist/direct/personal-server-read.js.map +1 -1
  5. package/dist/errors.cjs +27 -0
  6. package/dist/errors.cjs.map +1 -1
  7. package/dist/errors.d.ts +67 -0
  8. package/dist/errors.js +24 -0
  9. package/dist/errors.js.map +1 -1
  10. package/dist/index.browser.d.ts +2 -1
  11. package/dist/index.browser.js +724 -309
  12. package/dist/index.browser.js.map +4 -4
  13. package/dist/index.node.cjs +736 -311
  14. package/dist/index.node.cjs.map +4 -4
  15. package/dist/index.node.d.ts +2 -1
  16. package/dist/index.node.js +724 -309
  17. package/dist/index.node.js.map +4 -4
  18. package/dist/protocol/data-point-deletion.cjs +220 -0
  19. package/dist/protocol/data-point-deletion.cjs.map +1 -0
  20. package/dist/protocol/data-point-deletion.d.ts +180 -0
  21. package/dist/protocol/data-point-deletion.js +193 -0
  22. package/dist/protocol/data-point-deletion.js.map +1 -0
  23. package/dist/protocol/data-point-deletion.test.d.ts +1 -0
  24. package/dist/protocol/gateway.cjs +145 -32
  25. package/dist/protocol/gateway.cjs.map +1 -1
  26. package/dist/protocol/gateway.d.ts +42 -3
  27. package/dist/protocol/gateway.js +156 -32
  28. package/dist/protocol/gateway.js.map +1 -1
  29. package/dist/protocol/personal-server-data.cjs +20 -1
  30. package/dist/protocol/personal-server-data.cjs.map +1 -1
  31. package/dist/protocol/personal-server-data.js +23 -1
  32. package/dist/protocol/personal-server-data.js.map +1 -1
  33. package/dist/storage/index.cjs.map +1 -1
  34. package/dist/storage/index.d.ts +1 -1
  35. package/dist/storage/index.js.map +1 -1
  36. package/dist/storage/providers/vana-storage.cjs +66 -0
  37. package/dist/storage/providers/vana-storage.cjs.map +1 -1
  38. package/dist/storage/providers/vana-storage.d.ts +26 -0
  39. package/dist/storage/providers/vana-storage.js +66 -0
  40. package/dist/storage/providers/vana-storage.js.map +1 -1
  41. package/dist/utils/response-body.cjs +46 -0
  42. package/dist/utils/response-body.cjs.map +1 -0
  43. package/dist/utils/response-body.d.ts +26 -0
  44. package/dist/utils/response-body.js +20 -0
  45. package/dist/utils/response-body.js.map +1 -0
  46. package/dist/utils/response-body.test.d.ts +1 -0
  47. package/package.json +1 -1
@@ -1187,7 +1187,10 @@ __export(index_node_exports, {
1187
1187
  DATA_ACCESS_OP_TYPE: () => DATA_ACCESS_OP_TYPE,
1188
1188
  DATA_REGISTRY_STATUS_ABI: () => DATA_REGISTRY_STATUS_ABI,
1189
1189
  DataFileEnvelopeSchema: () => DataFileEnvelopeSchema,
1190
+ DataPointDeletedError: () => DataPointDeletedError,
1191
+ DataPointNotFoundError: () => DataPointNotFoundError,
1190
1192
  DataPointStatus: () => DataPointStatus,
1193
+ DataPointVersionConflictError: () => DataPointVersionConflictError,
1191
1194
  DropboxStorage: () => DropboxStorage,
1192
1195
  ECIESError: () => ECIESError,
1193
1196
  ESCROW_DEPOSIT_ABI: () => ESCROW_DEPOSIT_ABI2,
@@ -1247,6 +1250,10 @@ __export(index_node_exports, {
1247
1250
  SignatureError: () => SignatureError,
1248
1251
  StorageError: () => StorageError,
1249
1252
  StorageManager: () => StorageManager,
1253
+ TOMBSTONE_DATA_HASH: () => TOMBSTONE_DATA_HASH,
1254
+ TOMBSTONE_DATA_HASH_PREIMAGE: () => TOMBSTONE_DATA_HASH_PREIMAGE,
1255
+ TOMBSTONE_METADATA_HASH: () => TOMBSTONE_METADATA_HASH,
1256
+ TOMBSTONE_METADATA_HASH_PREIMAGE: () => TOMBSTONE_METADATA_HASH_PREIMAGE,
1250
1257
  TransactionPendingError: () => TransactionPendingError,
1251
1258
  UserRejectedRequestError: () => UserRejectedRequestError,
1252
1259
  VanaError: () => VanaError,
@@ -1271,6 +1278,8 @@ __export(index_node_exports, {
1271
1278
  authorizeEscrowPayment: () => authorizeEscrowPayment,
1272
1279
  authorizeGrantPayment: () => authorizeGrantPayment,
1273
1280
  binaryWriteSignedBytes: () => binaryWriteSignedBytes,
1281
+ buildDataPointDeletionSignature: () => buildDataPointDeletionSignature,
1282
+ buildDataPointDeletionTypedData: () => buildDataPointDeletionTypedData,
1274
1283
  buildDepositNativeRequest: () => buildDepositNativeRequest,
1275
1284
  buildDepositTokenRequest: () => buildDepositTokenRequest,
1276
1285
  buildEscrowPaymentHeader: () => buildEscrowPaymentHeader,
@@ -1288,6 +1297,7 @@ __export(index_node_exports, {
1288
1297
  clearContractCache: () => clearContractCache,
1289
1298
  computeBodyHash: () => computeBodyHash,
1290
1299
  computePkceChallenge: () => computePkceChallenge,
1300
+ computeTombstoneHash: () => computeTombstoneHash,
1291
1301
  contractCacheForTesting: () => contractCacheForTesting,
1292
1302
  createBrowserPlatformAdapter: () => createBrowserPlatformAdapter,
1293
1303
  createDataFileEnvelope: () => createDataFileEnvelope,
@@ -1299,11 +1309,13 @@ __export(index_node_exports, {
1299
1309
  createPlatformAdapterFor: () => createPlatformAdapterFor,
1300
1310
  createPlatformAdapterSafe: () => createPlatformAdapterSafe,
1301
1311
  createVanaStorageProvider: () => createVanaStorageProvider,
1312
+ createViemDataPointDeletionSigner: () => createViemDataPointDeletionSigner,
1302
1313
  createViemPersonalServerLiteOwnerBindingSigner: () => createViemPersonalServerLiteOwnerBindingSigner,
1303
1314
  createViemPersonalServerRegistrationSigner: () => createViemPersonalServerRegistrationSigner,
1304
1315
  dataRegistryContractAddress: () => dataRegistryContractAddress,
1305
1316
  dataRegistryDomain: () => dataRegistryDomain,
1306
1317
  decryptWithPassword: () => decryptWithPassword,
1318
+ deleteDataPoint: () => deleteDataPoint,
1307
1319
  deriveDataPointId: () => deriveDataPointId,
1308
1320
  deriveMasterKey: () => deriveMasterKey,
1309
1321
  deriveScopeKey: () => deriveScopeKey,
@@ -1339,10 +1351,12 @@ __export(index_node_exports, {
1339
1351
  grantRevocationDomain: () => grantRevocationDomain,
1340
1352
  hasAction: () => hasAction,
1341
1353
  isDataPointId: () => isDataPointId,
1354
+ isDataPointTombstone: () => isDataPointTombstone,
1342
1355
  isDataPortabilityGatewayConfig: () => isDataPortabilityGatewayConfig,
1343
1356
  isECIESEncrypted: () => isECIESEncrypted,
1344
1357
  isPlatformSupported: () => isPlatformSupported,
1345
1358
  isRedactedLineageNode: () => isRedactedLineageNode,
1359
+ isTombstoneHashes: () => isTombstoneHashes,
1346
1360
  mainnetServices: () => mainnetServices,
1347
1361
  moksha: () => moksha,
1348
1362
  mokshaServices: () => mokshaServices,
@@ -1377,6 +1391,7 @@ __export(index_node_exports, {
1377
1391
  signPersonalServerRegistrationWithAccount: () => signPersonalServerRegistrationWithAccount,
1378
1392
  toDirectFeeBreakdown: () => toDirectFeeBreakdown,
1379
1393
  toDirectPaymentReceipt: () => toDirectPaymentReceipt,
1394
+ tombstoneDeletedAt: () => tombstoneDeletedAt,
1380
1395
  tryGrantPermissions: () => tryGrantPermissions,
1381
1396
  vanaMainnet: () => vanaMainnet2,
1382
1397
  verifyGrantRegistration: () => verifyGrantRegistration,
@@ -1598,6 +1613,27 @@ var LineageReadError = class extends VanaError {
1598
1613
  errorCode;
1599
1614
  details;
1600
1615
  };
1616
+ var DataPointDeletedError = class extends VanaError {
1617
+ constructor(message, details = {}) {
1618
+ super(message, "DATA_POINT_DELETED");
1619
+ this.details = details;
1620
+ }
1621
+ details;
1622
+ };
1623
+ var DataPointNotFoundError = class extends VanaError {
1624
+ constructor(message, details = {}) {
1625
+ super(message, "DATA_POINT_NOT_FOUND");
1626
+ this.details = details;
1627
+ }
1628
+ details;
1629
+ };
1630
+ var DataPointVersionConflictError = class extends VanaError {
1631
+ constructor(message, details = {}) {
1632
+ super(message, "DATA_POINT_VERSION_CONFLICT");
1633
+ this.details = details;
1634
+ }
1635
+ details;
1636
+ };
1601
1637
 
1602
1638
  // src/contracts/contractController.ts
1603
1639
  var import_viem3 = require("viem");
@@ -29354,6 +29390,22 @@ function getProtocolNetworkChainId(network) {
29354
29390
  return PROTOCOL_NETWORK_CHAIN_IDS[network];
29355
29391
  }
29356
29392
 
29393
+ // src/utils/response-body.ts
29394
+ function isPlainObject(value) {
29395
+ return typeof value === "object" && value !== null && !Array.isArray(value);
29396
+ }
29397
+ async function readJsonValue(res) {
29398
+ try {
29399
+ return await res.json();
29400
+ } catch {
29401
+ return null;
29402
+ }
29403
+ }
29404
+ async function readJsonObject(res) {
29405
+ const value = await readJsonValue(res);
29406
+ return isPlainObject(value) ? value : {};
29407
+ }
29408
+
29357
29409
  // src/storage/providers/vana-storage.ts
29358
29410
  var DEFAULT_ENDPOINT = "https://storage.vana.org";
29359
29411
  var LEGACY_BLOB_PATH_PREFIX = "/v1/blobs";
@@ -29525,6 +29577,65 @@ var VanaStorage = class {
29525
29577
  }
29526
29578
  return true;
29527
29579
  }
29580
+ /**
29581
+ * Delete every version's blob under `(owner, scope)` --
29582
+ * `DELETE {prefix}/{owner}/{scope}` on vana-storage, signed with the same
29583
+ * Web3Signed header as uploads (aud = endpoint origin, empty bodyHash).
29584
+ * The worker accepts the owner's own signature or a personal server the
29585
+ * owner registered with the gateway.
29586
+ *
29587
+ * @param ownerAddress - Must equal the provider's configured owner; a
29588
+ * mismatch throws before anything is signed so this wallet can never be
29589
+ * induced to sign a delete for another namespace.
29590
+ * @param scope - The scope segment, e.g. `"instagram.profile"`.
29591
+ */
29592
+ async deleteScope(ownerAddress, scope) {
29593
+ if (ownerAddress.toLowerCase() !== this.ownerAddress) {
29594
+ throw new StorageError(
29595
+ `deleteScope owner '${ownerAddress}' does not match the configured owner '${this.ownerAddress}'`,
29596
+ "INVALID_OWNER",
29597
+ "vana-storage"
29598
+ );
29599
+ }
29600
+ if (scope.length === 0 || scope.includes("/") || isTraversalSegment(scope)) {
29601
+ throw new StorageError(
29602
+ `scope must be a single non-empty path segment, got '${scope}'`,
29603
+ "INVALID_SCOPE",
29604
+ "vana-storage"
29605
+ );
29606
+ }
29607
+ const path = `${this.blobPathPrefix}/${this.ownerAddress}/${encodeURIComponent(scope)}`;
29608
+ const header = await this.signRequest("DELETE", path);
29609
+ let response;
29610
+ try {
29611
+ response = await this.fetchImpl(`${this.endpoint}${path}`, {
29612
+ method: "DELETE",
29613
+ headers: { authorization: header }
29614
+ });
29615
+ } catch (cause) {
29616
+ throw new StorageError(
29617
+ `vana-storage scope delete network error: ${describe(cause)}`,
29618
+ "DELETE_ERROR",
29619
+ "vana-storage",
29620
+ { cause: cause instanceof Error ? cause : void 0 }
29621
+ );
29622
+ }
29623
+ if (!response.ok) {
29624
+ const responseText = await safeText(response);
29625
+ throw new StorageError(
29626
+ `vana-storage scope delete failed: ${response.status} ${response.statusText} - ${responseText}`,
29627
+ "DELETE_FAILED",
29628
+ "vana-storage"
29629
+ );
29630
+ }
29631
+ const body = await readJsonObject(response);
29632
+ return {
29633
+ deleted: typeof body["deleted"] === "boolean" ? body["deleted"] : true,
29634
+ scope: typeof body["scope"] === "string" ? body["scope"] : scope,
29635
+ count: nonNegativeInteger(body["count"]) ?? 0,
29636
+ totalBytes: nonNegativeInteger(body["totalBytes"]) ?? 0
29637
+ };
29638
+ }
29528
29639
  getConfig() {
29529
29640
  return {
29530
29641
  name: "vana-storage",
@@ -29653,6 +29764,12 @@ function encodeRelativePath(filename) {
29653
29764
  }
29654
29765
  return parts.map((p) => encodeURIComponent(p)).join("/");
29655
29766
  }
29767
+ function isTraversalSegment(segment) {
29768
+ return segment === "." || segment === "..";
29769
+ }
29770
+ function nonNegativeInteger(value) {
29771
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : void 0;
29772
+ }
29656
29773
  function describe(value) {
29657
29774
  if (value instanceof Error) return value.message;
29658
29775
  return String(value);
@@ -33756,270 +33873,12 @@ function buildMarkDataPointUnavailableRequest(config, input) {
33756
33873
  });
33757
33874
  }
33758
33875
 
33759
- // src/protocol/data-file.ts
33760
- var import_zod = require("zod");
33761
- var DataFileEnvelopeSchema = import_zod.z.object({
33762
- $schema: import_zod.z.string().url().optional(),
33763
- version: import_zod.z.literal("1.0"),
33764
- scope: import_zod.z.string(),
33765
- schemaId: import_zod.z.string().optional(),
33766
- collectedAt: import_zod.z.string().datetime(),
33767
- data: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown())
33768
- });
33769
- function createDataFileEnvelope(scope, collectedAt, data, schemaUrl, schemaId) {
33770
- return {
33771
- ...schemaUrl !== void 0 && { $schema: schemaUrl },
33772
- ...schemaId !== void 0 && { schemaId },
33773
- version: "1.0",
33774
- scope,
33775
- collectedAt,
33776
- data
33777
- };
33778
- }
33779
- var IngestResponseSchema = import_zod.z.object({
33780
- scope: import_zod.z.string(),
33781
- collectedAt: import_zod.z.string().datetime(),
33782
- status: import_zod.z.enum(["stored", "syncing"])
33783
- });
33784
-
33785
- // src/protocol/personal-server-data.ts
33786
- function personalServerDataReadPath(scope) {
33787
- return `/v1/data/${encodeURIComponent(scope)}`;
33788
- }
33789
- async function buildPersonalServerDataReadRequest(params) {
33790
- const path = personalServerDataReadPath(params.scope);
33791
- const baseUrl = params.personalServerUrl.replace(/\/+$/, "");
33792
- const audience = params.audience ?? baseUrl;
33793
- const headers = new Headers(params.headers);
33794
- headers.set(
33795
- "Authorization",
33796
- await buildWeb3SignedHeader({
33797
- aud: audience,
33798
- grantId: params.grantId,
33799
- method: "GET",
33800
- signMessage: params.signMessage,
33801
- uri: path
33802
- })
33803
- );
33804
- return new Request(`${baseUrl}${path}`, {
33805
- headers,
33806
- method: "GET"
33807
- });
33808
- }
33809
- async function readPersonalServerData(params) {
33810
- const fetchFn = params.fetch ?? globalThis.fetch;
33811
- if (fetchFn === void 0) {
33812
- throw new Error("No fetch implementation available");
33813
- }
33814
- const request = await buildPersonalServerDataReadRequest(params);
33815
- const response = await fetchFn(request);
33816
- if (!response.ok) {
33817
- throw new Error(
33818
- `Personal Server data read failed: ${response.status} ${response.statusText}`
33819
- );
33820
- }
33821
- return DataFileEnvelopeSchema.parse(await response.json());
33822
- }
33823
-
33824
- // src/protocol/scopes.ts
33825
- var import_zod2 = require("zod");
33826
- var SOURCE_RE = /^[a-z0-9][a-z0-9_]*$/;
33827
- var TAIL_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9_]*$/;
33828
- var ScopeSchema = import_zod2.z.string().refine(
33829
- (scope) => {
33830
- const parts = scope.split(".");
33831
- if (parts.length < 2 || parts.length > 3) return false;
33832
- const [source, ...tail] = parts;
33833
- return SOURCE_RE.test(source) && tail.every((part) => TAIL_SEGMENT_RE.test(part));
33834
- },
33835
- {
33836
- message: "Scope must be {source}.{category}[.{subcategory}]; source lowercase, tail may keep the historical camelCase form (e.g. spotify.savedTracks)"
33837
- }
33838
- );
33839
- function parseScope(scope) {
33840
- const validated = ScopeSchema.parse(scope);
33841
- const parts = validated.split(".");
33842
- return {
33843
- source: parts[0],
33844
- category: parts[1],
33845
- subcategory: parts[2],
33846
- raw: validated
33847
- };
33848
- }
33849
- function scopeToPathSegments(scope) {
33850
- const parsed = parseScope(scope);
33851
- const segments = [parsed.source, parsed.category];
33852
- if (parsed.subcategory) {
33853
- segments.push(parsed.subcategory);
33854
- }
33855
- return segments;
33856
- }
33857
- function scopeMatchesPattern(requestedScope, grantPattern) {
33858
- if (grantPattern === "*") return true;
33859
- if (grantPattern.endsWith(".*")) {
33860
- const prefix = grantPattern.slice(0, -1);
33861
- return requestedScope.startsWith(prefix);
33862
- }
33863
- return requestedScope === grantPattern;
33864
- }
33865
- function scopeCoveredByGrant(requestedScope, grantedScopes) {
33866
- return grantedScopes.some(
33867
- (pattern) => scopeMatchesPattern(requestedScope, pattern)
33868
- );
33869
- }
33870
-
33871
- // src/protocol/scope-actions.ts
33872
- var SCOPE_ACTIONS = ["read", "write"];
33873
- var InvalidScopeEntryError = class extends Error {
33874
- /** The offending entry, verbatim (unknown because it may not be a string). */
33875
- entry;
33876
- constructor(entry, reason) {
33877
- super(`Invalid scope entry ${describeValue(entry)}: ${reason}`);
33878
- this.name = "InvalidScopeEntryError";
33879
- this.entry = entry;
33880
- }
33881
- };
33882
- var OPERATION_SEPARATOR = ":";
33883
- function describeValue(value) {
33884
- if (typeof value === "string") return JSON.stringify(value);
33885
- if (value === null) return "null";
33886
- return `[${typeof value}]`;
33887
- }
33888
- var OPERATION_BY_PREFIX = {
33889
- write: "write"
33890
- };
33891
- function assertScopePart(entry, scope) {
33892
- if (scope.length === 0) {
33893
- throw new InvalidScopeEntryError(entry, "scope part is empty");
33894
- }
33895
- if (scope.includes(OPERATION_SEPARATOR)) {
33896
- throw new InvalidScopeEntryError(
33897
- entry,
33898
- `scope part must not contain "${OPERATION_SEPARATOR}"`
33899
- );
33900
- }
33901
- }
33902
- function parseScopeEntry(entry) {
33903
- const raw = entry;
33904
- if (typeof raw !== "string") {
33905
- throw new InvalidScopeEntryError(raw, "entry must be a string");
33906
- }
33907
- const separatorIndex = entry.indexOf(OPERATION_SEPARATOR);
33908
- if (separatorIndex === -1) {
33909
- assertScopePart(entry, entry);
33910
- return { scope: entry, action: "read" };
33911
- }
33912
- const prefix = entry.slice(0, separatorIndex);
33913
- const scope = entry.slice(separatorIndex + 1);
33914
- const action = Object.hasOwn(OPERATION_BY_PREFIX, prefix) ? OPERATION_BY_PREFIX[prefix] : void 0;
33915
- if (action === void 0) {
33916
- throw new InvalidScopeEntryError(
33917
- entry,
33918
- `unknown operation "${prefix}" (known: ${Object.keys(OPERATION_BY_PREFIX).join(", ")}; read has no prefix)`
33919
- );
33920
- }
33921
- assertScopePart(entry, scope);
33922
- return { scope, action };
33923
- }
33924
- function formatScopeEntry(parsed) {
33925
- const { scope, action } = parsed;
33926
- assertScopePart(scope, scope);
33927
- if (action === "read") return scope;
33928
- const prefix = Object.entries(OPERATION_BY_PREFIX).find(
33929
- ([, candidate]) => candidate === action
33930
- )?.[0];
33931
- if (prefix === void 0) {
33932
- throw new InvalidScopeEntryError(
33933
- scope,
33934
- `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
33935
- );
33936
- }
33937
- return `${prefix}${OPERATION_SEPARATOR}${scope}`;
33938
- }
33939
- function compareScopes(a, b) {
33940
- if (a < b) return -1;
33941
- if (a > b) return 1;
33942
- return 0;
33943
- }
33944
- function sortActions(actions) {
33945
- const present = new Set(actions);
33946
- return SCOPE_ACTIONS.filter((action) => present.has(action));
33947
- }
33948
- function grantPermissions(scopes) {
33949
- const byScope = /* @__PURE__ */ new Map();
33950
- for (const entry of scopes) {
33951
- const { scope, action } = parseScopeEntry(entry);
33952
- let actions = byScope.get(scope);
33953
- if (actions === void 0) {
33954
- actions = /* @__PURE__ */ new Set();
33955
- byScope.set(scope, actions);
33956
- }
33957
- actions.add(action);
33958
- }
33959
- return [...byScope.keys()].sort(compareScopes).map((scope) => ({
33960
- scope,
33961
- actions: sortActions(byScope.get(scope) ?? [])
33962
- }));
33963
- }
33964
- function permissionsToScopes(permissions) {
33965
- const byScope = /* @__PURE__ */ new Map();
33966
- for (const { scope, actions } of permissions) {
33967
- let merged = byScope.get(scope);
33968
- if (merged === void 0) {
33969
- merged = /* @__PURE__ */ new Set();
33970
- byScope.set(scope, merged);
33971
- }
33972
- for (const action of actions) {
33973
- if (!SCOPE_ACTIONS.includes(action)) {
33974
- throw new InvalidScopeEntryError(
33975
- scope,
33976
- `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
33977
- );
33978
- }
33979
- merged.add(action);
33980
- }
33981
- }
33982
- const entries = [];
33983
- for (const scope of [...byScope.keys()].sort(compareScopes)) {
33984
- for (const action of sortActions(byScope.get(scope) ?? [])) {
33985
- entries.push(formatScopeEntry({ scope, action }));
33986
- }
33987
- }
33988
- return entries;
33989
- }
33990
- function hasAction(scopes, scope, action) {
33991
- if (scope.includes(OPERATION_SEPARATOR)) return false;
33992
- for (const entry of scopes) {
33993
- let parsed;
33994
- try {
33995
- parsed = parseScopeEntry(entry);
33996
- } catch (error) {
33997
- if (error instanceof InvalidScopeEntryError) continue;
33998
- throw error;
33999
- }
34000
- if (parsed.action === action && scopeMatchesPattern(scope, parsed.scope)) {
34001
- return true;
34002
- }
34003
- }
34004
- return false;
34005
- }
34006
- function tryGrantPermissions(scopes) {
34007
- try {
34008
- return grantPermissions(scopes);
34009
- } catch (error) {
34010
- if (error instanceof InvalidScopeEntryError) return void 0;
34011
- throw error;
34012
- }
34013
- }
34014
-
34015
- // src/protocol/personal-server-write.ts
34016
- var import_sha25 = require("@noble/hashes/sha2");
33876
+ // src/protocol/data-point-deletion.ts
34017
33877
  var import_viem22 = require("viem");
34018
- var import_zod4 = require("zod");
34019
33878
 
34020
33879
  // src/protocol/lineage.ts
34021
33880
  var import_viem21 = require("viem");
34022
- var import_zod3 = require("zod");
33881
+ var import_zod = require("zod");
34023
33882
 
34024
33883
  // src/protocol/personal-server-error-body.ts
34025
33884
  function isRecord2(value) {
@@ -34111,10 +33970,10 @@ function deriveDataPointId(ownerAddress, scope) {
34111
33970
  )
34112
33971
  );
34113
33972
  }
34114
- var DataPointIdSchema = import_zod3.z.string().regex(DATA_POINT_ID_PATTERN).transform((value) => value.toLowerCase());
33973
+ var DataPointIdSchema = import_zod.z.string().regex(DATA_POINT_ID_PATTERN).transform((value) => value.toLowerCase());
34115
33974
  var VERSION_PATTERN = /^[1-9]\d*$/;
34116
33975
  var NODE_VERSION_PATTERN = /^(0|[1-9]\d*)$/;
34117
- var VersionSchema = import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number()]).transform(String).refine((value) => NODE_VERSION_PATTERN.test(value), {
33976
+ var VersionSchema = import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).transform(String).refine((value) => NODE_VERSION_PATTERN.test(value), {
34118
33977
  message: "version must be a decimal integer"
34119
33978
  });
34120
33979
  var ViewVersionSchema = VersionSchema.refine(
@@ -34138,41 +33997,41 @@ function assertDerivedScopeNaming(derivedScope, sourceScopes) {
34138
33997
  }
34139
33998
  }
34140
33999
  }
34141
- var LineageNodeSchema = import_zod3.z.object({
34000
+ var LineageNodeSchema = import_zod.z.object({
34142
34001
  dataPointId: DataPointIdSchema,
34143
- scope: import_zod3.z.string(),
34002
+ scope: import_zod.z.string(),
34144
34003
  /**
34145
34004
  * The node's current version, decimal string; `"0"` for a source that no
34146
34005
  * longer resolves to a registered data point.
34147
34006
  */
34148
34007
  version: VersionSchema,
34149
34008
  /** The node's tombstone time, or `null` when live. */
34150
- deletedAt: import_zod3.z.string().nullable()
34009
+ deletedAt: import_zod.z.string().nullable()
34151
34010
  });
34152
- var RedactedLineageNodeSchema = import_zod3.z.object({
34011
+ var RedactedLineageNodeSchema = import_zod.z.object({
34153
34012
  dataPointId: DataPointIdSchema,
34154
- redacted: import_zod3.z.literal(true)
34013
+ redacted: import_zod.z.literal(true)
34155
34014
  });
34156
- var LineageEntrySchema = import_zod3.z.union([
34015
+ var LineageEntrySchema = import_zod.z.union([
34157
34016
  RedactedLineageNodeSchema,
34158
34017
  LineageNodeSchema
34159
34018
  ]);
34160
- var LineageGraphSchema = import_zod3.z.object({
34019
+ var LineageGraphSchema = import_zod.z.object({
34161
34020
  dataPointId: DataPointIdSchema,
34162
34021
  /** The data point owner; every node in the view belongs to it. */
34163
- ownerAddress: import_zod3.z.string().optional(),
34164
- scope: import_zod3.z.string(),
34022
+ ownerAddress: import_zod.z.string().optional(),
34023
+ scope: import_zod.z.string(),
34165
34024
  /**
34166
34025
  * The derived record's version whose lineage is shown: the requested one,
34167
34026
  * else the current one, else (current is a tombstone) the last version
34168
34027
  * that carried lineage.
34169
34028
  */
34170
34029
  version: ViewVersionSchema,
34171
- deletedAt: import_zod3.z.string().nullable(),
34172
- sources: import_zod3.z.array(LineageEntrySchema),
34173
- derivatives: import_zod3.z.array(LineageEntrySchema),
34030
+ deletedAt: import_zod.z.string().nullable(),
34031
+ sources: import_zod.z.array(LineageEntrySchema),
34032
+ derivatives: import_zod.z.array(LineageEntrySchema),
34174
34033
  /** `true` when `derivatives` was cut at the server's cap (1000). */
34175
- derivativesTruncated: import_zod3.z.boolean().optional()
34034
+ derivativesTruncated: import_zod.z.boolean().optional()
34176
34035
  });
34177
34036
  function isRedactedLineageNode(entry) {
34178
34037
  return "redacted" in entry && entry.redacted === true;
@@ -34317,7 +34176,449 @@ function getLineage(params) {
34317
34176
  return "personalServerUrl" in params ? getPersonalServerLineage(params) : getGatewayLineage(params);
34318
34177
  }
34319
34178
 
34179
+ // src/protocol/data-point-deletion.ts
34180
+ var TOMBSTONE_DATA_HASH_PREIMAGE = "vana.data-point.tombstone.v1";
34181
+ var TOMBSTONE_METADATA_HASH_PREIMAGE = "vana.data-point.tombstone.metadata.v1";
34182
+ var TOMBSTONE_DATA_HASH = "0x30c45ee72fe56d1927701316925ab7ceacd3b6f9267061735d59396f075c6222";
34183
+ var TOMBSTONE_METADATA_HASH = "0xc5255a141acd6a2ae55971b62c0a85977c2511989dc114ad2abc2b7644f57d90";
34184
+ function computeTombstoneHash(preimage) {
34185
+ return (0, import_viem22.keccak256)((0, import_viem22.stringToBytes)(preimage));
34186
+ }
34187
+ function isTombstoneHashes(dataHash, metadataHash) {
34188
+ return typeof dataHash === "string" && typeof metadataHash === "string" && dataHash.toLowerCase() === TOMBSTONE_DATA_HASH && metadataHash.toLowerCase() === TOMBSTONE_METADATA_HASH;
34189
+ }
34190
+ function isDataPointTombstone(value) {
34191
+ if (!isPlainObject(value)) return false;
34192
+ if (typeof value["deletedAt"] === "string") return true;
34193
+ return isTombstoneHashes(
34194
+ typeof value["dataHash"] === "string" ? value["dataHash"] : void 0,
34195
+ typeof value["metadataHash"] === "string" ? value["metadataHash"] : void 0
34196
+ );
34197
+ }
34198
+ function tombstoneDeletedAt(value) {
34199
+ if (!isPlainObject(value)) return null;
34200
+ const deletedAt = value["deletedAt"];
34201
+ return typeof deletedAt === "string" ? deletedAt : null;
34202
+ }
34203
+ function assertAddress4(value, name) {
34204
+ if (!(0, import_viem22.isAddress)(value)) {
34205
+ throw new Error(`${name} must be a valid EVM address`);
34206
+ }
34207
+ }
34208
+ function assertUint256(value, name) {
34209
+ if (value < 0n || value > import_viem22.maxUint256) {
34210
+ throw new Error(`${name} must fit in uint256, got ${value}`);
34211
+ }
34212
+ }
34213
+ function getAccountAddress3(account) {
34214
+ if (!account) return void 0;
34215
+ return typeof account === "string" ? account : account.address;
34216
+ }
34217
+ function isDataPointDeletionSigner(source) {
34218
+ return "address" in source && typeof source.signTypedData === "function";
34219
+ }
34220
+ function createViemDataPointDeletionSigner(source, options = {}) {
34221
+ if (isDataPointDeletionSigner(source)) {
34222
+ return source;
34223
+ }
34224
+ const accountAddress2 = getAccountAddress3(options.account) ?? getAccountAddress3(source.account);
34225
+ if (accountAddress2) {
34226
+ return {
34227
+ address: accountAddress2,
34228
+ signTypedData: (typedData) => source.signTypedData({
34229
+ ...typedData,
34230
+ account: options.account ?? source.account ?? accountAddress2
34231
+ })
34232
+ };
34233
+ }
34234
+ throw new Error(
34235
+ "Viem wallet client requires an account option or account property"
34236
+ );
34237
+ }
34238
+ function buildDataPointDeletionTypedData(input) {
34239
+ assertAddress4(input.ownerAddress, "ownerAddress");
34240
+ if (input.scope.length === 0) {
34241
+ throw new Error("scope must be a non-empty string");
34242
+ }
34243
+ if (input.expectedVersion <= 0n) {
34244
+ throw new Error("expectedVersion must be a positive version number");
34245
+ }
34246
+ assertUint256(input.expectedVersion, "expectedVersion");
34247
+ return {
34248
+ domain: dataRegistryDomain(input.config),
34249
+ types: ADD_DATA_TYPES,
34250
+ primaryType: "AddData",
34251
+ message: {
34252
+ ownerAddress: input.ownerAddress,
34253
+ scope: input.scope,
34254
+ dataHash: TOMBSTONE_DATA_HASH,
34255
+ metadataHash: TOMBSTONE_METADATA_HASH,
34256
+ expectedVersion: input.expectedVersion
34257
+ }
34258
+ };
34259
+ }
34260
+ async function buildDataPointDeletionSignature(input) {
34261
+ const typedData = buildDataPointDeletionTypedData({
34262
+ ownerAddress: input.signer.address,
34263
+ scope: input.scope,
34264
+ expectedVersion: input.expectedVersion,
34265
+ config: input.config
34266
+ });
34267
+ const signature = await input.signer.signTypedData(typedData);
34268
+ return {
34269
+ signature,
34270
+ signerAddress: input.signer.address,
34271
+ typedData
34272
+ };
34273
+ }
34274
+ function toError(value) {
34275
+ return value instanceof Error ? value : new Error(String(value));
34276
+ }
34277
+ function parseExpectedVersion(value) {
34278
+ if (typeof value !== "string" || !/^\d+$/.test(value)) {
34279
+ throw new Error(
34280
+ `Gateway returned a malformed expectedVersion: ${JSON.stringify(value)}`
34281
+ );
34282
+ }
34283
+ const parsed = BigInt(value);
34284
+ assertUint256(parsed, "Gateway expectedVersion");
34285
+ return parsed;
34286
+ }
34287
+ async function deleteDataPoint(input) {
34288
+ const ownerAddress = input.signer.address;
34289
+ const dataPointId = deriveDataPointId(ownerAddress, input.scope);
34290
+ let currentVersion = input.currentVersion;
34291
+ if (currentVersion === void 0) {
34292
+ const record = await input.gateway.getDataPoint(dataPointId);
34293
+ if (record === null) {
34294
+ throw new DataPointNotFoundError(
34295
+ `No data point registered for scope '${input.scope}' owned by ${ownerAddress}`,
34296
+ { dataPointId, scope: input.scope, ownerAddress }
34297
+ );
34298
+ }
34299
+ if (isDataPointTombstone(record)) {
34300
+ throw new DataPointDeletedError(
34301
+ `Data point ${dataPointId} (scope '${input.scope}') is already deleted`,
34302
+ {
34303
+ dataPointId,
34304
+ scope: input.scope,
34305
+ ownerAddress,
34306
+ deletedAt: tombstoneDeletedAt(record)
34307
+ }
34308
+ );
34309
+ }
34310
+ currentVersion = parseExpectedVersion(record.expectedVersion);
34311
+ }
34312
+ if (currentVersion < 0n || currentVersion >= import_viem22.maxUint256) {
34313
+ throw new Error(
34314
+ `currentVersion ${currentVersion} cannot be incremented to a uint256 tombstone version`
34315
+ );
34316
+ }
34317
+ const tombstoneVersion = currentVersion + 1n;
34318
+ const signed = await buildDataPointDeletionSignature({
34319
+ signer: input.signer,
34320
+ scope: input.scope,
34321
+ expectedVersion: tombstoneVersion,
34322
+ config: input.config
34323
+ });
34324
+ const tombstone = await input.gateway.deleteDataPoint({
34325
+ ownerAddress,
34326
+ scope: input.scope,
34327
+ expectedVersion: tombstoneVersion.toString(),
34328
+ signature: signed.signature
34329
+ });
34330
+ const base = {
34331
+ dataPointId,
34332
+ ownerAddress,
34333
+ scope: input.scope,
34334
+ version: tombstoneVersion.toString(),
34335
+ signature: signed.signature,
34336
+ tombstone
34337
+ };
34338
+ try {
34339
+ const storage = await input.storage.deleteScope(ownerAddress, input.scope);
34340
+ return { ...base, status: "deleted", storage };
34341
+ } catch (cause) {
34342
+ return { ...base, status: "partial", storageError: toError(cause) };
34343
+ }
34344
+ }
34345
+
34346
+ // src/protocol/data-file.ts
34347
+ var import_zod2 = require("zod");
34348
+ var DataFileEnvelopeSchema = import_zod2.z.object({
34349
+ $schema: import_zod2.z.string().url().optional(),
34350
+ version: import_zod2.z.literal("1.0"),
34351
+ scope: import_zod2.z.string(),
34352
+ schemaId: import_zod2.z.string().optional(),
34353
+ collectedAt: import_zod2.z.string().datetime(),
34354
+ data: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown())
34355
+ });
34356
+ function createDataFileEnvelope(scope, collectedAt, data, schemaUrl, schemaId) {
34357
+ return {
34358
+ ...schemaUrl !== void 0 && { $schema: schemaUrl },
34359
+ ...schemaId !== void 0 && { schemaId },
34360
+ version: "1.0",
34361
+ scope,
34362
+ collectedAt,
34363
+ data
34364
+ };
34365
+ }
34366
+ var IngestResponseSchema = import_zod2.z.object({
34367
+ scope: import_zod2.z.string(),
34368
+ collectedAt: import_zod2.z.string().datetime(),
34369
+ status: import_zod2.z.enum(["stored", "syncing"])
34370
+ });
34371
+
34372
+ // src/protocol/personal-server-data.ts
34373
+ function personalServerDataReadPath(scope) {
34374
+ return `/v1/data/${encodeURIComponent(scope)}`;
34375
+ }
34376
+ async function buildPersonalServerDataReadRequest(params) {
34377
+ const path = personalServerDataReadPath(params.scope);
34378
+ const baseUrl = params.personalServerUrl.replace(/\/+$/, "");
34379
+ const audience = params.audience ?? baseUrl;
34380
+ const headers = new Headers(params.headers);
34381
+ headers.set(
34382
+ "Authorization",
34383
+ await buildWeb3SignedHeader({
34384
+ aud: audience,
34385
+ grantId: params.grantId,
34386
+ method: "GET",
34387
+ signMessage: params.signMessage,
34388
+ uri: path
34389
+ })
34390
+ );
34391
+ return new Request(`${baseUrl}${path}`, {
34392
+ headers,
34393
+ method: "GET"
34394
+ });
34395
+ }
34396
+ async function readPersonalServerData(params) {
34397
+ const fetchFn = params.fetch ?? globalThis.fetch;
34398
+ if (fetchFn === void 0) {
34399
+ throw new Error("No fetch implementation available");
34400
+ }
34401
+ const request = await buildPersonalServerDataReadRequest(params);
34402
+ const response = await fetchFn(request);
34403
+ if (response.status === 410) {
34404
+ throw new DataPointDeletedError(
34405
+ `Personal Server scope '${params.scope}' has been deleted`,
34406
+ {
34407
+ scope: params.scope,
34408
+ deletedAt: tombstoneDeletedAt(await readJsonValue(response))
34409
+ }
34410
+ );
34411
+ }
34412
+ if (!response.ok) {
34413
+ throw new Error(
34414
+ `Personal Server data read failed: ${response.status} ${response.statusText}`
34415
+ );
34416
+ }
34417
+ const body = await response.json();
34418
+ if (isDataPointTombstone(body)) {
34419
+ throw new DataPointDeletedError(
34420
+ `Personal Server scope '${params.scope}' has been deleted`,
34421
+ { scope: params.scope, deletedAt: tombstoneDeletedAt(body) }
34422
+ );
34423
+ }
34424
+ return DataFileEnvelopeSchema.parse(body);
34425
+ }
34426
+
34427
+ // src/protocol/scopes.ts
34428
+ var import_zod3 = require("zod");
34429
+ var SOURCE_RE = /^[a-z0-9][a-z0-9_]*$/;
34430
+ var TAIL_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9_]*$/;
34431
+ var ScopeSchema = import_zod3.z.string().refine(
34432
+ (scope) => {
34433
+ const parts = scope.split(".");
34434
+ if (parts.length < 2 || parts.length > 3) return false;
34435
+ const [source, ...tail] = parts;
34436
+ return SOURCE_RE.test(source) && tail.every((part) => TAIL_SEGMENT_RE.test(part));
34437
+ },
34438
+ {
34439
+ message: "Scope must be {source}.{category}[.{subcategory}]; source lowercase, tail may keep the historical camelCase form (e.g. spotify.savedTracks)"
34440
+ }
34441
+ );
34442
+ function parseScope(scope) {
34443
+ const validated = ScopeSchema.parse(scope);
34444
+ const parts = validated.split(".");
34445
+ return {
34446
+ source: parts[0],
34447
+ category: parts[1],
34448
+ subcategory: parts[2],
34449
+ raw: validated
34450
+ };
34451
+ }
34452
+ function scopeToPathSegments(scope) {
34453
+ const parsed = parseScope(scope);
34454
+ const segments = [parsed.source, parsed.category];
34455
+ if (parsed.subcategory) {
34456
+ segments.push(parsed.subcategory);
34457
+ }
34458
+ return segments;
34459
+ }
34460
+ function scopeMatchesPattern(requestedScope, grantPattern) {
34461
+ if (grantPattern === "*") return true;
34462
+ if (grantPattern.endsWith(".*")) {
34463
+ const prefix = grantPattern.slice(0, -1);
34464
+ return requestedScope.startsWith(prefix);
34465
+ }
34466
+ return requestedScope === grantPattern;
34467
+ }
34468
+ function scopeCoveredByGrant(requestedScope, grantedScopes) {
34469
+ return grantedScopes.some(
34470
+ (pattern) => scopeMatchesPattern(requestedScope, pattern)
34471
+ );
34472
+ }
34473
+
34474
+ // src/protocol/scope-actions.ts
34475
+ var SCOPE_ACTIONS = ["read", "write"];
34476
+ var InvalidScopeEntryError = class extends Error {
34477
+ /** The offending entry, verbatim (unknown because it may not be a string). */
34478
+ entry;
34479
+ constructor(entry, reason) {
34480
+ super(`Invalid scope entry ${describeValue(entry)}: ${reason}`);
34481
+ this.name = "InvalidScopeEntryError";
34482
+ this.entry = entry;
34483
+ }
34484
+ };
34485
+ var OPERATION_SEPARATOR = ":";
34486
+ function describeValue(value) {
34487
+ if (typeof value === "string") return JSON.stringify(value);
34488
+ if (value === null) return "null";
34489
+ return `[${typeof value}]`;
34490
+ }
34491
+ var OPERATION_BY_PREFIX = {
34492
+ write: "write"
34493
+ };
34494
+ function assertScopePart(entry, scope) {
34495
+ if (scope.length === 0) {
34496
+ throw new InvalidScopeEntryError(entry, "scope part is empty");
34497
+ }
34498
+ if (scope.includes(OPERATION_SEPARATOR)) {
34499
+ throw new InvalidScopeEntryError(
34500
+ entry,
34501
+ `scope part must not contain "${OPERATION_SEPARATOR}"`
34502
+ );
34503
+ }
34504
+ }
34505
+ function parseScopeEntry(entry) {
34506
+ const raw = entry;
34507
+ if (typeof raw !== "string") {
34508
+ throw new InvalidScopeEntryError(raw, "entry must be a string");
34509
+ }
34510
+ const separatorIndex = entry.indexOf(OPERATION_SEPARATOR);
34511
+ if (separatorIndex === -1) {
34512
+ assertScopePart(entry, entry);
34513
+ return { scope: entry, action: "read" };
34514
+ }
34515
+ const prefix = entry.slice(0, separatorIndex);
34516
+ const scope = entry.slice(separatorIndex + 1);
34517
+ const action = Object.hasOwn(OPERATION_BY_PREFIX, prefix) ? OPERATION_BY_PREFIX[prefix] : void 0;
34518
+ if (action === void 0) {
34519
+ throw new InvalidScopeEntryError(
34520
+ entry,
34521
+ `unknown operation "${prefix}" (known: ${Object.keys(OPERATION_BY_PREFIX).join(", ")}; read has no prefix)`
34522
+ );
34523
+ }
34524
+ assertScopePart(entry, scope);
34525
+ return { scope, action };
34526
+ }
34527
+ function formatScopeEntry(parsed) {
34528
+ const { scope, action } = parsed;
34529
+ assertScopePart(scope, scope);
34530
+ if (action === "read") return scope;
34531
+ const prefix = Object.entries(OPERATION_BY_PREFIX).find(
34532
+ ([, candidate]) => candidate === action
34533
+ )?.[0];
34534
+ if (prefix === void 0) {
34535
+ throw new InvalidScopeEntryError(
34536
+ scope,
34537
+ `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
34538
+ );
34539
+ }
34540
+ return `${prefix}${OPERATION_SEPARATOR}${scope}`;
34541
+ }
34542
+ function compareScopes(a, b) {
34543
+ if (a < b) return -1;
34544
+ if (a > b) return 1;
34545
+ return 0;
34546
+ }
34547
+ function sortActions(actions) {
34548
+ const present = new Set(actions);
34549
+ return SCOPE_ACTIONS.filter((action) => present.has(action));
34550
+ }
34551
+ function grantPermissions(scopes) {
34552
+ const byScope = /* @__PURE__ */ new Map();
34553
+ for (const entry of scopes) {
34554
+ const { scope, action } = parseScopeEntry(entry);
34555
+ let actions = byScope.get(scope);
34556
+ if (actions === void 0) {
34557
+ actions = /* @__PURE__ */ new Set();
34558
+ byScope.set(scope, actions);
34559
+ }
34560
+ actions.add(action);
34561
+ }
34562
+ return [...byScope.keys()].sort(compareScopes).map((scope) => ({
34563
+ scope,
34564
+ actions: sortActions(byScope.get(scope) ?? [])
34565
+ }));
34566
+ }
34567
+ function permissionsToScopes(permissions) {
34568
+ const byScope = /* @__PURE__ */ new Map();
34569
+ for (const { scope, actions } of permissions) {
34570
+ let merged = byScope.get(scope);
34571
+ if (merged === void 0) {
34572
+ merged = /* @__PURE__ */ new Set();
34573
+ byScope.set(scope, merged);
34574
+ }
34575
+ for (const action of actions) {
34576
+ if (!SCOPE_ACTIONS.includes(action)) {
34577
+ throw new InvalidScopeEntryError(
34578
+ scope,
34579
+ `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
34580
+ );
34581
+ }
34582
+ merged.add(action);
34583
+ }
34584
+ }
34585
+ const entries = [];
34586
+ for (const scope of [...byScope.keys()].sort(compareScopes)) {
34587
+ for (const action of sortActions(byScope.get(scope) ?? [])) {
34588
+ entries.push(formatScopeEntry({ scope, action }));
34589
+ }
34590
+ }
34591
+ return entries;
34592
+ }
34593
+ function hasAction(scopes, scope, action) {
34594
+ if (scope.includes(OPERATION_SEPARATOR)) return false;
34595
+ for (const entry of scopes) {
34596
+ let parsed;
34597
+ try {
34598
+ parsed = parseScopeEntry(entry);
34599
+ } catch (error) {
34600
+ if (error instanceof InvalidScopeEntryError) continue;
34601
+ throw error;
34602
+ }
34603
+ if (parsed.action === action && scopeMatchesPattern(scope, parsed.scope)) {
34604
+ return true;
34605
+ }
34606
+ }
34607
+ return false;
34608
+ }
34609
+ function tryGrantPermissions(scopes) {
34610
+ try {
34611
+ return grantPermissions(scopes);
34612
+ } catch (error) {
34613
+ if (error instanceof InvalidScopeEntryError) return void 0;
34614
+ throw error;
34615
+ }
34616
+ }
34617
+
34320
34618
  // src/protocol/personal-server-write.ts
34619
+ var import_sha25 = require("@noble/hashes/sha2");
34620
+ var import_viem23 = require("viem");
34621
+ var import_zod4 = require("zod");
34321
34622
  var WRITE_SESSION_PATH = "/v1/write/session";
34322
34623
  var WRITE_SIGNATURE_HEADER = "X-Vana-Write-Signature";
34323
34624
  var WRITE_METADATA_HEADER = "X-Vana-Metadata";
@@ -34405,7 +34706,7 @@ function nextProofIat(proofKey) {
34405
34706
  return sleep2(waitSec * 1e3).then(() => iat);
34406
34707
  }
34407
34708
  function proofKeyFor(parts) {
34408
- return (0, import_viem22.bytesToHex)(
34709
+ return (0, import_viem23.bytesToHex)(
34409
34710
  (0, import_sha25.sha256)(
34410
34711
  new TextEncoder().encode(
34411
34712
  JSON.stringify([
@@ -34413,7 +34714,7 @@ function proofKeyFor(parts) {
34413
34714
  parts.method,
34414
34715
  parts.uri,
34415
34716
  parts.grantId,
34416
- parts.signedBytes ? (0, import_viem22.bytesToHex)((0, import_sha25.sha256)(parts.signedBytes)) : ""
34717
+ parts.signedBytes ? (0, import_viem23.bytesToHex)((0, import_sha25.sha256)(parts.signedBytes)) : ""
34417
34718
  ])
34418
34719
  )
34419
34720
  )
@@ -34572,7 +34873,7 @@ function binaryWriteSignedBytes(input) {
34572
34873
  mimeType: normalizeBinaryMimeType(input.contentType),
34573
34874
  ...input.filename ? { filename: input.filename } : {},
34574
34875
  sizeBytes: input.bytes.length,
34575
- contentHash: (0, import_viem22.bytesToHex)((0, import_sha25.sha256)(input.bytes)),
34876
+ contentHash: (0, import_viem23.bytesToHex)((0, import_sha25.sha256)(input.bytes)),
34576
34877
  encoding: "base64",
34577
34878
  content: toBase64(input.bytes),
34578
34879
  ...metadata !== void 0 ? { metadata } : {}
@@ -34620,7 +34921,7 @@ function normalizeLineage(lineage, derivedScope) {
34620
34921
  for (const entry of lineage) {
34621
34922
  let id;
34622
34923
  if (isLineagePair(entry)) {
34623
- if (!(0, import_viem22.isAddress)(entry.ownerAddress, { strict: false })) {
34924
+ if (!(0, import_viem23.isAddress)(entry.ownerAddress, { strict: false })) {
34624
34925
  throw new WriteRequestError(
34625
34926
  "lineage source ownerAddress must be an EVM address",
34626
34927
  { ownerAddress: entry.ownerAddress }
@@ -34882,14 +35183,44 @@ function withGrantPermissions(grant) {
34882
35183
  }
34883
35184
  function createGatewayClient(baseUrl) {
34884
35185
  const base = baseUrl.replace(/\/+$/, "");
35186
+ function malformedBody(res) {
35187
+ return new Error(
35188
+ `Gateway error: ${res.status} malformed response body (expected a JSON envelope)`
35189
+ );
35190
+ }
35191
+ async function readEnvelope(res) {
35192
+ const envelope = await readJsonValue(res);
35193
+ if (!isPlainObject(envelope) || !("data" in envelope)) {
35194
+ throw malformedBody(res);
35195
+ }
35196
+ return envelope;
35197
+ }
34885
35198
  async function unwrapEnvelope(res) {
34886
- const envelope = await res.json();
34887
- return envelope.data;
35199
+ return (await readEnvelope(res)).data;
34888
35200
  }
34889
35201
  function getMutationId(body, key) {
35202
+ if (!isPlainObject(body)) return void 0;
34890
35203
  const value = body[key] ?? body["id"];
34891
35204
  return typeof value === "string" ? value : void 0;
34892
35205
  }
35206
+ async function readBody(res) {
35207
+ const raw = await readJsonObject(res);
35208
+ const data = raw["data"];
35209
+ if (isPlainObject(data) && "proof" in raw) {
35210
+ return data;
35211
+ }
35212
+ return raw;
35213
+ }
35214
+ function stringOrUndefined(value) {
35215
+ return typeof value === "string" ? value : void 0;
35216
+ }
35217
+ async function deletedError(res, details) {
35218
+ const body = await readBody(res);
35219
+ return new DataPointDeletedError(
35220
+ `Data point ${details.dataPointId ?? details.scope ?? ""} has been deleted`,
35221
+ { ...details, deletedAt: tombstoneDeletedAt(body) }
35222
+ );
35223
+ }
34893
35224
  return {
34894
35225
  async isRegisteredBuilder(address) {
34895
35226
  const builder = await this.getBuilder(address);
@@ -34946,13 +35277,29 @@ function createGatewayClient(baseUrl) {
34946
35277
  }
34947
35278
  return await res.json();
34948
35279
  },
34949
- async getDataPoint(dataPointId) {
34950
- const res = await fetch(`${base}/v1/data/${dataPointId}`);
35280
+ async getDataPoint(dataPointId, options) {
35281
+ const query = options?.includeDeleted ? "?includeDeleted=true" : "";
35282
+ const res = await fetch(`${base}/v1/data/${dataPointId}${query}`);
34951
35283
  if (res.status === 404) return null;
35284
+ if (res.status === 410) {
35285
+ throw await deletedError(res, { dataPointId });
35286
+ }
34952
35287
  if (!res.ok) {
34953
35288
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
34954
35289
  }
34955
- return unwrapEnvelope(res);
35290
+ const record = await unwrapEnvelope(res);
35291
+ if (!options?.includeDeleted && isDataPointTombstone(record)) {
35292
+ throw new DataPointDeletedError(
35293
+ `Data point ${dataPointId} has been deleted`,
35294
+ {
35295
+ dataPointId,
35296
+ scope: record.scope,
35297
+ ownerAddress: record.ownerAddress,
35298
+ deletedAt: tombstoneDeletedAt(record)
35299
+ }
35300
+ );
35301
+ }
35302
+ return record;
34956
35303
  },
34957
35304
  async listDataPointsByOwner(owner, cursor, options) {
34958
35305
  const params = new URLSearchParams({ user: owner });
@@ -34965,14 +35312,24 @@ function createGatewayClient(baseUrl) {
34965
35312
  if (options?.limit !== void 0) {
34966
35313
  params.set("limit", String(options.limit));
34967
35314
  }
35315
+ if (options?.includeDeleted) {
35316
+ params.set("includeDeleted", "true");
35317
+ }
34968
35318
  const res = await fetch(`${base}/v1/data?${params.toString()}`);
34969
35319
  if (!res.ok) {
34970
35320
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
34971
35321
  }
34972
- const envelope = await res.json();
34973
- const nextCursor = envelope.pagination?.hasMore === false ? null : envelope.pagination?.nextCursor ?? null;
35322
+ const envelope = await readEnvelope(res);
35323
+ if (!isPlainObject(envelope.data) || !Array.isArray(envelope.data["dataPoints"])) {
35324
+ throw malformedBody(res);
35325
+ }
35326
+ const rows = envelope.data["dataPoints"];
35327
+ const pagination = isPlainObject(envelope["pagination"]) ? envelope["pagination"] : void 0;
35328
+ const rawCursor = pagination?.["nextCursor"];
35329
+ const nextCursor = pagination?.["hasMore"] === false || typeof rawCursor !== "string" ? null : rawCursor;
35330
+ const dataPoints = options?.includeDeleted ? rows : rows.filter((row) => !isDataPointTombstone(row));
34974
35331
  return {
34975
- dataPoints: envelope.data.dataPoints,
35332
+ dataPoints,
34976
35333
  cursor: nextCursor
34977
35334
  };
34978
35335
  },
@@ -34999,7 +35356,7 @@ function createGatewayClient(baseUrl) {
34999
35356
  })
35000
35357
  });
35001
35358
  if (res.status === 409) {
35002
- const body2 = await res.json().catch(() => ({}));
35359
+ const body2 = await readJsonObject(res);
35003
35360
  return {
35004
35361
  serverId: getMutationId(body2, "serverId"),
35005
35362
  alreadyRegistered: true
@@ -35008,7 +35365,7 @@ function createGatewayClient(baseUrl) {
35008
35365
  if (!res.ok) {
35009
35366
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
35010
35367
  }
35011
- const body = await res.json().catch(() => ({}));
35368
+ const body = await readJsonObject(res);
35012
35369
  return {
35013
35370
  serverId: getMutationId(body, "serverId"),
35014
35371
  alreadyRegistered: false
@@ -35029,19 +35386,16 @@ function createGatewayClient(baseUrl) {
35029
35386
  })
35030
35387
  });
35031
35388
  if (res.status === 409) {
35032
- const body2 = await res.json().catch(() => ({}));
35389
+ const body2 = await readJsonObject(res);
35033
35390
  return {
35034
- builderId: getMutationId(
35035
- body2,
35036
- "builderId"
35037
- ),
35391
+ builderId: getMutationId(body2, "builderId"),
35038
35392
  alreadyRegistered: true
35039
35393
  };
35040
35394
  }
35041
35395
  if (!res.ok) {
35042
35396
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
35043
35397
  }
35044
- const body = await res.json().catch(() => ({}));
35398
+ const body = await readJsonObject(res);
35045
35399
  return {
35046
35400
  builderId: getMutationId(body, "builderId"),
35047
35401
  alreadyRegistered: false
@@ -35063,17 +35417,77 @@ function createGatewayClient(baseUrl) {
35063
35417
  })
35064
35418
  });
35065
35419
  if (!res.ok) {
35066
- const body2 = await res.json().catch(() => ({}));
35067
- const detail = body2.error ?? res.statusText;
35420
+ const body2 = await readJsonObject(res);
35421
+ const detail = stringOrUndefined(body2["error"]) ?? res.statusText;
35068
35422
  throw new Error(`Gateway error: ${res.status} ${detail}`);
35069
35423
  }
35070
- const body = await res.json().catch(() => ({}));
35424
+ const body = await readJsonObject(res);
35071
35425
  return {
35072
- dataPointId: getMutationId(
35073
- body,
35074
- "dataPointId"
35075
- ),
35076
- expectedVersion: body.expectedVersion
35426
+ dataPointId: getMutationId(body, "dataPointId"),
35427
+ expectedVersion: stringOrUndefined(body["expectedVersion"])
35428
+ };
35429
+ },
35430
+ async deleteDataPoint(params) {
35431
+ const dataPointId = deriveDataPointId(
35432
+ params.ownerAddress,
35433
+ params.scope
35434
+ );
35435
+ const details = {
35436
+ dataPointId,
35437
+ scope: params.scope,
35438
+ ownerAddress: params.ownerAddress
35439
+ };
35440
+ const res = await fetch(`${base}/v1/data/${dataPointId}`, {
35441
+ method: "DELETE",
35442
+ headers: {
35443
+ "Content-Type": "application/json",
35444
+ Authorization: `Web3Signed ${params.signature}`
35445
+ },
35446
+ body: JSON.stringify({
35447
+ ownerAddress: params.ownerAddress,
35448
+ scope: params.scope,
35449
+ expectedVersion: params.expectedVersion,
35450
+ signature: params.signature
35451
+ })
35452
+ });
35453
+ if (res.status === 404) {
35454
+ throw new DataPointNotFoundError(
35455
+ `Data point ${dataPointId} (scope '${params.scope}') is not registered`,
35456
+ details
35457
+ );
35458
+ }
35459
+ if (res.status === 409) {
35460
+ const body2 = await readBody(res);
35461
+ const currentExpectedVersion = stringOrUndefined(
35462
+ body2["currentExpectedVersion"]
35463
+ );
35464
+ const detail = stringOrUndefined(body2["error"]) ?? res.statusText;
35465
+ throw new DataPointVersionConflictError(
35466
+ `Gateway error: 409 ${detail}`,
35467
+ {
35468
+ ...details,
35469
+ expectedVersion: params.expectedVersion,
35470
+ currentExpectedVersion
35471
+ }
35472
+ );
35473
+ }
35474
+ if (res.status === 410) {
35475
+ throw await deletedError(res, details);
35476
+ }
35477
+ if (!res.ok) {
35478
+ const body2 = await readBody(res);
35479
+ const detail = stringOrUndefined(body2["error"]) ?? res.statusText;
35480
+ throw new Error(`Gateway error: ${res.status} ${detail}`);
35481
+ }
35482
+ const body = await readBody(res);
35483
+ return {
35484
+ dataPointId: getMutationId(body, "dataPointId") ?? dataPointId,
35485
+ ownerAddress: stringOrUndefined(body["ownerAddress"]),
35486
+ scope: stringOrUndefined(body["scope"]),
35487
+ dataHash: stringOrUndefined(body["dataHash"]),
35488
+ metadataHash: stringOrUndefined(body["metadataHash"]),
35489
+ expectedVersion: stringOrUndefined(body["expectedVersion"]),
35490
+ deletedAt: tombstoneDeletedAt(body)
35077
35491
  };
35078
35492
  },
35079
35493
  async createGrant(params) {
@@ -35092,18 +35506,14 @@ function createGatewayClient(baseUrl) {
35092
35506
  })
35093
35507
  });
35094
35508
  if (res.status === 409) {
35095
- const body2 = await res.json().catch(() => ({}));
35096
- return {
35097
- grantId: getMutationId(body2, "grantId")
35098
- };
35509
+ const body2 = await readJsonObject(res);
35510
+ return { grantId: getMutationId(body2, "grantId") };
35099
35511
  }
35100
35512
  if (!res.ok) {
35101
35513
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
35102
35514
  }
35103
- const body = await res.json();
35104
- return {
35105
- grantId: getMutationId(body, "grantId")
35106
- };
35515
+ const body = await readJsonObject(res);
35516
+ return { grantId: getMutationId(body, "grantId") };
35107
35517
  },
35108
35518
  async revokeGrant(params) {
35109
35519
  const res = await fetch(`${base}/v1/grants/${params.grantId}`, {
@@ -35842,7 +36252,10 @@ async function parsePSError(response) {
35842
36252
  DATA_ACCESS_OP_TYPE,
35843
36253
  DATA_REGISTRY_STATUS_ABI,
35844
36254
  DataFileEnvelopeSchema,
36255
+ DataPointDeletedError,
36256
+ DataPointNotFoundError,
35845
36257
  DataPointStatus,
36258
+ DataPointVersionConflictError,
35846
36259
  DropboxStorage,
35847
36260
  ECIESError,
35848
36261
  ESCROW_DEPOSIT_ABI,
@@ -35902,6 +36315,10 @@ async function parsePSError(response) {
35902
36315
  SignatureError,
35903
36316
  StorageError,
35904
36317
  StorageManager,
36318
+ TOMBSTONE_DATA_HASH,
36319
+ TOMBSTONE_DATA_HASH_PREIMAGE,
36320
+ TOMBSTONE_METADATA_HASH,
36321
+ TOMBSTONE_METADATA_HASH_PREIMAGE,
35905
36322
  TransactionPendingError,
35906
36323
  UserRejectedRequestError,
35907
36324
  VanaError,
@@ -35926,6 +36343,8 @@ async function parsePSError(response) {
35926
36343
  authorizeEscrowPayment,
35927
36344
  authorizeGrantPayment,
35928
36345
  binaryWriteSignedBytes,
36346
+ buildDataPointDeletionSignature,
36347
+ buildDataPointDeletionTypedData,
35929
36348
  buildDepositNativeRequest,
35930
36349
  buildDepositTokenRequest,
35931
36350
  buildEscrowPaymentHeader,
@@ -35943,6 +36362,7 @@ async function parsePSError(response) {
35943
36362
  clearContractCache,
35944
36363
  computeBodyHash,
35945
36364
  computePkceChallenge,
36365
+ computeTombstoneHash,
35946
36366
  contractCacheForTesting,
35947
36367
  createBrowserPlatformAdapter,
35948
36368
  createDataFileEnvelope,
@@ -35954,11 +36374,13 @@ async function parsePSError(response) {
35954
36374
  createPlatformAdapterFor,
35955
36375
  createPlatformAdapterSafe,
35956
36376
  createVanaStorageProvider,
36377
+ createViemDataPointDeletionSigner,
35957
36378
  createViemPersonalServerLiteOwnerBindingSigner,
35958
36379
  createViemPersonalServerRegistrationSigner,
35959
36380
  dataRegistryContractAddress,
35960
36381
  dataRegistryDomain,
35961
36382
  decryptWithPassword,
36383
+ deleteDataPoint,
35962
36384
  deriveDataPointId,
35963
36385
  deriveMasterKey,
35964
36386
  deriveScopeKey,
@@ -35994,10 +36416,12 @@ async function parsePSError(response) {
35994
36416
  grantRevocationDomain,
35995
36417
  hasAction,
35996
36418
  isDataPointId,
36419
+ isDataPointTombstone,
35997
36420
  isDataPortabilityGatewayConfig,
35998
36421
  isECIESEncrypted,
35999
36422
  isPlatformSupported,
36000
36423
  isRedactedLineageNode,
36424
+ isTombstoneHashes,
36001
36425
  mainnetServices,
36002
36426
  moksha,
36003
36427
  mokshaServices,
@@ -36032,6 +36456,7 @@ async function parsePSError(response) {
36032
36456
  signPersonalServerRegistrationWithAccount,
36033
36457
  toDirectFeeBreakdown,
36034
36458
  toDirectPaymentReceipt,
36459
+ tombstoneDeletedAt,
36035
36460
  tryGrantPermissions,
36036
36461
  vanaMainnet,
36037
36462
  verifyGrantRegistration,