@opendatalabs/vana-sdk 0.1.0-alpha.170e27e → 0.1.0-alpha.18ba63a

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.
@@ -428,8 +428,10 @@ var init_dataSchema_schema = __esm({
428
428
  // src/utils/schemaValidation.ts
429
429
  import Ajv from "ajv";
430
430
  import addFormats from "ajv-formats";
431
- function validateDataSchema(schema) {
432
- return schemaValidator.validateDataSchema(schema);
431
+ function validateDataSchemaAgainstMetaSchema(schema) {
432
+ const validator = schemaValidator;
433
+ validator.validateDataSchemaAgainstMetaSchema(schema);
434
+ return schema;
433
435
  }
434
436
  function validateDataAgainstSchema(data, schema) {
435
437
  return schemaValidator.validateDataAgainstSchema(data, schema);
@@ -462,9 +464,9 @@ var init_schemaValidation = __esm({
462
464
  this.dataSchemaValidator = this.ajv.compile(dataSchema_schema_default);
463
465
  }
464
466
  /**
465
- * Validates a data schema against the Vana meta-schema
467
+ * Validates a data schema definition against the Vana meta-schema
466
468
  *
467
- * @param schema - The data schema to validate
469
+ * @param schema - The data schema definition to validate
468
470
  * @throws SchemaValidationError if invalid
469
471
  * @example
470
472
  * ```typescript
@@ -483,10 +485,10 @@ var init_schemaValidation = __esm({
483
485
  * }
484
486
  * };
485
487
  *
486
- * validator.validateDataSchema(schema); // throws if invalid
488
+ * validator.validateDataSchemaAgainstMetaSchema(schema); // throws if invalid
487
489
  * ```
488
490
  */
489
- validateDataSchema(schema) {
491
+ validateDataSchemaAgainstMetaSchema(schema) {
490
492
  const isValid = this.dataSchemaValidator(schema);
491
493
  if (!isValid) {
492
494
  const errors = this.dataSchemaValidator.errors || [];
@@ -506,10 +508,10 @@ var init_schemaValidation = __esm({
506
508
  }
507
509
  }
508
510
  /**
509
- * Validates data against a JSON Schema from a schema
511
+ * Validates data against a JSON Schema
510
512
  *
511
513
  * @param data - The data to validate
512
- * @param schema - The schema containing the validation rules (DataSchema or Schema)
514
+ * @param schema - The schema containing the validation rules (must have been validated or fetched from chain)
513
515
  * @throws SchemaValidationError if invalid
514
516
  * @example
515
517
  * ```typescript
@@ -519,25 +521,22 @@ var init_schemaValidation = __esm({
519
521
  * const schema = await vana.schemas.get(1);
520
522
  * validator.validateDataAgainstSchema(userData, schema);
521
523
  *
522
- * // Also works with DataSchema object
523
- * const dataSchema: DataSchema = {
524
+ * // Also works with pre-validated DataSchema object
525
+ * const dataSchema = validator.validateDataSchemaAgainstMetaSchema({
524
526
  * name: "User Profile",
525
527
  * version: "1.0.0",
526
528
  * dialect: "json",
527
529
  * schema: { type: "object", properties: { name: { type: "string" } } }
528
- * };
530
+ * });
529
531
  * validator.validateDataAgainstSchema(userData, dataSchema);
530
532
  * ```
531
533
  */
532
534
  validateDataAgainstSchema(data, schema) {
533
- if (!("id" in schema)) {
534
- this.validateDataSchema(schema);
535
- }
536
535
  if (schema.dialect !== "json") {
537
- throw new SchemaValidationError(
538
- `Data validation only supported for JSON dialect, got: ${schema.dialect}`,
539
- []
536
+ console.warn(
537
+ `[SchemaValidator] Data validation skipped: dialect '${schema.dialect}' does not support data validation. Only JSON schemas can validate data structure.`
540
538
  );
539
+ return;
541
540
  }
542
541
  if (typeof schema.schema !== "object") {
543
542
  throw new SchemaValidationError(
@@ -603,9 +602,9 @@ var init_schemaValidation = __esm({
603
602
  }
604
603
  }
605
604
  /**
606
- * Fetches and validates a schema from a URL
605
+ * Fetches and validates a data schema from a URL
607
606
  *
608
- * @param url - The URL to fetch the schema from
607
+ * @param url - The URL to fetch the data schema from
609
608
  * @returns The validated data schema
610
609
  * @throws SchemaValidationError if invalid or fetch fails
611
610
  * @example
@@ -621,7 +620,7 @@ var init_schemaValidation = __esm({
621
620
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
622
621
  }
623
622
  const schema = await response.json();
624
- this.validateDataSchema(schema);
623
+ this.validateDataSchemaAgainstMetaSchema(schema);
625
624
  if (schema.dialect === "sqlite" && typeof schema.schema === "string") {
626
625
  this.validateSQLiteDDL(schema.schema, schema.dialectVersion);
627
626
  }
@@ -1270,19 +1269,19 @@ var init_eventMappings = __esm({
1270
1269
  // DataRegistry operations
1271
1270
  addFile: {
1272
1271
  contract: "DataRegistry",
1273
- event: "FileAdded"
1272
+ event: "FileAddedV2"
1274
1273
  },
1275
1274
  addFileWithPermissionsAndSchema: {
1276
1275
  contract: "DataRegistry",
1277
- event: "FileAdded"
1276
+ event: "FileAddedV2"
1278
1277
  },
1279
1278
  addFileWithSchema: {
1280
1279
  contract: "DataRegistry",
1281
- event: "FileAdded"
1280
+ event: "FileAddedV2"
1282
1281
  },
1283
1282
  addFileWithPermissions: {
1284
1283
  contract: "DataRegistry",
1285
- event: "FileAdded"
1284
+ event: "FileAddedV2"
1286
1285
  },
1287
1286
  addRefinement: {
1288
1287
  contract: "DataRegistry",
@@ -2769,6 +2768,37 @@ var init_DataRegistryImplementation = __esm({
2769
2768
  name: "FileAdded",
2770
2769
  type: "event"
2771
2770
  },
2771
+ {
2772
+ anonymous: false,
2773
+ inputs: [
2774
+ {
2775
+ indexed: true,
2776
+ internalType: "uint256",
2777
+ name: "fileId",
2778
+ type: "uint256"
2779
+ },
2780
+ {
2781
+ indexed: true,
2782
+ internalType: "address",
2783
+ name: "ownerAddress",
2784
+ type: "address"
2785
+ },
2786
+ {
2787
+ indexed: false,
2788
+ internalType: "string",
2789
+ name: "url",
2790
+ type: "string"
2791
+ },
2792
+ {
2793
+ indexed: false,
2794
+ internalType: "uint256",
2795
+ name: "schemaId",
2796
+ type: "uint256"
2797
+ }
2798
+ ],
2799
+ name: "FileAddedV2",
2800
+ type: "event"
2801
+ },
2772
2802
  {
2773
2803
  anonymous: false,
2774
2804
  inputs: [
@@ -3008,6 +3038,19 @@ var init_DataRegistryImplementation = __esm({
3008
3038
  name: "Upgraded",
3009
3039
  type: "event"
3010
3040
  },
3041
+ {
3042
+ inputs: [],
3043
+ name: "DATA_PORTABILITY_ROLE",
3044
+ outputs: [
3045
+ {
3046
+ internalType: "bytes32",
3047
+ name: "",
3048
+ type: "bytes32"
3049
+ }
3050
+ ],
3051
+ stateMutability: "view",
3052
+ type: "function"
3053
+ },
3011
3054
  {
3012
3055
  inputs: [],
3013
3056
  name: "DEFAULT_ADMIN_ROLE",
@@ -3102,6 +3145,41 @@ var init_DataRegistryImplementation = __esm({
3102
3145
  stateMutability: "nonpayable",
3103
3146
  type: "function"
3104
3147
  },
3148
+ {
3149
+ inputs: [
3150
+ {
3151
+ internalType: "uint256",
3152
+ name: "fileId",
3153
+ type: "uint256"
3154
+ },
3155
+ {
3156
+ components: [
3157
+ {
3158
+ internalType: "address",
3159
+ name: "account",
3160
+ type: "address"
3161
+ },
3162
+ {
3163
+ internalType: "string",
3164
+ name: "key",
3165
+ type: "string"
3166
+ }
3167
+ ],
3168
+ internalType: "struct IDataRegistry.Permission[]",
3169
+ name: "permissions",
3170
+ type: "tuple[]"
3171
+ },
3172
+ {
3173
+ internalType: "uint256",
3174
+ name: "schemaId",
3175
+ type: "uint256"
3176
+ }
3177
+ ],
3178
+ name: "addFilePermissionsAndSchema",
3179
+ outputs: [],
3180
+ stateMutability: "nonpayable",
3181
+ type: "function"
3182
+ },
3105
3183
  {
3106
3184
  inputs: [
3107
3185
  {
@@ -3316,6 +3394,19 @@ var init_DataRegistryImplementation = __esm({
3316
3394
  stateMutability: "view",
3317
3395
  type: "function"
3318
3396
  },
3397
+ {
3398
+ inputs: [],
3399
+ name: "emitLegacyEvents",
3400
+ outputs: [
3401
+ {
3402
+ internalType: "bool",
3403
+ name: "",
3404
+ type: "bool"
3405
+ }
3406
+ ],
3407
+ stateMutability: "view",
3408
+ type: "function"
3409
+ },
3319
3410
  {
3320
3411
  inputs: [
3321
3412
  {
@@ -3473,6 +3564,11 @@ var init_DataRegistryImplementation = __esm({
3473
3564
  name: "url",
3474
3565
  type: "string"
3475
3566
  },
3567
+ {
3568
+ internalType: "uint256",
3569
+ name: "schemaId",
3570
+ type: "uint256"
3571
+ },
3476
3572
  {
3477
3573
  internalType: "uint256",
3478
3574
  name: "addedAtBlock",
@@ -3756,6 +3852,19 @@ var init_DataRegistryImplementation = __esm({
3756
3852
  stateMutability: "nonpayable",
3757
3853
  type: "function"
3758
3854
  },
3855
+ {
3856
+ inputs: [
3857
+ {
3858
+ internalType: "bool",
3859
+ name: "newEmitLegacyEvents",
3860
+ type: "bool"
3861
+ }
3862
+ ],
3863
+ name: "updateEmitLegacyEvents",
3864
+ outputs: [],
3865
+ stateMutability: "nonpayable",
3866
+ type: "function"
3867
+ },
3759
3868
  {
3760
3869
  inputs: [
3761
3870
  {
@@ -36561,7 +36670,7 @@ var init_schemas = __esm({
36561
36670
  dialect,
36562
36671
  schema: schemaDefinition
36563
36672
  };
36564
- validateDataSchema(dataSchema);
36673
+ validateDataSchemaAgainstMetaSchema(dataSchema);
36565
36674
  if (!this.context.storageManager) {
36566
36675
  if (this.context.validateStorageRequired) {
36567
36676
  this.context.validateStorageRequired();
@@ -36670,7 +36779,7 @@ var init_schemas = __esm({
36670
36779
  `Invalid schema definition format for schema ${schemaId}`
36671
36780
  );
36672
36781
  }
36673
- validateDataSchema(definition);
36782
+ validateDataSchemaAgainstMetaSchema(definition);
36674
36783
  const dataSchema = definition;
36675
36784
  if (dataSchema.name !== metadata.name) {
36676
36785
  throw new Error(
@@ -37005,7 +37114,7 @@ var init_schemas = __esm({
37005
37114
  try {
37006
37115
  const definition = await fetchFromUrl(schema.definitionUrl);
37007
37116
  if (definition && typeof definition === "object") {
37008
- validateDataSchema(definition);
37117
+ validateDataSchemaAgainstMetaSchema(definition);
37009
37118
  const dataSchema = definition;
37010
37119
  schema.version = dataSchema.version;
37011
37120
  schema.description = dataSchema.description;
@@ -41878,6 +41987,29 @@ var DataController = class {
41878
41987
  const userFiles = Array.from(fileMap.values()).sort(
41879
41988
  (a, b) => Number((b.addedAtTimestamp || 0n) - (a.addedAtTimestamp || 0n))
41880
41989
  );
41990
+ if (userFiles.length > 0) {
41991
+ try {
41992
+ const fileIds = userFiles.map((f) => f.id);
41993
+ let proofMap;
41994
+ try {
41995
+ proofMap = await this._fetchProofsFromSubgraph(fileIds, endpoint);
41996
+ } catch (subgraphError) {
41997
+ console.debug(
41998
+ "Failed to fetch proofs from subgraph, trying chain:",
41999
+ subgraphError
42000
+ );
42001
+ proofMap = await this._fetchProofsFromChain(fileIds);
42002
+ }
42003
+ for (const file of userFiles) {
42004
+ const dlpIds = proofMap.get(file.id);
42005
+ if (dlpIds && dlpIds.length > 0) {
42006
+ file.dlpIds = dlpIds;
42007
+ }
42008
+ }
42009
+ } catch (error) {
42010
+ console.warn("Failed to fetch proof data for files:", error);
42011
+ }
42012
+ }
41881
42013
  return userFiles;
41882
42014
  } catch (error) {
41883
42015
  console.error("Failed to fetch user files from subgraph:", error);
@@ -41886,6 +42018,349 @@ var DataController = class {
41886
42018
  );
41887
42019
  }
41888
42020
  }
42021
+ /**
42022
+ * Fetches proof data for multiple files from the subgraph.
42023
+ *
42024
+ * @private
42025
+ * @param fileIds - Array of file IDs to fetch proofs for
42026
+ * @param subgraphUrl - The subgraph endpoint URL
42027
+ * @returns Map of file IDs to their associated DLP IDs
42028
+ */
42029
+ async _fetchProofsFromSubgraph(fileIds, subgraphUrl) {
42030
+ const query = `
42031
+ query GetFileProofs($fileIds: [BigInt!]!) {
42032
+ dataRegistryProofs(where: { fileId_in: $fileIds }) {
42033
+ fileId
42034
+ dlp {
42035
+ id
42036
+ }
42037
+ }
42038
+ }
42039
+ `;
42040
+ const response = await fetch(subgraphUrl, {
42041
+ method: "POST",
42042
+ headers: {
42043
+ "Content-Type": "application/json"
42044
+ },
42045
+ body: JSON.stringify({
42046
+ query,
42047
+ variables: {
42048
+ fileIds: fileIds.map((id) => id.toString())
42049
+ }
42050
+ })
42051
+ });
42052
+ if (!response.ok) {
42053
+ throw new Error(
42054
+ `Subgraph request failed: ${response.status} ${response.statusText}`
42055
+ );
42056
+ }
42057
+ const result = await response.json();
42058
+ if (result.errors) {
42059
+ throw new Error(
42060
+ `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
42061
+ );
42062
+ }
42063
+ const proofMap = /* @__PURE__ */ new Map();
42064
+ if (result.data?.dataRegistryProofs) {
42065
+ for (const proof of result.data.dataRegistryProofs) {
42066
+ if (proof.dlp?.id) {
42067
+ const fileId = parseInt(proof.fileId);
42068
+ const dlpId = parseInt(proof.dlp.id);
42069
+ if (!proofMap.has(fileId)) {
42070
+ proofMap.set(fileId, []);
42071
+ }
42072
+ const dlpIds = proofMap.get(fileId);
42073
+ if (!dlpIds.includes(dlpId)) {
42074
+ dlpIds.push(dlpId);
42075
+ }
42076
+ }
42077
+ }
42078
+ }
42079
+ return proofMap;
42080
+ }
42081
+ /**
42082
+ * Fetches proof data for multiple files from the blockchain.
42083
+ * Falls back to this when subgraph is unavailable.
42084
+ *
42085
+ * @private
42086
+ * @param fileIds - Array of file IDs to fetch proofs for
42087
+ * @returns Map of file IDs to their associated DLP IDs
42088
+ */
42089
+ async _fetchProofsFromChain(fileIds) {
42090
+ const chainId = this.context.walletClient.chain?.id;
42091
+ if (!chainId) {
42092
+ throw new Error("Chain ID not available");
42093
+ }
42094
+ const dataRegistryAddress = getContractAddress(chainId, "DataRegistry");
42095
+ const dataRegistryAbi = getAbi("DataRegistry");
42096
+ const proofMap = /* @__PURE__ */ new Map();
42097
+ for (const fileId of fileIds) {
42098
+ const dlpIds = [];
42099
+ let proofIndex = 0;
42100
+ let hasMoreProofs = true;
42101
+ while (hasMoreProofs) {
42102
+ try {
42103
+ const proof = await this.context.publicClient.readContract({
42104
+ address: dataRegistryAddress,
42105
+ abi: dataRegistryAbi,
42106
+ functionName: "fileProofs",
42107
+ args: [BigInt(fileId), BigInt(proofIndex)]
42108
+ });
42109
+ if (proof?.data?.dlpId) {
42110
+ const dlpId = Number(proof.data.dlpId);
42111
+ if (!dlpIds.includes(dlpId)) {
42112
+ dlpIds.push(dlpId);
42113
+ }
42114
+ }
42115
+ proofIndex++;
42116
+ } catch {
42117
+ hasMoreProofs = false;
42118
+ }
42119
+ }
42120
+ if (dlpIds.length > 0) {
42121
+ proofMap.set(fileId, dlpIds);
42122
+ }
42123
+ }
42124
+ return proofMap;
42125
+ }
42126
+ /**
42127
+ * Retrieves information about a specific Data Liquidity Pool (DLP).
42128
+ *
42129
+ * @remarks
42130
+ * DLPs are entities that process and verify data files in the Vana network.
42131
+ * This method fetches DLP metadata including name, status, and performance rating.
42132
+ * Uses subgraph first for efficiency, falls back to chain if unavailable.
42133
+ *
42134
+ * @param dlpId - The unique identifier of the DLP
42135
+ * @param options - Optional parameters
42136
+ * @param options.subgraphUrl - Custom subgraph URL to override default
42137
+ * @returns Promise resolving to DLP information
42138
+ * @throws {Error} When DLP cannot be found - "DLP not found: {dlpId}"
42139
+ * @throws {Error} When query fails - "Failed to fetch DLP: {error}"
42140
+ * @example
42141
+ * ```typescript
42142
+ * const dlp = await vana.data.getDLP(26);
42143
+ * console.log(`DLP ${dlp.name}: ${dlp.status}`);
42144
+ * ```
42145
+ */
42146
+ async getDLP(dlpId, options = {}) {
42147
+ const subgraphUrl = options.subgraphUrl || this.context.subgraphUrl;
42148
+ if (subgraphUrl) {
42149
+ try {
42150
+ const query = `
42151
+ query GetDLP($id: ID!) {
42152
+ dlp(id: $id) {
42153
+ id
42154
+ name
42155
+ metadata
42156
+ status
42157
+ address
42158
+ owner
42159
+ }
42160
+ }
42161
+ `;
42162
+ const response = await fetch(subgraphUrl, {
42163
+ method: "POST",
42164
+ headers: {
42165
+ "Content-Type": "application/json"
42166
+ },
42167
+ body: JSON.stringify({
42168
+ query,
42169
+ variables: {
42170
+ id: dlpId.toString()
42171
+ }
42172
+ })
42173
+ });
42174
+ if (!response.ok) {
42175
+ throw new Error(
42176
+ `Subgraph request failed: ${response.status} ${response.statusText}`
42177
+ );
42178
+ }
42179
+ const result = await response.json();
42180
+ if (result.errors) {
42181
+ throw new Error(
42182
+ `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
42183
+ );
42184
+ }
42185
+ if (!result.data?.dlp) {
42186
+ throw new Error(`DLP not found: ${dlpId}`);
42187
+ }
42188
+ return {
42189
+ id: parseInt(result.data.dlp.id),
42190
+ name: result.data.dlp.name || "",
42191
+ metadata: result.data.dlp.metadata,
42192
+ status: result.data.dlp.status ? parseInt(result.data.dlp.status) : void 0,
42193
+ address: result.data.dlp.address,
42194
+ owner: result.data.dlp.owner
42195
+ };
42196
+ } catch (error) {
42197
+ console.debug("Subgraph query failed, falling back to chain:", error);
42198
+ }
42199
+ }
42200
+ try {
42201
+ const chainId = this.context.walletClient.chain?.id;
42202
+ if (!chainId) {
42203
+ throw new Error("Chain ID not available");
42204
+ }
42205
+ const dlpRegistryAddress = getContractAddress(chainId, "DLPRegistry");
42206
+ const dlpRegistryAbi = getAbi("DLPRegistry");
42207
+ const dlpData = await this.context.publicClient.readContract({
42208
+ address: dlpRegistryAddress,
42209
+ abi: dlpRegistryAbi,
42210
+ functionName: "dlps",
42211
+ args: [BigInt(dlpId)]
42212
+ });
42213
+ if (!dlpData || !dlpData.name) {
42214
+ throw new Error(`DLP not found: ${dlpId}`);
42215
+ }
42216
+ return {
42217
+ id: dlpId,
42218
+ name: dlpData.name,
42219
+ metadata: dlpData.metadata,
42220
+ status: dlpData.status,
42221
+ address: dlpData.dlpAddress,
42222
+ owner: dlpData.ownerAddress
42223
+ };
42224
+ } catch (error) {
42225
+ throw new Error(
42226
+ `Failed to fetch DLP: ${error instanceof Error ? error.message : "Unknown error"}`
42227
+ );
42228
+ }
42229
+ }
42230
+ /**
42231
+ * Lists all Data Liquidity Pools (DLPs) with optional pagination.
42232
+ *
42233
+ * @remarks
42234
+ * Fetches a paginated list of all DLPs registered in the network.
42235
+ * Uses subgraph for efficient querying with fallback to chain multicall.
42236
+ *
42237
+ * @param options - Optional parameters for pagination and filtering
42238
+ * @param options.limit - Maximum number of DLPs to return (default: 100)
42239
+ * @param options.offset - Number of DLPs to skip (default: 0)
42240
+ * @param options.subgraphUrl - Custom subgraph URL to override default
42241
+ * @returns Promise resolving to array of DLP information
42242
+ * @throws {Error} When query fails - "Failed to list DLPs: {error}"
42243
+ * @example
42244
+ * ```typescript
42245
+ * // Get first 10 DLPs
42246
+ * const dlps = await vana.data.listDLPs({ limit: 10 });
42247
+ * dlps.forEach(dlp => console.log(`${dlp.id}: ${dlp.name}`));
42248
+ *
42249
+ * // Get next page
42250
+ * const nextPage = await vana.data.listDLPs({ limit: 10, offset: 10 });
42251
+ * ```
42252
+ */
42253
+ async listDLPs(options = {}) {
42254
+ const { limit = 100, offset = 0 } = options;
42255
+ const subgraphUrl = options.subgraphUrl || this.context.subgraphUrl;
42256
+ if (subgraphUrl) {
42257
+ try {
42258
+ const query = `
42259
+ query ListDLPs($first: Int!, $skip: Int!) {
42260
+ dlps(first: $first, skip: $skip, orderBy: id) {
42261
+ id
42262
+ name
42263
+ metadata
42264
+ status
42265
+ address
42266
+ owner
42267
+ }
42268
+ }
42269
+ `;
42270
+ const response = await fetch(subgraphUrl, {
42271
+ method: "POST",
42272
+ headers: {
42273
+ "Content-Type": "application/json"
42274
+ },
42275
+ body: JSON.stringify({
42276
+ query,
42277
+ variables: {
42278
+ first: limit,
42279
+ skip: offset
42280
+ }
42281
+ })
42282
+ });
42283
+ if (!response.ok) {
42284
+ throw new Error(
42285
+ `Subgraph request failed: ${response.status} ${response.statusText}`
42286
+ );
42287
+ }
42288
+ const result = await response.json();
42289
+ if (result.errors) {
42290
+ throw new Error(
42291
+ `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
42292
+ );
42293
+ }
42294
+ const dlps = result.data?.dlps || [];
42295
+ return dlps.map((dlp) => ({
42296
+ id: parseInt(dlp.id),
42297
+ name: dlp.name || "",
42298
+ metadata: dlp.metadata,
42299
+ status: dlp.status ? parseInt(dlp.status) : void 0,
42300
+ address: dlp.address,
42301
+ owner: dlp.owner
42302
+ }));
42303
+ } catch (error) {
42304
+ console.debug("Subgraph query failed, falling back to chain:", error);
42305
+ }
42306
+ }
42307
+ try {
42308
+ const chainId = this.context.walletClient.chain?.id;
42309
+ if (!chainId) {
42310
+ throw new Error("Chain ID not available");
42311
+ }
42312
+ const dlpRegistryAddress = getContractAddress(chainId, "DLPRegistry");
42313
+ const dlpRegistryAbi = getAbi("DLPRegistry");
42314
+ const dlpCount = await this.context.publicClient.readContract({
42315
+ address: dlpRegistryAddress,
42316
+ abi: dlpRegistryAbi,
42317
+ functionName: "dlpsCount",
42318
+ args: []
42319
+ });
42320
+ const totalCount = Number(dlpCount);
42321
+ const start = offset;
42322
+ const end = Math.min(start + limit, totalCount);
42323
+ if (end <= start) {
42324
+ return [];
42325
+ }
42326
+ const calls = [];
42327
+ for (let i = start + 1; i <= end; i++) {
42328
+ calls.push({
42329
+ address: dlpRegistryAddress,
42330
+ abi: dlpRegistryAbi,
42331
+ functionName: "dlps",
42332
+ args: [BigInt(i)]
42333
+ });
42334
+ }
42335
+ const results = await gasAwareMulticall(this.context.publicClient, {
42336
+ contracts: calls,
42337
+ allowFailure: true,
42338
+ batchSize: 50
42339
+ });
42340
+ const dlps = [];
42341
+ for (let i = 0; i < results.length; i++) {
42342
+ const result = results[i];
42343
+ if (result.status === "success" && result.result) {
42344
+ const dlpData = result.result;
42345
+ if (dlpData.name) {
42346
+ dlps.push({
42347
+ id: start + i + 1,
42348
+ name: dlpData.name,
42349
+ metadata: dlpData.metadata,
42350
+ status: dlpData.status,
42351
+ address: dlpData.dlpAddress,
42352
+ owner: dlpData.ownerAddress
42353
+ });
42354
+ }
42355
+ }
42356
+ }
42357
+ return dlps;
42358
+ } catch (error) {
42359
+ throw new Error(
42360
+ `Failed to list DLPs: ${error instanceof Error ? error.message : "Unknown error"}`
42361
+ );
42362
+ }
42363
+ }
41889
42364
  /**
41890
42365
  * Retrieves a list of permissions granted by a user.
41891
42366
  *
@@ -43016,19 +43491,31 @@ var DataController = class {
43016
43491
  return await this.submitFilePermission(fileId, account, publicKey);
43017
43492
  }
43018
43493
  /**
43019
- * Submits a file permission transaction and returns the transaction hash immediately.
43494
+ * Submits a file permission transaction to the blockchain.
43020
43495
  *
43021
- * This is the lower-level method that provides maximum control over transaction timing.
43496
+ * @remarks
43497
+ * This method supports gasless transactions via relayer callbacks when configured.
43498
+ * It encrypts the user's encryption key with the recipient's public key before submission.
43022
43499
  * Use this when you want to handle transaction confirmation and event parsing separately.
43023
43500
  *
43024
- * @param fileId - The ID of the file to add permissions for
43025
- * @param account - The address of the account to grant permission to
43026
- * @param publicKey - The public key to encrypt the user's encryption key with
43027
- * @returns Promise resolving to the transaction hash
43501
+ * @param fileId - The ID of the file to grant permission for
43502
+ * @param account - The recipient's wallet address that will access the file
43503
+ * @param publicKey - The recipient's public key for encryption.
43504
+ * Obtain via `vana.server.getIdentity(account).public_key`
43505
+ * @returns Promise resolving to TransactionHandle for tracking the transaction
43506
+ * @throws {Error} When chain ID is not available
43507
+ * @throws {Error} When encryption key generation fails
43508
+ * @throws {Error} When public key encryption fails
43509
+ *
43028
43510
  * @example
43029
43511
  * ```typescript
43030
- * const txHash = await vana.data.submitFilePermission(fileId, account, publicKey);
43031
- * console.log(`Transaction submitted: ${txHash}`);
43512
+ * const tx = await vana.data.submitFilePermission(
43513
+ * fileId,
43514
+ * "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
43515
+ * recipientPublicKey
43516
+ * );
43517
+ * const result = await tx.waitForEvents();
43518
+ * console.log(`Permission granted with ID: ${result.permissionId}`);
43032
43519
  * ```
43033
43520
  */
43034
43521
  async submitFilePermission(fileId, account, publicKey) {
@@ -43312,10 +43799,10 @@ var DataController = class {
43312
43799
  );
43313
43800
  }
43314
43801
  /**
43315
- * Validates a data schema against the Vana meta-schema.
43802
+ * Validates a data schema definition against the Vana meta-schema.
43316
43803
  *
43317
- * @param schema - The data schema to validate
43318
- * @returns Assertion that schema is valid (throws if invalid)
43804
+ * @param schema - The data schema definition to validate
43805
+ * @returns The validated DataSchema
43319
43806
  * @throws SchemaValidationError if invalid
43320
43807
  * @example
43321
43808
  * ```typescript
@@ -43332,11 +43819,11 @@ var DataController = class {
43332
43819
  * }
43333
43820
  * };
43334
43821
  *
43335
- * vana.data.validateDataSchema(schema);
43822
+ * const validatedSchema = vana.data.validateDataSchemaAgainstMetaSchema(schema);
43336
43823
  * ```
43337
43824
  */
43338
- validateDataSchema(schema) {
43339
- return validateDataSchema(schema);
43825
+ validateDataSchemaAgainstMetaSchema(schema) {
43826
+ return validateDataSchemaAgainstMetaSchema(schema);
43340
43827
  }
43341
43828
  /**
43342
43829
  * Validates data against a JSON Schema from a data schema.
@@ -43369,9 +43856,9 @@ var DataController = class {
43369
43856
  return validateDataAgainstSchema(data, schema);
43370
43857
  }
43371
43858
  /**
43372
- * Fetches and validates a schema from a URL, then returns the parsed data schema.
43859
+ * Fetches and validates a data schema from a URL, then returns the parsed data schema.
43373
43860
  *
43374
- * @param url - The URL to fetch the schema from
43861
+ * @param url - The URL to fetch the data schema from
43375
43862
  * @returns The validated data schema
43376
43863
  * @throws SchemaValidationError if invalid or fetch fails
43377
43864
  * @example
@@ -43396,6 +43883,73 @@ init_schemas();
43396
43883
 
43397
43884
  // src/controllers/server.ts
43398
43885
  init_errors();
43886
+
43887
+ // src/utils/operationHandle.ts
43888
+ init_errors();
43889
+ var OperationHandle = class {
43890
+ constructor(controller, id) {
43891
+ this.controller = controller;
43892
+ this.id = id;
43893
+ __publicField(this, "_resultPromise");
43894
+ }
43895
+ /**
43896
+ * Waits for the operation to complete and returns the result.
43897
+ *
43898
+ * @remarks
43899
+ * Results are memoized - multiple calls return the same promise.
43900
+ * The method polls the server at regular intervals until the operation
43901
+ * succeeds, fails, or times out. Returns the raw string result from the
43902
+ * server - callers are responsible for parsing if needed.
43903
+ *
43904
+ * @param options - Optional polling configuration
43905
+ * @returns The operation result as a string when completed
43906
+ * @throws {PersonalServerError} When the operation fails or times out
43907
+ * @example
43908
+ * ```typescript
43909
+ * const result = await handle.waitForResult({
43910
+ * timeout: 60000,
43911
+ * pollingInterval: 500
43912
+ * });
43913
+ * // If expecting JSON, parse it:
43914
+ * const data = JSON.parse(result);
43915
+ * ```
43916
+ */
43917
+ async waitForResult(options) {
43918
+ if (!this._resultPromise) {
43919
+ this._resultPromise = this.pollForCompletion(options);
43920
+ }
43921
+ return this._resultPromise;
43922
+ }
43923
+ async pollForCompletion(options) {
43924
+ const startTime = Date.now();
43925
+ const timeout = options?.timeout ?? 3e4;
43926
+ const interval = options?.pollingInterval ?? 500;
43927
+ while (true) {
43928
+ const result = await this.controller.getOperation(
43929
+ this.id
43930
+ );
43931
+ if (result.status === "succeeded") {
43932
+ if (result.result) {
43933
+ return result.result;
43934
+ }
43935
+ throw new PersonalServerError(
43936
+ "Operation succeeded but returned no result"
43937
+ );
43938
+ }
43939
+ if (result.status === "failed") {
43940
+ throw new PersonalServerError(
43941
+ `Operation ${result.status}: ${result.result || "Unknown error"}`
43942
+ );
43943
+ }
43944
+ if (Date.now() - startTime > timeout) {
43945
+ throw new PersonalServerError(`Operation timed out after ${timeout}ms`);
43946
+ }
43947
+ await new Promise((resolve) => setTimeout(resolve, interval));
43948
+ }
43949
+ }
43950
+ };
43951
+
43952
+ // src/controllers/server.ts
43399
43953
  var ServerController = class {
43400
43954
  constructor(context) {
43401
43955
  this.context = context;
@@ -43477,26 +44031,29 @@ var ServerController = class {
43477
44031
  }
43478
44032
  }
43479
44033
  /**
43480
- * Creates an operation via the personal server API.
44034
+ * Creates a server operation and returns a handle for lifecycle management.
43481
44035
  *
43482
44036
  * @remarks
43483
- * This method submits a computation request to the personal server API.
43484
- * The response includes the operation ID.
43485
- * @param params - The request parameters object
44037
+ * This method submits a computation request to the personal server and returns
44038
+ * an OperationHandle that provides Promise-based methods for waiting on results.
44039
+ * The handle pattern matches TransactionHandle for consistency across async operations.
44040
+ *
44041
+ * @param params - The operation request parameters
43486
44042
  * @param params.permissionId - The permission ID authorizing this operation.
43487
- * Obtain from granted permissions via `vana.permissions.getUserPermissionGrantsOnChain()`.
43488
- * @returns A Promise that resolves to an operation response with status and control URLs
43489
- * @throws {PersonalServerError} When server request fails or parameters are invalid.
43490
- * Verify permissionId exists and is active for the target server.
43491
- * @throws {NetworkError} When personal server API communication fails.
43492
- * Check server URL configuration and network connectivity.
44043
+ * Obtain via `vana.permissions.getUserPermissionGrantsOnChain()`.
44044
+ * @returns An OperationHandle providing access to the operation ID and result methods
44045
+ * @throws {PersonalServerError} When the server request fails or parameters are invalid
44046
+ * @throws {NetworkError} When personal server API communication fails
43493
44047
  * @example
43494
44048
  * ```typescript
43495
- * const response = await vana.server.createOperation({
43496
- * permissionId: 123,
44049
+ * const operation = await vana.server.createOperation({
44050
+ * permissionId: 123
43497
44051
  * });
43498
- *
43499
- * console.log(`Operation created: ${response.id}`);
44052
+ * console.log(`Operation ID: ${operation.id}`);
44053
+ *
44054
+ * // Wait for completion
44055
+ * const result = await operation.waitForResult();
44056
+ * console.log("Result:", result);
43500
44057
  * ```
43501
44058
  */
43502
44059
  async createOperation(params) {
@@ -43512,7 +44069,7 @@ var ServerController = class {
43512
44069
  };
43513
44070
  console.debug("\u{1F50D} Debug - createOperation requestBody", requestBody);
43514
44071
  const response = await this.makeRequest(requestBody);
43515
- return response;
44072
+ return new OperationHandle(this, response.id);
43516
44073
  } catch (error) {
43517
44074
  if (error instanceof Error) {
43518
44075
  if (error instanceof NetworkError || error instanceof SerializationError || error instanceof SignatureError || error instanceof PersonalServerError) {
@@ -43529,30 +44086,20 @@ var ServerController = class {
43529
44086
  }
43530
44087
  }
43531
44088
  /**
43532
- * Polls the status of a computation request for updates and results.
44089
+ * Retrieves the current status and result of a server operation.
43533
44090
  *
43534
44091
  * @remarks
43535
- * This method checks the current status of a computation request by querying
43536
- * the personal server API using the provided operation ID. It returns the current
43537
- * status, any available output, and error information. The method can be
43538
- * called periodically until the operation completes or fails.
43539
- *
43540
- * Common status values include: `starting`, `processing`, `succeeded`, `failed`, `canceled`.
43541
- * @param operationId - The operation ID returned from the initial request submission
43542
- * @returns A Promise that resolves to the current operation response with status and results
43543
- * @throws {NetworkError} When the polling request fails or returns invalid data
44092
+ * Common status values: `starting`, `running`, `succeeded`, `failed`, `canceled`.
44093
+ * When status is `succeeded`, the result field contains the operation output.
44094
+ *
44095
+ * @param operationId - The ID of the operation to query
44096
+ * @returns The operation response containing status, result, and metadata
44097
+ * @throws {NetworkError} When the API request fails or returns invalid data
43544
44098
  * @example
43545
44099
  * ```typescript
43546
- * // Poll until completion
43547
- * let result = await vana.server.getOperation(response.id);
43548
- *
43549
- * while (result.status === "processing") {
43550
- * await new Promise(resolve => setTimeout(resolve, 1000));
43551
- * result = await vana.server.getOperation(response.id);
43552
- * }
43553
- *
43554
- * if (result.status === "succeeded") {
43555
- * console.log("Computation completed:", result.output);
44100
+ * const status = await vana.server.getOperation(operationId);
44101
+ * if (status.status === 'succeeded') {
44102
+ * console.log('Result:', JSON.parse(status.result));
43556
44103
  * }
43557
44104
  * ```
43558
44105
  */
@@ -46905,7 +47452,7 @@ export {
46905
47452
  storeGrantFile,
46906
47453
  summarizeGrant,
46907
47454
  validateDataAgainstSchema,
46908
- validateDataSchema,
47455
+ validateDataSchemaAgainstMetaSchema,
46909
47456
  validateGrant,
46910
47457
  validateGrantExpiry,
46911
47458
  validateGrantFile,