@opendatalabs/vana-sdk 0.1.0-alpha.e64ec83 → 0.1.0-alpha.f05a34e

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 (40) hide show
  1. package/README.md +189 -425
  2. package/dist/chains.browser.cjs +4 -1
  3. package/dist/chains.browser.cjs.map +1 -1
  4. package/dist/chains.browser.d.cts +2 -1
  5. package/dist/chains.browser.d.ts +2 -1
  6. package/dist/chains.browser.js +3 -1
  7. package/dist/chains.browser.js.map +1 -1
  8. package/dist/chains.cjs +4 -1
  9. package/dist/chains.cjs.map +1 -1
  10. package/dist/chains.d.cts +1 -1
  11. package/dist/chains.d.ts +1 -1
  12. package/dist/chains.js +3 -1
  13. package/dist/chains.js.map +1 -1
  14. package/dist/chains.node.cjs +4 -1
  15. package/dist/chains.node.cjs.map +1 -1
  16. package/dist/chains.node.d.cts +1 -1
  17. package/dist/chains.node.d.ts +1 -1
  18. package/dist/chains.node.js +3 -1
  19. package/dist/chains.node.js.map +1 -1
  20. package/dist/index.browser.d.ts +3883 -2669
  21. package/dist/index.browser.js +1412 -1094
  22. package/dist/index.browser.js.map +1 -1
  23. package/dist/index.d.cts +1 -31277
  24. package/dist/index.node.cjs +1448 -1131
  25. package/dist/index.node.cjs.map +1 -1
  26. package/dist/index.node.d.cts +3885 -2671
  27. package/dist/index.node.d.ts +3885 -2671
  28. package/dist/index.node.js +1427 -1110
  29. package/dist/index.node.js.map +1 -1
  30. package/dist/platform.browser.js +32 -181
  31. package/dist/platform.browser.js.map +1 -1
  32. package/dist/platform.cjs +47 -197
  33. package/dist/platform.cjs.map +1 -1
  34. package/dist/platform.js +47 -197
  35. package/dist/platform.js.map +1 -1
  36. package/dist/platform.node.cjs +47 -197
  37. package/dist/platform.node.cjs.map +1 -1
  38. package/dist/platform.node.js +47 -197
  39. package/dist/platform.node.js.map +1 -1
  40. package/package.json +24 -18
@@ -29,11 +29,6 @@ function parseEncryptedDataBuffer(encryptedBuffer) {
29
29
  mac: encryptedBuffer.slice(-32)
30
30
  };
31
31
  }
32
- function uint8ArrayToHex(array) {
33
- return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join(
34
- ""
35
- );
36
- }
37
32
  var init_crypto_utils = __esm({
38
33
  "src/platform/shared/crypto-utils.ts"() {
39
34
  "use strict";
@@ -84,147 +79,59 @@ var init_error_utils = __esm({
84
79
 
85
80
  // src/platform/browser.ts
86
81
  import * as openpgp from "openpgp";
87
- function hexToUint8Array(hex) {
88
- const result = new Uint8Array(hex.length / 2);
89
- for (let i = 0; i < hex.length; i += 2) {
90
- result[i / 2] = parseInt(hex.substr(i, 2), 16);
91
- }
92
- return result;
93
- }
94
- var BrowserECDH, BrowserCryptoAdapter, BrowserPGPAdapter, BrowserHttpAdapter, BrowserPlatformAdapter, browserPlatformAdapter;
82
+ var BrowserCryptoAdapter, BrowserPGPAdapter, BrowserHttpAdapter, BrowserPlatformAdapter, browserPlatformAdapter;
95
83
  var init_browser = __esm({
96
84
  "src/platform/browser.ts"() {
97
85
  "use strict";
98
86
  init_crypto_utils();
99
87
  init_pgp_utils();
100
88
  init_error_utils();
101
- BrowserECDH = class {
102
- async generateKeyPair() {
103
- const keyPair = await crypto.subtle.generateKey(
104
- {
105
- name: "ECDH",
106
- namedCurve: "P-256"
107
- },
108
- true,
109
- ["deriveKey", "deriveBits"]
110
- );
111
- return keyPair;
112
- }
113
- async encrypt(publicKeyHex, message) {
114
- const ephemeralKeyPair = await this.generateKeyPair();
115
- const publicKeyData = hexToUint8Array(publicKeyHex);
116
- const importedPublicKey = await crypto.subtle.importKey(
117
- "raw",
118
- publicKeyData,
119
- { name: "ECDH", namedCurve: "P-256" },
120
- false,
121
- []
122
- );
123
- const sharedKey = await crypto.subtle.deriveKey(
124
- { name: "ECDH", public: importedPublicKey },
125
- ephemeralKeyPair.privateKey,
126
- { name: "AES-GCM", length: 256 },
127
- false,
128
- ["encrypt"]
129
- );
130
- const iv = crypto.getRandomValues(new Uint8Array(12));
131
- const encoder = new TextEncoder();
132
- const data = encoder.encode(message);
133
- const encrypted = await crypto.subtle.encrypt(
134
- { name: "AES-GCM", iv },
135
- sharedKey,
136
- data
137
- );
138
- const ephemeralPublicKeyData = await crypto.subtle.exportKey(
139
- "raw",
140
- ephemeralKeyPair.publicKey
141
- );
142
- return JSON.stringify({
143
- encrypted: Array.from(new Uint8Array(encrypted)),
144
- iv: Array.from(iv),
145
- ephemeralPublicKey: Array.from(new Uint8Array(ephemeralPublicKeyData)),
146
- publicKey: publicKeyHex
147
- });
148
- }
149
- async decrypt(privateKeyHex, encryptedData) {
150
- try {
151
- const data = JSON.parse(encryptedData);
152
- if (!data.encrypted || !data.iv || !data.ephemeralPublicKey) {
153
- throw new Error("Invalid encrypted data format");
154
- }
155
- const privateKeyData = hexToUint8Array(privateKeyHex);
156
- const importedPrivateKey = await crypto.subtle.importKey(
157
- "pkcs8",
158
- privateKeyData,
159
- { name: "ECDH", namedCurve: "P-256" },
160
- false,
161
- ["deriveKey"]
162
- );
163
- const ephemeralPublicKey = await crypto.subtle.importKey(
164
- "raw",
165
- new Uint8Array(data.ephemeralPublicKey),
166
- { name: "ECDH", namedCurve: "P-256" },
167
- false,
168
- []
169
- );
170
- const sharedKey = await crypto.subtle.deriveKey(
171
- { name: "ECDH", public: ephemeralPublicKey },
172
- importedPrivateKey,
173
- { name: "AES-GCM", length: 256 },
174
- false,
175
- ["decrypt"]
176
- );
177
- const decrypted = await crypto.subtle.decrypt(
178
- { name: "AES-GCM", iv: new Uint8Array(data.iv) },
179
- sharedKey,
180
- new Uint8Array(data.encrypted)
181
- );
182
- return new TextDecoder().decode(decrypted);
183
- } catch (error) {
184
- throw new Error(
185
- `Decryption failed: ${error instanceof Error ? error.message : "Unknown error"}`
186
- );
187
- }
188
- }
189
- };
190
89
  BrowserCryptoAdapter = class {
191
90
  async encryptWithPublicKey(data, publicKeyHex) {
192
91
  try {
193
- const ecdh = new BrowserECDH();
194
- return await ecdh.encrypt(publicKeyHex, data);
92
+ const eccrypto = await import("eccrypto-js");
93
+ const publicKeyBuffer = Buffer.from(publicKeyHex, "hex");
94
+ const encrypted = await eccrypto.encrypt(
95
+ publicKeyBuffer,
96
+ Buffer.from(data, "utf8")
97
+ );
98
+ const result = Buffer.concat([
99
+ encrypted.iv,
100
+ encrypted.ephemPublicKey,
101
+ encrypted.ciphertext,
102
+ encrypted.mac
103
+ ]);
104
+ return result.toString("hex");
195
105
  } catch (error) {
196
106
  throw new Error(`Encryption failed: ${error}`);
197
107
  }
198
108
  }
199
109
  async decryptWithPrivateKey(encryptedData, privateKeyHex) {
200
110
  try {
201
- const ecdh = new BrowserECDH();
202
- return await ecdh.decrypt(privateKeyHex, encryptedData);
111
+ const eccrypto = await import("eccrypto-js");
112
+ const privateKeyBuffer = processWalletPrivateKey(privateKeyHex);
113
+ const encryptedBuffer = Buffer.from(encryptedData, "hex");
114
+ const { iv, ephemPublicKey, ciphertext, mac } = parseEncryptedDataBuffer(encryptedBuffer);
115
+ const encryptedObj = { iv, ephemPublicKey, ciphertext, mac };
116
+ const decryptedBuffer = await eccrypto.decrypt(
117
+ privateKeyBuffer,
118
+ encryptedObj
119
+ );
120
+ return decryptedBuffer.toString("utf8");
203
121
  } catch (error) {
204
122
  throw new Error(`Decryption failed: ${error}`);
205
123
  }
206
124
  }
207
125
  async generateKeyPair() {
208
126
  try {
209
- const keyPair = await crypto.subtle.generateKey(
210
- {
211
- name: "ECDH",
212
- namedCurve: "P-256"
213
- },
214
- true,
215
- ["deriveKey", "deriveBits"]
216
- );
217
- const publicKeyBuffer = await crypto.subtle.exportKey(
218
- "raw",
219
- keyPair.publicKey
220
- );
221
- const privateKeyBuffer = await crypto.subtle.exportKey(
222
- "pkcs8",
223
- keyPair.privateKey
224
- );
127
+ const eccrypto = await import("eccrypto-js");
128
+ const privateKeyBytes = new Uint8Array(32);
129
+ crypto.getRandomValues(privateKeyBytes);
130
+ const privateKey = Buffer.from(privateKeyBytes);
131
+ const publicKey = eccrypto.getPublicCompressed(privateKey);
225
132
  return {
226
- publicKey: uint8ArrayToHex(new Uint8Array(publicKeyBuffer)),
227
- privateKey: uint8ArrayToHex(new Uint8Array(privateKeyBuffer))
133
+ privateKey: privateKey.toString("hex"),
134
+ publicKey: publicKey.toString("hex")
228
135
  };
229
136
  } catch (error) {
230
137
  throw wrapCryptoError("key generation", error);
@@ -234,65 +141,9 @@ var init_browser = __esm({
234
141
  try {
235
142
  const eccrypto = await import("eccrypto-js");
236
143
  const uncompressedKey = processWalletPublicKey(publicKey);
237
- const iv = Buffer.from([
238
- 1,
239
- 2,
240
- 3,
241
- 4,
242
- 5,
243
- 6,
244
- 7,
245
- 8,
246
- 9,
247
- 10,
248
- 11,
249
- 12,
250
- 13,
251
- 14,
252
- 15,
253
- 16
254
- ]);
255
- const ephemeralKey = Buffer.from([
256
- 17,
257
- 34,
258
- 51,
259
- 68,
260
- 85,
261
- 102,
262
- 119,
263
- 136,
264
- 153,
265
- 170,
266
- 187,
267
- 204,
268
- 221,
269
- 238,
270
- 255,
271
- 0,
272
- 16,
273
- 32,
274
- 48,
275
- 64,
276
- 80,
277
- 96,
278
- 112,
279
- 128,
280
- 144,
281
- 160,
282
- 176,
283
- 192,
284
- 208,
285
- 224,
286
- 240,
287
- 0
288
- ]);
289
144
  const encryptedBuffer = await eccrypto.encrypt(
290
145
  uncompressedKey,
291
- Buffer.from(data),
292
- {
293
- iv,
294
- ephemPrivateKey: ephemeralKey
295
- }
146
+ Buffer.from(data)
296
147
  );
297
148
  const result = Buffer.concat([
298
149
  encryptedBuffer.iv,
@@ -539,6 +390,9 @@ function isWalletConfig(config) {
539
390
  function isChainConfig(config) {
540
391
  return "chainId" in config && !("walletClient" in config);
541
392
  }
393
+ function hasStorageConfig(config) {
394
+ return config.storage?.providers !== void 0 && Object.keys(config.storage.providers).length > 0;
395
+ }
542
396
 
543
397
  // src/types/chains.ts
544
398
  function isVanaChainId(chainId) {
@@ -562,8 +416,8 @@ var StorageError = class extends Error {
562
416
  import Ajv from "ajv";
563
417
  import addFormats from "ajv-formats";
564
418
 
565
- // src/schemas/dataContract.schema.json
566
- var dataContract_schema_default = {
419
+ // src/schemas/dataSchema.schema.json
420
+ var dataSchema_schema_default = {
567
421
  $id: "https://vana.org/data-schema.json",
568
422
  $schema: "http://json-schema.org/draft-07/schema#",
569
423
  title: "Schema",
@@ -635,7 +489,7 @@ var SchemaValidator = class {
635
489
  strict: false
636
490
  });
637
491
  addFormats(this.ajv);
638
- this.dataSchemaValidator = this.ajv.compile(dataContract_schema_default);
492
+ this.dataSchemaValidator = this.ajv.compile(dataSchema_schema_default);
639
493
  }
640
494
  /**
641
495
  * Validates a data schema against the Vana meta-schema
@@ -834,55 +688,6 @@ function isReplicateAPIResponse(value) {
834
688
  obj.status
835
689
  );
836
690
  }
837
- function isIdentityServerOutput(value) {
838
- console.debug("\u{1F50D} Type Guard: Checking value:", value);
839
- console.debug("\u{1F50D} Type Guard: Value type:", typeof value);
840
- if (typeof value !== "object" || value === null) {
841
- console.debug("\u{1F50D} Type Guard: Failed - not object or null");
842
- return false;
843
- }
844
- const obj = value;
845
- console.debug("\u{1F50D} Type Guard: Object keys:", Object.keys(obj));
846
- console.debug(
847
- "\u{1F50D} Type Guard: user_address:",
848
- obj.user_address,
849
- typeof obj.user_address
850
- );
851
- if (typeof obj.user_address !== "string") {
852
- console.debug("\u{1F50D} Type Guard: Failed - user_address not string");
853
- return false;
854
- }
855
- console.debug(
856
- "\u{1F50D} Type Guard: personal_server:",
857
- obj.personal_server,
858
- typeof obj.personal_server
859
- );
860
- if (typeof obj.personal_server !== "object" || obj.personal_server === null) {
861
- console.debug("\u{1F50D} Type Guard: Failed - personal_server not object or null");
862
- return false;
863
- }
864
- const personalServer = obj.personal_server;
865
- console.debug(
866
- "\u{1F50D} Type Guard: Personal server keys:",
867
- Object.keys(personalServer)
868
- );
869
- console.debug("\u{1F50D} Type Guard: address:", personalServer.address);
870
- console.debug("\u{1F50D} Type Guard: public_key:", personalServer.public_key);
871
- const hasAddress = "address" in personalServer;
872
- const hasPublicKey = "public_key" in personalServer;
873
- console.debug(
874
- "\u{1F50D} Type Guard: Has address:",
875
- hasAddress,
876
- "Has public_key:",
877
- hasPublicKey
878
- );
879
- return hasAddress && hasPublicKey;
880
- }
881
- function isPersonalServerOutput(value) {
882
- if (typeof value !== "object" || value === null) return false;
883
- const obj = value;
884
- return "user_address" in obj && "identity" in obj && typeof obj.user_address === "string" && typeof obj.identity === "object";
885
- }
886
691
  function isAPIResponse(value) {
887
692
  if (typeof value !== "object" || value === null) return false;
888
693
  const obj = value;
@@ -7913,6 +7718,12 @@ var DataRefinerRegistryABI = [
7913
7718
  name: "schemaId",
7914
7719
  type: "uint256"
7915
7720
  },
7721
+ {
7722
+ indexed: false,
7723
+ internalType: "string",
7724
+ name: "schemaDefinitionUrl",
7725
+ type: "string"
7726
+ },
7916
7727
  {
7917
7728
  indexed: false,
7918
7729
  internalType: "string",
@@ -8016,7 +7827,7 @@ var DataRefinerRegistryABI = [
8016
7827
  {
8017
7828
  indexed: false,
8018
7829
  internalType: "string",
8019
- name: "typ",
7830
+ name: "dialect",
8020
7831
  type: "string"
8021
7832
  },
8022
7833
  {
@@ -8112,6 +7923,40 @@ var DataRefinerRegistryABI = [
8112
7923
  stateMutability: "nonpayable",
8113
7924
  type: "function"
8114
7925
  },
7926
+ {
7927
+ inputs: [
7928
+ {
7929
+ internalType: "uint256",
7930
+ name: "dlpId",
7931
+ type: "uint256"
7932
+ },
7933
+ {
7934
+ internalType: "string",
7935
+ name: "name",
7936
+ type: "string"
7937
+ },
7938
+ {
7939
+ internalType: "string",
7940
+ name: "schemaDefinitionUrl",
7941
+ type: "string"
7942
+ },
7943
+ {
7944
+ internalType: "string",
7945
+ name: "refinementInstructionUrl",
7946
+ type: "string"
7947
+ }
7948
+ ],
7949
+ name: "addRefiner",
7950
+ outputs: [
7951
+ {
7952
+ internalType: "uint256",
7953
+ name: "",
7954
+ type: "uint256"
7955
+ }
7956
+ ],
7957
+ stateMutability: "nonpayable",
7958
+ type: "function"
7959
+ },
8115
7960
  {
8116
7961
  inputs: [
8117
7962
  {
@@ -8135,7 +7980,7 @@ var DataRefinerRegistryABI = [
8135
7980
  type: "string"
8136
7981
  }
8137
7982
  ],
8138
- name: "addRefiner",
7983
+ name: "addRefinerWithSchemaId",
8139
7984
  outputs: [
8140
7985
  {
8141
7986
  internalType: "uint256",
@@ -8155,7 +8000,7 @@ var DataRefinerRegistryABI = [
8155
8000
  },
8156
8001
  {
8157
8002
  internalType: "string",
8158
- name: "typ",
8003
+ name: "dialect",
8159
8004
  type: "string"
8160
8005
  },
8161
8006
  {
@@ -8518,7 +8363,7 @@ var DataRefinerRegistryABI = [
8518
8363
  },
8519
8364
  {
8520
8365
  internalType: "string",
8521
- name: "typ",
8366
+ name: "dialect",
8522
8367
  type: "string"
8523
8368
  },
8524
8369
  {
@@ -33435,7 +33280,7 @@ function getAbi(contract) {
33435
33280
  import { keccak256, toHex } from "viem";
33436
33281
  function createGrantFile(params) {
33437
33282
  const grantFile = {
33438
- grantee: params.to,
33283
+ grantee: params.grantee,
33439
33284
  operation: params.operation,
33440
33285
  parameters: params.parameters
33441
33286
  };
@@ -33855,7 +33700,7 @@ var PermissionsController = class {
33855
33700
  * @example
33856
33701
  * ```typescript
33857
33702
  * const txHash = await vana.permissions.grant({
33858
- * to: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
33703
+ * grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
33859
33704
  * operation: "llm_inference",
33860
33705
  * parameters: {
33861
33706
  * model: "gpt-4",
@@ -33884,7 +33729,7 @@ var PermissionsController = class {
33884
33729
  * @example
33885
33730
  * ```typescript
33886
33731
  * const { preview, confirm } = await vana.permissions.prepareGrant({
33887
- * to: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
33732
+ * grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
33888
33733
  * operation: "llm_inference",
33889
33734
  * files: [1, 2, 3],
33890
33735
  * parameters: { model: "gpt-4", prompt: "Analyze my social media data" }
@@ -33933,9 +33778,13 @@ var PermissionsController = class {
33933
33778
  console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
33934
33779
  if (!grantUrl) {
33935
33780
  if (!this.context.relayerCallbacks?.storeGrantFile && !this.context.storageManager) {
33936
- throw new Error(
33937
- "No storage available. Provide a grantUrl, configure relayerCallbacks.storeGrantFile, or storageManager."
33938
- );
33781
+ if (this.context.validateStorageRequired) {
33782
+ this.context.validateStorageRequired();
33783
+ } else {
33784
+ throw new Error(
33785
+ "No storage available. Provide a grantUrl, configure relayerCallbacks.storeGrantFile, or storageManager."
33786
+ );
33787
+ }
33939
33788
  }
33940
33789
  if (this.context.relayerCallbacks?.storeGrantFile) {
33941
33790
  grantUrl = await this.context.relayerCallbacks.storeGrantFile(grantFile);
@@ -33959,7 +33808,7 @@ var PermissionsController = class {
33959
33808
  grantUrl
33960
33809
  );
33961
33810
  const typedData = await this.composePermissionGrantMessage({
33962
- to: params.to,
33811
+ grantee: params.grantee,
33963
33812
  operation: params.operation,
33964
33813
  // Placeholder - real data is in IPFS
33965
33814
  files: params.files,
@@ -34006,7 +33855,7 @@ var PermissionsController = class {
34006
33855
  * @example
34007
33856
  * ```typescript
34008
33857
  * const { typedData, signature } = await vana.permissions.createAndSign({
34009
- * to: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
33858
+ * grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
34010
33859
  * operation: "data_analysis",
34011
33860
  * parameters: { analysisType: "sentiment" },
34012
33861
  * });
@@ -34022,9 +33871,13 @@ var PermissionsController = class {
34022
33871
  console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
34023
33872
  if (!grantUrl) {
34024
33873
  if (!this.context.relayerCallbacks?.storeGrantFile && !this.context.storageManager) {
34025
- throw new Error(
34026
- "No storage available. Provide a grantUrl, configure relayerCallbacks.storeGrantFile, or storageManager."
34027
- );
33874
+ if (this.context.validateStorageRequired) {
33875
+ this.context.validateStorageRequired();
33876
+ } else {
33877
+ throw new Error(
33878
+ "No storage available. Provide a grantUrl, configure relayerCallbacks.storeGrantFile, or storageManager."
33879
+ );
33880
+ }
34028
33881
  }
34029
33882
  if (this.context.relayerCallbacks?.storeGrantFile) {
34030
33883
  grantUrl = await this.context.relayerCallbacks.storeGrantFile(grantFile);
@@ -34048,7 +33901,7 @@ var PermissionsController = class {
34048
33901
  grantUrl
34049
33902
  );
34050
33903
  const typedData = await this.composePermissionGrantMessage({
34051
- to: params.to,
33904
+ grantee: params.grantee,
34052
33905
  operation: params.operation,
34053
33906
  // Placeholder - real data is in IPFS
34054
33907
  files: params.files,
@@ -34399,7 +34252,7 @@ var PermissionsController = class {
34399
34252
  * Composes the EIP-712 typed data for PermissionGrant (new simplified format).
34400
34253
  *
34401
34254
  * @param params - The parameters for composing the permission grant message
34402
- * @param params.to - The recipient address for the permission grant
34255
+ * @param params.grantee - The recipient address for the permission grant
34403
34256
  * @param params.operation - The type of operation being granted permission for
34404
34257
  * @param params.files - Array of file IDs that the permission applies to
34405
34258
  * @param params.grantUrl - URL where the grant details are stored
@@ -34492,36 +34345,45 @@ var PermissionsController = class {
34492
34345
  return addresses[0];
34493
34346
  }
34494
34347
  /**
34495
- * Retrieves all permissions granted by the current user using subgraph queries.
34348
+ * Gets on-chain permission grant data without expensive off-chain resolution.
34496
34349
  *
34497
34350
  * @remarks
34498
- * This method queries the Vana subgraph to find permissions directly granted by the user
34499
- * using the Permission entity. It efficiently handles millions of permissions by leveraging
34500
- * indexed subgraph data instead of scanning contract logs. The method fetches complete
34501
- * grant files from IPFS to provide detailed permission information including operation
34502
- * parameters and grantee details.
34503
- * @param params - Optional query parameters
34504
- * @param params.limit - Maximum number of permissions to return (default: 50)
34505
- * @param params.subgraphUrl - Optional subgraph URL to override the default endpoint
34506
- * @returns A Promise that resolves to an array of `GrantedPermission` objects
34507
- * @throws {BlockchainError} When subgraph is unavailable or returns invalid data
34351
+ * This method provides a fast, performance-focused way to retrieve permission grants
34352
+ * by querying only the subgraph without making expensive IPFS or individual contract calls.
34353
+ * It eliminates the N+1 query problem of the legacy `getUserPermissions()` method.
34354
+ *
34355
+ * The returned data contains all on-chain information but does NOT include resolved
34356
+ * operation details, parameters, or file IDs. Use `retrieveGrantFile()` separately
34357
+ * for specific grants when detailed data is needed.
34358
+ *
34359
+ * **Performance**: Completes in ~100-500ms regardless of permission count.
34360
+ * **Reliability**: Single point of failure (subgraph) with clear RPC fallback path.
34361
+ *
34362
+ * @param options - Options for retrieving permissions (limit, subgraph URL)
34363
+ * @returns A Promise that resolves to an array of `OnChainPermissionGrant` objects
34364
+ * @throws {BlockchainError} When subgraph query fails
34365
+ * @throws {NetworkError} When network requests fail
34508
34366
  * @example
34509
34367
  * ```typescript
34510
- * // Get all permissions granted by current user
34511
- * const permissions = await vana.permissions.getUserPermissions();
34368
+ * // Fast: Get all on-chain permission data
34369
+ * const grants = await vana.permissions.getUserPermissionGrantsOnChain({ limit: 20 });
34512
34370
  *
34513
- * permissions.forEach(permission => {
34514
- * console.log(`Granted ${permission.operation} to ${permission.grantee}`);
34371
+ * // Display in UI immediately
34372
+ * grants.forEach(grant => {
34373
+ * console.log(`Permission ${grant.id}: ${grant.grantUrl}`);
34515
34374
  * });
34516
34375
  *
34517
- * // Limit results
34518
- * const recent = await vana.permissions.getUserPermissions({ limit: 10 });
34376
+ * // Lazy load detailed data for specific permission when user clicks
34377
+ * const grantFile = await retrieveGrantFile(grants[0].grantUrl);
34378
+ * console.log(`Operation: ${grantFile.operation}`);
34379
+ * console.log(`Parameters:`, grantFile.parameters);
34519
34380
  * ```
34520
34381
  */
34521
- async getUserPermissions(params) {
34382
+ async getUserPermissionGrantsOnChain(options = {}) {
34383
+ const { limit = 50, subgraphUrl } = options;
34522
34384
  try {
34523
34385
  const userAddress = await this.getUserAddress();
34524
- const graphqlEndpoint = params?.subgraphUrl || this.context.subgraphUrl;
34386
+ const graphqlEndpoint = subgraphUrl || this.context.subgraphUrl;
34525
34387
  if (!graphqlEndpoint) {
34526
34388
  throw new BlockchainError(
34527
34389
  "subgraphUrl is required. Please provide a valid subgraph endpoint or configure it in Vana constructor."
@@ -34543,16 +34405,6 @@ var PermissionsController = class {
34543
34405
  }
34544
34406
  }
34545
34407
  `;
34546
- console.info("Query:", query);
34547
- console.info(
34548
- "Body:",
34549
- JSON.stringify({
34550
- query,
34551
- variables: {
34552
- userId: userAddress.toLowerCase()
34553
- }
34554
- })
34555
- );
34556
34408
  const response = await fetch(graphqlEndpoint, {
34557
34409
  method: "POST",
34558
34410
  headers: {
@@ -34571,7 +34423,6 @@ var PermissionsController = class {
34571
34423
  );
34572
34424
  }
34573
34425
  const result = await response.json();
34574
- console.info("Result:", result);
34575
34426
  if (result.errors) {
34576
34427
  throw new BlockchainError(
34577
34428
  `Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
@@ -34579,64 +34430,32 @@ var PermissionsController = class {
34579
34430
  }
34580
34431
  const userData = result.data?.user;
34581
34432
  if (!userData || !userData.permissions?.length) {
34582
- console.warn("No permissions found for user:", userAddress);
34583
34433
  return [];
34584
34434
  }
34585
- const userPermissions = [];
34586
- const limit = params?.limit || 50;
34587
- const permissionsToProcess = userData.permissions.slice(0, limit);
34588
- for (const permission of permissionsToProcess) {
34589
- try {
34590
- let operation;
34591
- let files = [];
34592
- let parameters;
34593
- let granteeAddress;
34594
- try {
34595
- const grantFile = await retrieveGrantFile(permission.grant);
34596
- operation = grantFile.operation;
34597
- parameters = grantFile.parameters;
34598
- granteeAddress = grantFile.grantee;
34599
- } catch {
34600
- }
34601
- try {
34602
- const fileIds = await this.getPermissionFileIds(
34603
- BigInt(permission.id)
34604
- );
34605
- files = fileIds.map((id) => Number(id));
34606
- } catch {
34607
- }
34608
- userPermissions.push({
34609
- id: BigInt(permission.id),
34610
- files,
34611
- operation: operation || "",
34612
- parameters: parameters || {},
34613
- grant: permission.grant,
34614
- grantor: userAddress.toLowerCase(),
34615
- // Current user is the grantor
34616
- grantee: granteeAddress || userAddress,
34617
- // Application that received permission
34618
- active: true,
34619
- // Default to active if not specified
34620
- grantedAt: Number(permission.addedAtBlock),
34621
- nonce: Number(permission.nonce)
34622
- });
34623
- } catch (error) {
34624
- console.error(
34625
- "SDK Error: Failed to process permission:",
34626
- permission.id,
34627
- error
34628
- );
34629
- }
34630
- }
34631
- return userPermissions.sort((a, b) => {
34435
+ const onChainGrants = userData.permissions.slice(0, limit).map((permission) => ({
34436
+ id: BigInt(permission.id),
34437
+ grantUrl: permission.grant,
34438
+ grantSignature: permission.grantSignature,
34439
+ grantHash: permission.grantHash,
34440
+ nonce: BigInt(permission.nonce),
34441
+ addedAtBlock: BigInt(permission.addedAtBlock),
34442
+ addedAtTimestamp: BigInt(permission.addedAtTimestamp || "0"),
34443
+ transactionHash: permission.transactionHash || "",
34444
+ grantor: userAddress,
34445
+ active: true
34446
+ // TODO: Add revocation status from subgraph when available
34447
+ }));
34448
+ return onChainGrants.sort((a, b) => {
34632
34449
  if (a.id < b.id) return 1;
34633
34450
  if (a.id > b.id) return -1;
34634
34451
  return 0;
34635
34452
  });
34636
34453
  } catch (error) {
34637
- console.error("Failed to fetch user permissions:", error);
34454
+ if (error instanceof BlockchainError || error instanceof NetworkError) {
34455
+ throw error;
34456
+ }
34638
34457
  throw new BlockchainError(
34639
- `Failed to fetch user permissions: ${error instanceof Error ? error.message : "Unknown error"}`
34458
+ `Failed to fetch user permission grants: ${error instanceof Error ? error.message : "Unknown error"}`
34640
34459
  );
34641
34460
  }
34642
34461
  }
@@ -35334,590 +35153,6 @@ var PermissionsController = class {
35334
35153
  // src/controllers/data.ts
35335
35154
  import { getContract, decodeEventLog } from "viem";
35336
35155
 
35337
- // src/controllers/server.ts
35338
- var ServerController = class {
35339
- constructor(context) {
35340
- this.context = context;
35341
- __publicField(this, "REPLICATE_API_URL", "https://api.replicate.com/v1/predictions");
35342
- __publicField(this, "PERSONAL_SERVER_VERSION", "vana-com/personal-server:6dae0fead4017557a2e6bd020643359ac1769228a9cfe3bd2365eeeb9711610e");
35343
- __publicField(this, "IDENTITY_SERVER_VERSION", "vana-com/identity-server:8e357fbeb87c0558b545809cabd0ef2f311082d8ce1f12b93cb8ad2f38cfbfd2");
35344
- }
35345
- /**
35346
- * Posts a computation request to a user's personal server.
35347
- *
35348
- * @remarks
35349
- * This method submits a computation request to the specified user's personal server
35350
- * via the Replicate API. It creates a signed request with the user address and
35351
- * permission ID, then submits it for processing. The response includes URLs for
35352
- * polling results and canceling the computation if needed.
35353
- *
35354
- * The method requires a valid Replicate API token and uses the application's
35355
- * wallet client for request signing to ensure authenticity.
35356
- * @param params - The request parameters object
35357
- * @param params.permissionId - The permission ID authorizing this computation
35358
- * @returns A Promise that resolves to a prediction response with status and control URLs
35359
- * @throws {PersonalServerError} When server request fails or parameters are invalid
35360
- * @throws {SignatureError} When request signing fails
35361
- * @throws {NetworkError} When Replicate API communication fails
35362
- * @example
35363
- * ```typescript
35364
- * const response = await vana.server.postRequest({
35365
- * permissionId: 123,
35366
- * });
35367
- *
35368
- * console.log(`Request submitted: ${response.id}`);
35369
- * console.log(`Poll for results: ${response.urls.get}`);
35370
- * ```
35371
- */
35372
- async postRequest(params) {
35373
- try {
35374
- this.validatePostRequestParams(params);
35375
- const requestJson = this.createRequestJson(params);
35376
- const signature = await this.createSignature(requestJson);
35377
- const replicateInput = {
35378
- replicate_api_token: this.getReplicateApiToken(),
35379
- signature,
35380
- request_json: requestJson
35381
- };
35382
- console.debug("\u{1F50D} Debug - replicateInput", replicateInput);
35383
- const response = await this.makeReplicateRequest(replicateInput);
35384
- return response;
35385
- } catch (error) {
35386
- if (error instanceof Error) {
35387
- if (error instanceof NetworkError || error instanceof SerializationError || error instanceof SignatureError || error instanceof PersonalServerError) {
35388
- throw error;
35389
- }
35390
- throw new PersonalServerError(
35391
- `Personal server request failed: ${error.message}`,
35392
- error
35393
- );
35394
- }
35395
- throw new PersonalServerError(
35396
- "Personal server request failed with unknown error"
35397
- );
35398
- }
35399
- }
35400
- /**
35401
- * Initializes the personal server and fetches user identity.
35402
- *
35403
- * @param params - The request parameters containing user address
35404
- * @returns Promise resolving to the user's identity information
35405
- */
35406
- async initPersonalServer(params) {
35407
- try {
35408
- this.validateInitPersonalServerParams(params);
35409
- const response = await this.makePersonalServerRequest(params);
35410
- const result = await this.pollPersonalServerResult(response);
35411
- return result;
35412
- } catch (error) {
35413
- if (error instanceof Error) {
35414
- if (error instanceof NetworkError || error instanceof SerializationError || error instanceof PersonalServerError) {
35415
- throw error;
35416
- }
35417
- throw new PersonalServerError(
35418
- `Personal server initialization failed: ${error.message}`,
35419
- error
35420
- );
35421
- }
35422
- throw new PersonalServerError(
35423
- "Personal server initialization failed with unknown error"
35424
- );
35425
- }
35426
- }
35427
- /**
35428
- * Retrieves the public key for a user's personal server via the Identity Server.
35429
- *
35430
- * @remarks
35431
- * This method uses the Identity Server to deterministically derive the personal server's
35432
- * public key from the user's EVM address. This enables anyone to encrypt data for a
35433
- * specific user's server without requiring that server to be online. The Identity Server
35434
- * provides a reliable way to obtain encryption keys for secure data sharing across the
35435
- * Vana network.
35436
- *
35437
- * The derived public key is deterministic and consistent, allowing for predictable
35438
- * encryption workflows in decentralized applications.
35439
- * @param userAddress - The user's EVM address to derive the server public key for
35440
- * @returns A Promise that resolves to the server's public key as a hex string
35441
- * @throws {PersonalServerError} When user address is invalid or server lookup fails
35442
- * @throws {NetworkError} When Identity Server API request fails
35443
- * @example
35444
- * ```typescript
35445
- * // Get public key for encrypting data to a user's server
35446
- * const publicKey = await vana.server.getTrustedServerPublicKey(
35447
- * "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36"
35448
- * );
35449
- *
35450
- * // Use the public key for encryption
35451
- * const encryptedData = await encryptForServer(data, publicKey);
35452
- * ```
35453
- */
35454
- async getTrustedServerPublicKey(userAddress) {
35455
- try {
35456
- if (!userAddress || typeof userAddress !== "string") {
35457
- throw new PersonalServerError(
35458
- "User address is required and must be a valid string"
35459
- );
35460
- }
35461
- if (!userAddress.startsWith("0x") || userAddress.length !== 42) {
35462
- throw new PersonalServerError(
35463
- "User address must be a valid EVM address"
35464
- );
35465
- }
35466
- const requestBody = {
35467
- version: this.IDENTITY_SERVER_VERSION,
35468
- input: {
35469
- user_address: userAddress
35470
- }
35471
- };
35472
- console.debug("Identity Server Request for Public Key:", {
35473
- url: this.REPLICATE_API_URL,
35474
- method: "POST",
35475
- body: requestBody
35476
- });
35477
- const response = await fetch(this.REPLICATE_API_URL, {
35478
- method: "POST",
35479
- headers: {
35480
- Authorization: `Token ${this.getReplicateApiToken()}`,
35481
- "Content-Type": "application/json"
35482
- },
35483
- body: JSON.stringify(requestBody)
35484
- });
35485
- if (!response.ok) {
35486
- const errorText = await response.text();
35487
- console.debug("Identity Server Error Response:", {
35488
- status: response.status,
35489
- statusText: response.statusText,
35490
- error: errorText
35491
- });
35492
- throw new NetworkError(
35493
- `Identity Server API request failed: ${response.status} ${response.statusText} - ${errorText}`
35494
- );
35495
- }
35496
- const data = await response.json();
35497
- console.debug("Identity Server Success Response:", data);
35498
- const result = await this.pollIdentityServerResult({
35499
- id: data.id,
35500
- status: data.status,
35501
- urls: {
35502
- get: data.urls?.get || "",
35503
- cancel: data.urls?.cancel || ""
35504
- },
35505
- input: data.input,
35506
- output: data.output,
35507
- error: data.error
35508
- });
35509
- return result;
35510
- } catch (error) {
35511
- if (error instanceof Error) {
35512
- if (error instanceof NetworkError || error instanceof PersonalServerError) {
35513
- throw error;
35514
- }
35515
- throw new PersonalServerError(
35516
- `Failed to get trusted server public key: ${error.message}`,
35517
- error
35518
- );
35519
- }
35520
- throw new PersonalServerError(
35521
- "Failed to get trusted server public key with unknown error"
35522
- );
35523
- }
35524
- }
35525
- /**
35526
- * Polls the status of a computation request for updates and results.
35527
- *
35528
- * @remarks
35529
- * This method checks the current status of a computation request by querying
35530
- * the Replicate API using the provided polling URL. It returns the current
35531
- * status, any available output, and error information. The method should be
35532
- * called periodically until the computation completes or fails.
35533
- *
35534
- * Common status values include: `starting`, `processing`, `succeeded`, `failed`, `canceled`.
35535
- * @param getUrl - The polling URL returned from the initial request submission
35536
- * @returns A Promise that resolves to the current prediction response with status and results
35537
- * @throws {NetworkError} When the polling request fails or returns invalid data
35538
- * @example
35539
- * ```typescript
35540
- * // Poll until completion
35541
- * let result = await vana.server.pollStatus(response.urls.get);
35542
- *
35543
- * while (result.status === "processing") {
35544
- * await new Promise(resolve => setTimeout(resolve, 1000));
35545
- * result = await vana.server.pollStatus(response.urls.get);
35546
- * }
35547
- *
35548
- * if (result.status === "succeeded") {
35549
- * console.log("Computation completed:", result.output);
35550
- * }
35551
- * ```
35552
- */
35553
- async pollStatus(getUrl) {
35554
- try {
35555
- console.debug("Polling Replicate Status:", getUrl);
35556
- const response = await fetch(getUrl, {
35557
- method: "GET",
35558
- headers: {
35559
- Authorization: `Token ${this.getReplicateApiToken()}`,
35560
- "Content-Type": "application/json"
35561
- }
35562
- });
35563
- if (!response.ok) {
35564
- const errorText = await response.text();
35565
- console.debug("Polling Error Response:", {
35566
- status: response.status,
35567
- statusText: response.statusText,
35568
- error: errorText
35569
- });
35570
- throw new NetworkError(
35571
- `Status polling failed: ${response.status} ${response.statusText} - ${errorText}`
35572
- );
35573
- }
35574
- const data = await response.json();
35575
- console.debug("Polling Success Response:", data);
35576
- return {
35577
- id: data.id,
35578
- status: data.status,
35579
- urls: {
35580
- get: data.urls?.get || getUrl,
35581
- cancel: data.urls?.cancel || ""
35582
- },
35583
- input: data.input,
35584
- output: data.output,
35585
- error: data.error
35586
- };
35587
- } catch (error) {
35588
- if (error instanceof NetworkError) {
35589
- throw error;
35590
- }
35591
- throw new NetworkError(
35592
- `Failed to poll status: ${error instanceof Error ? error.message : "Unknown error"}`
35593
- );
35594
- }
35595
- }
35596
- /**
35597
- * Validates the post request parameters.
35598
- *
35599
- * @param params - The post request parameters to validate
35600
- */
35601
- validatePostRequestParams(params) {
35602
- if (typeof params.permissionId !== "number" || params.permissionId <= 0) {
35603
- throw new PersonalServerError(
35604
- "Permission ID is required and must be a valid positive number"
35605
- );
35606
- }
35607
- }
35608
- /**
35609
- * Validates the init personal server parameters.
35610
- *
35611
- * @param params - The initialization parameters to validate
35612
- */
35613
- validateInitPersonalServerParams(params) {
35614
- if (!params.userAddress || typeof params.userAddress !== "string") {
35615
- throw new PersonalServerError(
35616
- "User address is required and must be a valid string"
35617
- );
35618
- }
35619
- if (!params.userAddress.startsWith("0x") || params.userAddress.length !== 42) {
35620
- throw new PersonalServerError(
35621
- "User address must be a valid Vana address"
35622
- );
35623
- }
35624
- }
35625
- /**
35626
- * Creates the request JSON string for the personal server.
35627
- *
35628
- * @param params - The post request parameters to serialize
35629
- * @returns JSON string representation of the request data
35630
- */
35631
- createRequestJson(params) {
35632
- try {
35633
- const requestData = {
35634
- permission_id: params.permissionId
35635
- };
35636
- return JSON.stringify(requestData);
35637
- } catch (error) {
35638
- throw new SerializationError(
35639
- `Failed to create request JSON: ${error instanceof Error ? error.message : "Unknown error"}`
35640
- );
35641
- }
35642
- }
35643
- /**
35644
- * Creates a signature for the request JSON.
35645
- *
35646
- * @param requestJson - The JSON string to sign
35647
- * @returns Promise resolving to the cryptographic signature
35648
- */
35649
- async createSignature(requestJson) {
35650
- try {
35651
- console.debug("\u{1F50D} Debug - createSignature", requestJson);
35652
- const client = this.context.applicationClient || this.context.walletClient;
35653
- const account = client.account;
35654
- if (!account) {
35655
- throw new SignatureError("No account available for signing");
35656
- }
35657
- if (account.type !== "local") {
35658
- throw new SignatureError(
35659
- "Only local accounts are supported for signing"
35660
- );
35661
- }
35662
- const signature = await account.signMessage({
35663
- message: requestJson
35664
- });
35665
- return signature;
35666
- } catch (error) {
35667
- if (error instanceof Error && error.message.includes("User rejected")) {
35668
- throw new SignatureError("User rejected the signature request");
35669
- }
35670
- throw new SignatureError(
35671
- `Failed to create signature: ${error instanceof Error ? error.message : "Unknown error"}`
35672
- );
35673
- }
35674
- }
35675
- /**
35676
- * Gets the Replicate API token from environment.
35677
- *
35678
- * @returns The Replicate API token from environment variables
35679
- */
35680
- getReplicateApiToken() {
35681
- const token = process.env.REPLICATE_API_TOKEN || process.env.NEXT_PUBLIC_REPLICATE_API_TOKEN;
35682
- if (!token) {
35683
- throw new PersonalServerError(
35684
- "REPLICATE_API_TOKEN environment variable is required"
35685
- );
35686
- }
35687
- return token;
35688
- }
35689
- /**
35690
- * Makes the request to the Replicate API.
35691
- *
35692
- * @param input - The input parameters for the Replicate API request
35693
- * @returns Promise resolving to the Replicate prediction response
35694
- */
35695
- async makeReplicateRequest(input) {
35696
- try {
35697
- const requestBody = {
35698
- version: this.PERSONAL_SERVER_VERSION,
35699
- input
35700
- };
35701
- console.debug("Replicate Request:", {
35702
- url: this.REPLICATE_API_URL,
35703
- method: "POST",
35704
- headers: {
35705
- Authorization: `Token ${this.getReplicateApiToken().substring(0, 10)}...`,
35706
- "Content-Type": "application/json"
35707
- },
35708
- body: requestBody
35709
- });
35710
- const response = await fetch(this.REPLICATE_API_URL, {
35711
- method: "POST",
35712
- headers: {
35713
- Authorization: `Token ${this.getReplicateApiToken()}`,
35714
- "Content-Type": "application/json"
35715
- },
35716
- body: JSON.stringify(requestBody)
35717
- });
35718
- if (!response.ok) {
35719
- const errorText = await response.text();
35720
- console.debug("Replicate Error Response:", {
35721
- status: response.status,
35722
- statusText: response.statusText,
35723
- error: errorText
35724
- });
35725
- throw new NetworkError(
35726
- `Replicate API request failed: ${response.status} ${response.statusText} - ${errorText}`
35727
- );
35728
- }
35729
- const data = await response.json();
35730
- console.debug("Replicate Success Response:", data);
35731
- return {
35732
- id: data.id,
35733
- status: data.status,
35734
- urls: {
35735
- get: data.urls?.get || "",
35736
- cancel: data.urls?.cancel || ""
35737
- },
35738
- input: data.input,
35739
- output: data.output,
35740
- error: data.error
35741
- };
35742
- } catch (error) {
35743
- if (error instanceof NetworkError) {
35744
- throw error;
35745
- }
35746
- throw new NetworkError(
35747
- `Failed to make Replicate API request: ${error instanceof Error ? error.message : "Unknown error"}`
35748
- );
35749
- }
35750
- }
35751
- /**
35752
- * Makes the request to the personal server.
35753
- *
35754
- * @param params - The initialization parameters for the personal server
35755
- * @returns Promise resolving to the Replicate prediction response
35756
- */
35757
- async makePersonalServerRequest(params) {
35758
- try {
35759
- const requestBody = {
35760
- version: this.IDENTITY_SERVER_VERSION,
35761
- input: {
35762
- user_address: params.userAddress
35763
- }
35764
- };
35765
- console.debug("Personal Server Request:", {
35766
- url: this.REPLICATE_API_URL,
35767
- method: "POST",
35768
- headers: {
35769
- Authorization: `Token ${this.getReplicateApiToken().substring(0, 10)}...`,
35770
- "Content-Type": "application/json"
35771
- },
35772
- body: requestBody
35773
- });
35774
- const response = await fetch(this.REPLICATE_API_URL, {
35775
- method: "POST",
35776
- headers: {
35777
- Authorization: `Token ${this.getReplicateApiToken()}`,
35778
- "Content-Type": "application/json"
35779
- },
35780
- body: JSON.stringify(requestBody)
35781
- });
35782
- if (!response.ok) {
35783
- const errorText = await response.text();
35784
- console.debug("Personal Server Error Response:", {
35785
- status: response.status,
35786
- statusText: response.statusText,
35787
- error: errorText
35788
- });
35789
- throw new NetworkError(
35790
- `Personal Server API request failed: ${response.status} ${response.statusText} - ${errorText}`
35791
- );
35792
- }
35793
- const data = await response.json();
35794
- console.debug("Personal Server Success Response:", data);
35795
- return {
35796
- id: data.id,
35797
- status: data.status,
35798
- urls: {
35799
- get: data.urls?.get || "",
35800
- cancel: data.urls?.cancel || ""
35801
- },
35802
- input: data.input,
35803
- output: data.output,
35804
- error: data.error
35805
- };
35806
- } catch (error) {
35807
- if (error instanceof NetworkError) {
35808
- throw error;
35809
- }
35810
- throw new NetworkError(
35811
- `Failed to make Personal Server API request: ${error instanceof Error ? error.message : "Unknown error"}`
35812
- );
35813
- }
35814
- }
35815
- /**
35816
- * Polls the identity server result until completion and extracts the public key.
35817
- *
35818
- * @param initialResponse - The initial response from the identity server
35819
- * @returns Promise resolving to the extracted public key
35820
- */
35821
- async pollIdentityServerResult(initialResponse) {
35822
- const maxAttempts = 60;
35823
- let attempts = 0;
35824
- let currentResponse = initialResponse;
35825
- while (attempts < maxAttempts) {
35826
- if (currentResponse.status === "succeeded") {
35827
- const output = currentResponse.output;
35828
- let parsedOutput;
35829
- if (typeof output === "string") {
35830
- try {
35831
- parsedOutput = JSON.parse(output);
35832
- } catch {
35833
- throw new PersonalServerError(
35834
- "Failed to parse Identity Server response as JSON"
35835
- );
35836
- }
35837
- } else {
35838
- parsedOutput = output;
35839
- }
35840
- const personalServer = parsedOutput.personal_server;
35841
- if (!personalServer || !personalServer.public_key) {
35842
- throw new PersonalServerError(
35843
- "Identity Server response missing personal_server.public_key"
35844
- );
35845
- }
35846
- return personalServer.public_key;
35847
- } else if (currentResponse.status === "failed") {
35848
- throw new PersonalServerError(
35849
- `Identity Server request failed: ${currentResponse.error || "Unknown error"}`
35850
- );
35851
- } else if (currentResponse.status === "canceled") {
35852
- throw new PersonalServerError("Identity Server request was canceled");
35853
- }
35854
- await new Promise((resolve) => setTimeout(resolve, 1e3));
35855
- attempts++;
35856
- if (currentResponse.urls.get) {
35857
- currentResponse = await this.pollStatus(currentResponse.urls.get);
35858
- }
35859
- }
35860
- throw new PersonalServerError(
35861
- "Identity Server request timed out after 60 seconds"
35862
- );
35863
- }
35864
- /**
35865
- * Polls the personal server result until completion.
35866
- *
35867
- * @param initialResponse - The initial response from the personal server
35868
- * @returns Promise resolving to the personal server response data
35869
- */
35870
- async pollPersonalServerResult(initialResponse) {
35871
- const maxAttempts = 60;
35872
- let attempts = 0;
35873
- let currentResponse = initialResponse;
35874
- while (attempts < maxAttempts) {
35875
- if (currentResponse.status === "succeeded") {
35876
- const output = currentResponse.output;
35877
- let parsedOutput;
35878
- if (typeof output === "string") {
35879
- try {
35880
- parsedOutput = JSON.parse(output);
35881
- } catch {
35882
- parsedOutput = output;
35883
- }
35884
- } else {
35885
- parsedOutput = output;
35886
- }
35887
- const personalServer = parsedOutput.personal_server;
35888
- const derivedAddress = personalServer?.address;
35889
- const publicKey = personalServer?.public_key;
35890
- return {
35891
- userAddress: parsedOutput.user_address,
35892
- identity: {
35893
- metadata: {
35894
- derivedAddress,
35895
- publicKey
35896
- }
35897
- },
35898
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
35899
- };
35900
- } else if (currentResponse.status === "failed") {
35901
- throw new PersonalServerError(
35902
- `Personal server initialization failed: ${currentResponse.error || "Unknown error"}`
35903
- );
35904
- } else if (currentResponse.status === "canceled") {
35905
- throw new PersonalServerError(
35906
- "Personal server initialization was canceled"
35907
- );
35908
- }
35909
- await new Promise((resolve) => setTimeout(resolve, 1e3));
35910
- attempts++;
35911
- if (currentResponse.urls.get) {
35912
- currentResponse = await this.pollStatus(currentResponse.urls.get);
35913
- }
35914
- }
35915
- throw new PersonalServerError(
35916
- "Personal server initialization timed out after 60 seconds"
35917
- );
35918
- }
35919
- };
35920
-
35921
35156
  // src/utils/encryption.ts
35922
35157
  var DEFAULT_ENCRYPTION_SEED = "Please sign to retrieve your encryption key";
35923
35158
  async function generateEncryptionKey(wallet, seed = DEFAULT_ENCRYPTION_SEED) {
@@ -35982,32 +35217,19 @@ async function decryptWithPrivateKey(encryptedData, privateKey, platformAdapter)
35982
35217
  throw new Error(`Failed to decrypt with private key: ${error}`);
35983
35218
  }
35984
35219
  }
35985
- async function encryptUserData(data, walletSignature, platformAdapter) {
35220
+ async function encryptBlobWithSignedKey(data, key, platformAdapter) {
35986
35221
  try {
35987
35222
  const dataBuffer = data instanceof Blob ? await data.arrayBuffer() : new TextEncoder().encode(data);
35988
35223
  const dataArray = new Uint8Array(dataBuffer);
35989
35224
  const encrypted = await platformAdapter.crypto.encryptWithPassword(
35990
35225
  dataArray,
35991
- walletSignature
35226
+ key
35992
35227
  );
35993
35228
  return new Blob([encrypted], {
35994
35229
  type: "application/octet-stream"
35995
35230
  });
35996
35231
  } catch (error) {
35997
- throw new Error(`Failed to encrypt user data: ${error}`);
35998
- }
35999
- }
36000
- async function decryptUserData(encryptedData, walletSignature, platformAdapter) {
36001
- try {
36002
- const encryptedBuffer = encryptedData instanceof Blob ? await encryptedData.arrayBuffer() : new TextEncoder().encode(encryptedData);
36003
- const encryptedArray = new Uint8Array(encryptedBuffer);
36004
- const decrypted = await platformAdapter.crypto.decryptWithPassword(
36005
- encryptedArray,
36006
- walletSignature
36007
- );
36008
- return new Blob([decrypted], { type: "text/plain" });
36009
- } catch (error) {
36010
- throw new Error(`Failed to decrypt user data: ${error}`);
35232
+ throw new Error(`Failed to encrypt data: ${error}`);
36011
35233
  }
36012
35234
  }
36013
35235
  async function generateEncryptionKeyPair(platformAdapter) {
@@ -36024,13 +35246,315 @@ async function generatePGPKeyPair(platformAdapter, options) {
36024
35246
  throw new Error(`Failed to generate PGP key pair: ${error}`);
36025
35247
  }
36026
35248
  }
35249
+ async function decryptBlobWithSignedKey(encryptedData, key, platformAdapter) {
35250
+ try {
35251
+ const encryptedBuffer = encryptedData instanceof Blob ? await encryptedData.arrayBuffer() : new TextEncoder().encode(encryptedData);
35252
+ const encryptedArray = new Uint8Array(encryptedBuffer);
35253
+ const decrypted = await platformAdapter.crypto.decryptWithPassword(
35254
+ encryptedArray,
35255
+ key
35256
+ );
35257
+ return new Blob([decrypted], { type: "text/plain" });
35258
+ } catch (error) {
35259
+ throw new Error(`Failed to decrypt data: ${error}`);
35260
+ }
35261
+ }
36027
35262
 
36028
35263
  // src/controllers/data.ts
36029
35264
  var DataController = class {
36030
35265
  constructor(context) {
36031
35266
  this.context = context;
36032
- __publicField(this, "serverController");
36033
- this.serverController = new ServerController(context);
35267
+ }
35268
+ async upload(params) {
35269
+ const {
35270
+ content,
35271
+ filename,
35272
+ schemaId,
35273
+ permissions = [],
35274
+ encrypt: encrypt2 = true,
35275
+ providerName
35276
+ } = params;
35277
+ try {
35278
+ let blob;
35279
+ if (content instanceof Blob) {
35280
+ blob = content;
35281
+ } else if (typeof content === "string") {
35282
+ blob = new Blob([content], { type: "text/plain" });
35283
+ } else if (content instanceof Buffer) {
35284
+ blob = new Blob([content], { type: "application/octet-stream" });
35285
+ } else {
35286
+ blob = new Blob([JSON.stringify(content)], {
35287
+ type: "application/json"
35288
+ });
35289
+ }
35290
+ let isValid = true;
35291
+ let validationErrors = [];
35292
+ if (schemaId !== void 0) {
35293
+ try {
35294
+ const schema = await this.getSchema(schemaId);
35295
+ const response = await fetch(schema.definitionUrl);
35296
+ if (!response.ok) {
35297
+ throw new Error(
35298
+ `Failed to fetch schema definition: ${response.status}`
35299
+ );
35300
+ }
35301
+ const schemaDefinition = await response.json();
35302
+ const dataSchema = {
35303
+ name: schema.name,
35304
+ version: "1.0.0",
35305
+ dialect: "json",
35306
+ schema: schemaDefinition
35307
+ };
35308
+ let parsedContent;
35309
+ if (typeof content === "string") {
35310
+ try {
35311
+ parsedContent = JSON.parse(content);
35312
+ } catch {
35313
+ parsedContent = content;
35314
+ }
35315
+ } else {
35316
+ parsedContent = content;
35317
+ }
35318
+ validateDataAgainstSchema(parsedContent, dataSchema);
35319
+ } catch (error) {
35320
+ isValid = false;
35321
+ validationErrors = [
35322
+ error instanceof Error ? error.message : "Schema validation failed"
35323
+ ];
35324
+ }
35325
+ }
35326
+ let finalBlob = blob;
35327
+ if (encrypt2) {
35328
+ const encryptionKey = await generateEncryptionKey(
35329
+ this.context.walletClient,
35330
+ DEFAULT_ENCRYPTION_SEED
35331
+ );
35332
+ finalBlob = await encryptBlobWithSignedKey(
35333
+ blob,
35334
+ encryptionKey,
35335
+ this.context.platform
35336
+ );
35337
+ }
35338
+ if (!this.context.storageManager) {
35339
+ if (this.context.validateStorageRequired) {
35340
+ this.context.validateStorageRequired();
35341
+ throw new Error("Storage validation failed");
35342
+ } else {
35343
+ throw new Error(
35344
+ "Storage manager not configured. Please provide storage providers in VanaConfig."
35345
+ );
35346
+ }
35347
+ }
35348
+ const uploadResult = await this.context.storageManager.upload(
35349
+ finalBlob,
35350
+ filename,
35351
+ providerName
35352
+ );
35353
+ const userAddress = await this.getUserAddress();
35354
+ let encryptedPermissions = [];
35355
+ if (permissions.length > 0 && encrypt2) {
35356
+ const userEncryptionKey = await generateEncryptionKey(
35357
+ this.context.walletClient,
35358
+ DEFAULT_ENCRYPTION_SEED
35359
+ );
35360
+ encryptedPermissions = await Promise.all(
35361
+ permissions.map(async (permission) => {
35362
+ const publicKey = permission.publicKey;
35363
+ if (!publicKey) {
35364
+ throw new Error(
35365
+ `Public key required for permission to ${permission.grantee} when encryption is enabled`
35366
+ );
35367
+ }
35368
+ const encryptedKey = await encryptWithWalletPublicKey(
35369
+ userEncryptionKey,
35370
+ publicKey,
35371
+ this.context.platform
35372
+ );
35373
+ return {
35374
+ account: permission.grantee,
35375
+ key: encryptedKey
35376
+ };
35377
+ })
35378
+ );
35379
+ }
35380
+ let result;
35381
+ if (this.context.relayerCallbacks?.submitFileAdditionComplete) {
35382
+ result = await this.context.relayerCallbacks.submitFileAdditionComplete(
35383
+ {
35384
+ url: uploadResult.url,
35385
+ userAddress,
35386
+ permissions: encryptedPermissions,
35387
+ schemaId: schemaId || 0
35388
+ }
35389
+ );
35390
+ } else if (this.context.relayerCallbacks?.submitFileAddition) {
35391
+ const needsComplexRegistration = schemaId !== void 0 || encryptedPermissions.length > 0;
35392
+ if (needsComplexRegistration) {
35393
+ throw new Error(
35394
+ "The configured relay callback does not support schemas or permissions. Please update your relay server implementation to provide the `submitFileAdditionComplete` callback."
35395
+ );
35396
+ }
35397
+ result = await this.context.relayerCallbacks.submitFileAddition(
35398
+ uploadResult.url,
35399
+ userAddress
35400
+ );
35401
+ } else {
35402
+ result = await this.addFileWithPermissionsAndSchema(
35403
+ uploadResult.url,
35404
+ userAddress,
35405
+ encryptedPermissions,
35406
+ schemaId || 0
35407
+ );
35408
+ }
35409
+ return {
35410
+ fileId: result.fileId,
35411
+ url: uploadResult.url,
35412
+ transactionHash: result.transactionHash,
35413
+ size: uploadResult.size,
35414
+ isValid,
35415
+ validationErrors: validationErrors.length > 0 ? validationErrors : void 0
35416
+ };
35417
+ } catch (error) {
35418
+ throw new Error(
35419
+ `Upload failed: ${error instanceof Error ? error.message : "Unknown error"}`
35420
+ );
35421
+ }
35422
+ }
35423
+ /**
35424
+ * Decrypts a file owned by the user using their wallet signature.
35425
+ *
35426
+ * @remarks
35427
+ * This is the high-level convenience method for decrypting user files, serving as the
35428
+ * symmetrical counterpart to the `upload` method. It handles the complete decryption
35429
+ * workflow including key generation, URL protocol detection, content fetching, and
35430
+ * decryption.
35431
+ *
35432
+ * The method automatically:
35433
+ * - Generates the decryption key from the user's wallet signature
35434
+ * - Determines the appropriate fetch method based on the file URL protocol
35435
+ * - Fetches the encrypted content from IPFS or standard HTTP URLs
35436
+ * - Decrypts the content using the generated key
35437
+ *
35438
+ * For IPFS URLs, the method uses gateway fallback for improved reliability. For
35439
+ * standard HTTP URLs, it uses a simple fetch. If you need custom authentication
35440
+ * headers or specific gateway configurations, use the low-level primitives directly.
35441
+ *
35442
+ * @param file - The user file to decrypt (typically from getUserFiles)
35443
+ * @param encryptionSeed - Optional custom encryption seed (defaults to Vana standard)
35444
+ * @returns Promise resolving to the decrypted file content as a Blob
35445
+ * @throws {Error} When the wallet is not connected
35446
+ * @throws {Error} When fetching the encrypted content fails
35447
+ * @throws {Error} When decryption fails (wrong key or corrupted data)
35448
+ * @example
35449
+ * ```typescript
35450
+ * // Basic file decryption
35451
+ * const files = await vana.data.getUserFiles({ owner: userAddress });
35452
+ * const decryptedBlob = await vana.data.decryptFile(files[0]);
35453
+ *
35454
+ * // Convert to text
35455
+ * const text = await decryptedBlob.text();
35456
+ * console.log('Decrypted content:', text);
35457
+ *
35458
+ * // Convert to JSON
35459
+ * const json = JSON.parse(await decryptedBlob.text());
35460
+ * console.log('Decrypted data:', json);
35461
+ *
35462
+ * // With custom encryption seed
35463
+ * const decryptedBlob = await vana.data.decryptFile(
35464
+ * files[0],
35465
+ * "My custom encryption seed"
35466
+ * );
35467
+ *
35468
+ * // Save to file (in Node.js)
35469
+ * const buffer = await decryptedBlob.arrayBuffer();
35470
+ * fs.writeFileSync('decrypted-file.txt', Buffer.from(buffer));
35471
+ * ```
35472
+ */
35473
+ async decryptFile(file, encryptionSeed) {
35474
+ try {
35475
+ const encryptionKey = await generateEncryptionKey(
35476
+ this.context.walletClient,
35477
+ encryptionSeed || DEFAULT_ENCRYPTION_SEED
35478
+ );
35479
+ let encryptedBlob;
35480
+ try {
35481
+ if (file.url.startsWith("ipfs://")) {
35482
+ encryptedBlob = await this.fetchFromIPFS(file.url);
35483
+ } else {
35484
+ encryptedBlob = await this.fetch(file.url);
35485
+ }
35486
+ } catch (fetchError) {
35487
+ const errorMessage = fetchError instanceof Error ? fetchError.message : "Unknown error";
35488
+ if (errorMessage.includes("Failed to fetch IPFS content") && errorMessage.includes("from all gateways")) {
35489
+ throw new Error(
35490
+ "Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
35491
+ );
35492
+ } else if (errorMessage.includes("Empty response")) {
35493
+ throw new Error("File is empty or could not be retrieved");
35494
+ } else if (errorMessage.includes("Network error:") || errorMessage.includes("Failed to fetch")) {
35495
+ throw new Error(
35496
+ "Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
35497
+ );
35498
+ } else if (errorMessage.includes("HTTP error!")) {
35499
+ const statusMatch = errorMessage.match(/status: (\d+)/);
35500
+ const status = statusMatch ? statusMatch[1] : "unknown";
35501
+ if (status === "500") {
35502
+ throw new Error(
35503
+ "Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
35504
+ );
35505
+ } else if (status === "403") {
35506
+ throw new Error(
35507
+ "Access denied. You may not have permission to access this file"
35508
+ );
35509
+ } else if (status === "404") {
35510
+ throw new Error(
35511
+ "File not found: The encrypted file is no longer available at the stored URL."
35512
+ );
35513
+ } else {
35514
+ throw new Error(
35515
+ "Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
35516
+ );
35517
+ }
35518
+ }
35519
+ throw fetchError;
35520
+ }
35521
+ if (encryptedBlob.size === 0) {
35522
+ throw new Error("File is empty or could not be retrieved");
35523
+ }
35524
+ let decryptedBlob;
35525
+ try {
35526
+ decryptedBlob = await decryptBlobWithSignedKey(
35527
+ encryptedBlob,
35528
+ encryptionKey,
35529
+ this.context.platform
35530
+ );
35531
+ } catch (decryptError) {
35532
+ const errorMessage = decryptError instanceof Error ? decryptError.message : "Unknown error";
35533
+ if (errorMessage.includes("not a valid OpenPGP message")) {
35534
+ throw new Error(
35535
+ "Invalid file format: This file doesn't appear to be encrypted with the Vana protocol"
35536
+ );
35537
+ } else if (errorMessage.includes("Session key decryption failed")) {
35538
+ throw new Error("Wrong encryption key");
35539
+ } else if (errorMessage.includes("Error decrypting message")) {
35540
+ throw new Error("Wrong encryption key");
35541
+ } else if (errorMessage.includes("File not found")) {
35542
+ throw new Error(
35543
+ "File not found: The encrypted file is no longer available"
35544
+ );
35545
+ } else {
35546
+ throw decryptError;
35547
+ }
35548
+ }
35549
+ return decryptedBlob;
35550
+ } catch (error) {
35551
+ if (error instanceof Error && (error.message.includes("Network error:") || error.message.includes("Invalid file format:") || error.message.includes("Wrong encryption key") || error.message.includes("Access denied") || error.message.includes("File not found:") || error.message.includes("File is empty"))) {
35552
+ throw error;
35553
+ }
35554
+ throw new Error(
35555
+ `Failed to decrypt file: ${error instanceof Error ? error.message : "Unknown error"}`
35556
+ );
35557
+ }
36034
35558
  }
36035
35559
  /**
36036
35560
  * Retrieves all data files owned by a specific user address.
@@ -36615,6 +36139,7 @@ var DataController = class {
36615
36139
  /**
36616
36140
  * Uploads an encrypted file to storage and registers it on the blockchain.
36617
36141
  *
36142
+ * @deprecated Use vana.data.upload() instead for the high-level API with automatic encryption
36618
36143
  * @param encryptedFile - The encrypted file blob to upload
36619
36144
  * @param filename - Optional filename for the upload
36620
36145
  * @param providerName - Optional storage provider to use
@@ -36702,6 +36227,7 @@ var DataController = class {
36702
36227
  /**
36703
36228
  * Uploads an encrypted file to storage and registers it on the blockchain with a schema.
36704
36229
  *
36230
+ * @deprecated Use vana.data.upload() instead for the high-level API with automatic encryption and schema validation
36705
36231
  * @param encryptedFile - The encrypted file blob to upload
36706
36232
  * @param schemaId - The schema ID to associate with the file
36707
36233
  * @param filename - Optional filename for the upload
@@ -36780,81 +36306,6 @@ var DataController = class {
36780
36306
  );
36781
36307
  }
36782
36308
  }
36783
- /**
36784
- * Decrypts a file that was encrypted using the Vana protocol.
36785
- *
36786
- * @param file - The UserFile object containing the file URL and metadata
36787
- * @param encryptionSeed - Optional custom encryption seed (defaults to Vana standard)
36788
- * @returns Promise resolving to the decrypted file as a Blob
36789
- *
36790
- * This method handles the complete flow of:
36791
- * 1. Generating the encryption key from the user's wallet signature
36792
- * 2. Fetching the encrypted file from the stored URL
36793
- * 3. Decrypting the file using the canonical Vana decryption method
36794
- */
36795
- async decryptFile(file, encryptionSeed = DEFAULT_ENCRYPTION_SEED) {
36796
- try {
36797
- const encryptionKey = await generateEncryptionKey(
36798
- this.context.walletClient,
36799
- encryptionSeed
36800
- );
36801
- const fetchUrl = this.convertToDownloadUrl(file.url);
36802
- console.debug(
36803
- `Fetching encrypted file from URL: ${fetchUrl} (original: ${file.url})`
36804
- );
36805
- const response = await fetch(fetchUrl);
36806
- if (!response.ok) {
36807
- if (response.status === 404) {
36808
- throw new Error(
36809
- "File not found. The encrypted file may have been moved or deleted."
36810
- );
36811
- } else if (response.status === 403) {
36812
- throw new Error(
36813
- "Access denied. You may not have permission to access this file."
36814
- );
36815
- } else {
36816
- throw new Error(
36817
- `Network error: ${response.status} ${response.statusText}`
36818
- );
36819
- }
36820
- }
36821
- const encryptedBlob = await response.blob();
36822
- console.debug(
36823
- `Retrieved blob of size: ${encryptedBlob.size} bytes, type: ${encryptedBlob.type}`
36824
- );
36825
- if (encryptedBlob.size === 0) {
36826
- throw new Error("File is empty or could not be retrieved.");
36827
- }
36828
- const decryptedBlob = await decryptUserData(
36829
- encryptedBlob,
36830
- encryptionKey,
36831
- this.context.platform
36832
- );
36833
- return decryptedBlob;
36834
- } catch (error) {
36835
- console.error("Failed to decrypt file:", error);
36836
- if (error instanceof Error) {
36837
- if (error.message.includes("Session key decryption failed") || error.message.includes("Error decrypting message")) {
36838
- throw new Error(
36839
- "Wrong encryption key. This file may have been encrypted with a different wallet or encryption seed. Try using the same wallet that originally encrypted this file."
36840
- );
36841
- } else if (error.message.includes("Failed to fetch") || error.message.includes("Network error")) {
36842
- throw new Error(
36843
- "Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
36844
- );
36845
- } else if (error.message.includes("File not found")) {
36846
- throw new Error(
36847
- "File not found: The encrypted file is no longer available at the stored URL."
36848
- );
36849
- } else if (error.message.includes("not a valid OpenPGP message") || error.message.includes("does not conform to a valid OpenPGP format")) {
36850
- throw new Error(
36851
- "Invalid file format: This file doesn't appear to be encrypted with the Vana protocol."
36852
- );
36853
- }
36854
- }
36855
- throw error;
36856
- }
36857
- }
36858
36309
  /**
36859
36310
  * Registers a file URL directly on the blockchain with a schema ID.
36860
36311
  *
@@ -36915,26 +36366,6 @@ var DataController = class {
36915
36366
  );
36916
36367
  }
36917
36368
  }
36918
- /**
36919
- * Converts IPFS and Google Drive URLs to direct download URLs for fetching.
36920
- *
36921
- * @param url - The URL to convert to a direct download URL
36922
- * @returns The converted direct download URL or the original URL if not a special URL
36923
- */
36924
- convertToDownloadUrl(url) {
36925
- if (url.startsWith("ipfs://")) {
36926
- const hash = url.replace("ipfs://", "");
36927
- return `https://ipfs.io/ipfs/${hash}`;
36928
- }
36929
- if (url.includes("drive.google.com/file/d/")) {
36930
- const fileIdMatch = url.match(/\/file\/d\/([a-zA-Z0-9-_]+)/);
36931
- if (fileIdMatch) {
36932
- const fileId = fileIdMatch[1];
36933
- return `https://drive.google.com/uc?id=${fileId}&export=download`;
36934
- }
36935
- }
36936
- return url;
36937
- }
36938
36369
  /**
36939
36370
  * Gets the user's address from the wallet client.
36940
36371
  *
@@ -37009,9 +36440,70 @@ var DataController = class {
37009
36440
  );
37010
36441
  }
37011
36442
  }
36443
+ /**
36444
+ * Adds a file to the registry with permissions and schema.
36445
+ * This combines the functionality of addFileWithPermissions and schema validation.
36446
+ *
36447
+ * @param url - The URL of the file to register
36448
+ * @param ownerAddress - The address of the file owner
36449
+ * @param permissions - Array of permissions to grant (account and encrypted key)
36450
+ * @param schemaId - The schema ID to associate with the file (0 for no schema)
36451
+ * @returns Promise resolving to object with fileId and transactionHash
36452
+ */
36453
+ async addFileWithPermissionsAndSchema(url, ownerAddress, permissions = [], schemaId = 0) {
36454
+ try {
36455
+ const chainId = this.context.walletClient.chain?.id;
36456
+ if (!chainId) {
36457
+ throw new Error("Chain ID not available");
36458
+ }
36459
+ const dataRegistryAddress = getContractAddress(chainId, "DataRegistry");
36460
+ const dataRegistryAbi = getAbi("DataRegistry");
36461
+ const txHash = await this.context.walletClient.writeContract({
36462
+ address: dataRegistryAddress,
36463
+ abi: dataRegistryAbi,
36464
+ functionName: "addFileWithPermissionsAndSchema",
36465
+ args: [url, ownerAddress, permissions, BigInt(schemaId)],
36466
+ account: this.context.walletClient.account || ownerAddress,
36467
+ chain: this.context.walletClient.chain || null
36468
+ });
36469
+ const receipt = await this.context.publicClient.waitForTransactionReceipt(
36470
+ {
36471
+ hash: txHash,
36472
+ timeout: 3e4
36473
+ // 30 seconds timeout
36474
+ }
36475
+ );
36476
+ let fileId = 0;
36477
+ for (const log of receipt.logs) {
36478
+ try {
36479
+ const decoded = decodeEventLog({
36480
+ abi: dataRegistryAbi,
36481
+ data: log.data,
36482
+ topics: log.topics
36483
+ });
36484
+ if (decoded.eventName === "FileAdded") {
36485
+ fileId = Number(decoded.args.fileId);
36486
+ break;
36487
+ }
36488
+ } catch {
36489
+ continue;
36490
+ }
36491
+ }
36492
+ return {
36493
+ fileId,
36494
+ transactionHash: txHash
36495
+ };
36496
+ } catch (error) {
36497
+ console.error("Failed to add file with permissions and schema:", error);
36498
+ throw new Error(
36499
+ `Failed to add file with permissions and schema: ${error instanceof Error ? error.message : "Unknown error"}`
36500
+ );
36501
+ }
36502
+ }
37012
36503
  /**
37013
36504
  * Adds a new schema to the DataRefinerRegistry.
37014
36505
  *
36506
+ * @deprecated Use vana.schemas.create() instead for the high-level API with automatic IPFS upload
37015
36507
  * @param params - Schema parameters including name, type, and definition URL
37016
36508
  * @returns Promise resolving to the new schema ID and transaction hash
37017
36509
  */
@@ -37070,6 +36562,7 @@ var DataController = class {
37070
36562
  /**
37071
36563
  * Retrieves a schema by its ID.
37072
36564
  *
36565
+ * @deprecated Use vana.schemas.get() instead
37073
36566
  * @param schemaId - The schema ID to retrieve
37074
36567
  * @returns Promise resolving to the schema information
37075
36568
  */
@@ -37095,11 +36588,15 @@ var DataController = class {
37095
36588
  if (!schemaData) {
37096
36589
  throw new Error("Schema not found");
37097
36590
  }
36591
+ const schemaObj = schemaData;
36592
+ if (!schemaObj.name || !schemaObj.typ || !schemaObj.definitionUrl) {
36593
+ throw new Error("Incomplete schema data");
36594
+ }
37098
36595
  return {
37099
36596
  id: schemaId,
37100
- name: schemaData.name,
37101
- type: schemaData.typ,
37102
- definitionUrl: schemaData.definitionUrl
36597
+ name: schemaObj.name,
36598
+ type: schemaObj.typ,
36599
+ definitionUrl: schemaObj.definitionUrl
37103
36600
  };
37104
36601
  } catch (error) {
37105
36602
  console.error("Failed to get schema:", error);
@@ -37111,6 +36608,7 @@ var DataController = class {
37111
36608
  /**
37112
36609
  * Gets the total number of schemas in the registry.
37113
36610
  *
36611
+ * @deprecated Use vana.schemas.count() instead
37114
36612
  * @returns Promise resolving to the total schema count
37115
36613
  */
37116
36614
  async getSchemasCount() {
@@ -37156,7 +36654,7 @@ var DataController = class {
37156
36654
  const txHash = await this.context.walletClient.writeContract({
37157
36655
  address: dataRefinerRegistryAddress,
37158
36656
  abi: dataRefinerRegistryAbi,
37159
- functionName: "addRefiner",
36657
+ functionName: "addRefinerWithSchemaId",
37160
36658
  args: [
37161
36659
  BigInt(params.dlpId),
37162
36660
  params.name,
@@ -37361,7 +36859,7 @@ var DataController = class {
37361
36859
  this.context.walletClient,
37362
36860
  DEFAULT_ENCRYPTION_SEED
37363
36861
  );
37364
- const encryptedData = await encryptUserData(
36862
+ const encryptedData = await encryptBlobWithSignedKey(
37365
36863
  data,
37366
36864
  userEncryptionKey,
37367
36865
  this.context.platform
@@ -37495,25 +36993,6 @@ var DataController = class {
37495
36993
  );
37496
36994
  }
37497
36995
  }
37498
- /**
37499
- * Gets the trusted server public key for a given server address.
37500
- * This method reads from the permissions contract to find servers and their public keys.
37501
- *
37502
- * @param serverAddress - The address of the trusted server
37503
- * @returns Promise resolving to the server's public key
37504
- */
37505
- async getTrustedServerPublicKey(serverAddress) {
37506
- try {
37507
- return await this.serverController.getTrustedServerPublicKey(
37508
- serverAddress
37509
- );
37510
- } catch (error) {
37511
- console.error("Failed to get trusted server public key:", error);
37512
- throw new Error(
37513
- `Failed to get trusted server public key: ${error instanceof Error ? error.message : "Unknown error"}`
37514
- );
37515
- }
37516
- }
37517
36996
  /**
37518
36997
  * Decrypts a file that the user has permission to access using their private key.
37519
36998
  *
@@ -37544,12 +37023,13 @@ var DataController = class {
37544
37023
  privateKey,
37545
37024
  this.context.platform
37546
37025
  );
37547
- const response = await fetch(this.convertToDownloadUrl(file.url));
37548
- if (!response.ok) {
37549
- throw new Error(`Failed to download file: ${response.statusText}`);
37026
+ let encryptedData;
37027
+ if (file.url.startsWith("ipfs://")) {
37028
+ encryptedData = await this.fetchFromIPFS(file.url);
37029
+ } else {
37030
+ encryptedData = await this.fetch(file.url);
37550
37031
  }
37551
- const encryptedData = await response.blob();
37552
- const decryptedData = await decryptUserData(
37032
+ const decryptedData = await decryptBlobWithSignedKey(
37553
37033
  encryptedData,
37554
37034
  userEncryptionKey,
37555
37035
  this.context.platform
@@ -37562,6 +37042,162 @@ var DataController = class {
37562
37042
  );
37563
37043
  }
37564
37044
  }
37045
+ /**
37046
+ * Simple network-agnostic fetch utility for retrieving file content.
37047
+ *
37048
+ * @remarks
37049
+ * This is a thin wrapper around the global fetch API that returns the response as a Blob.
37050
+ * It provides a consistent interface for fetching encrypted content before decryption.
37051
+ * For IPFS URLs, consider using fetchFromIPFS for better reliability.
37052
+ *
37053
+ * @param url - The URL to fetch content from
37054
+ * @returns Promise resolving to the fetched content as a Blob
37055
+ * @throws {Error} When the fetch fails or returns a non-ok response
37056
+ *
37057
+ * @example
37058
+ * ```typescript
37059
+ * // Fetch and decrypt a file
37060
+ * const encryptionKey = await generateEncryptionKey(walletClient);
37061
+ * const encryptedBlob = await vana.data.fetch(file.url);
37062
+ * const decryptedBlob = await decryptBlob(encryptedBlob, encryptionKey, platform);
37063
+ *
37064
+ * // With custom headers for authentication
37065
+ * const response = await fetch(file.url, {
37066
+ * headers: { 'Authorization': 'Bearer token' }
37067
+ * });
37068
+ * const encryptedBlob = await response.blob();
37069
+ * ```
37070
+ */
37071
+ async fetch(url) {
37072
+ try {
37073
+ const response = await fetch(url);
37074
+ if (!response.ok) {
37075
+ throw new Error(
37076
+ `HTTP error! status: ${response.status} ${response.statusText}`
37077
+ );
37078
+ }
37079
+ const blob = await response.blob();
37080
+ if (blob.size === 0) {
37081
+ throw new Error("Empty response");
37082
+ }
37083
+ return blob;
37084
+ } catch (error) {
37085
+ if (error instanceof TypeError && error.message.includes("fetch")) {
37086
+ throw new Error(
37087
+ `Network error: Failed to fetch from ${url}. The URL may be invalid or the server may not be accessible.`
37088
+ );
37089
+ }
37090
+ throw error;
37091
+ }
37092
+ }
37093
+ /**
37094
+ * Specialized IPFS fetcher with gateway fallback mechanism.
37095
+ *
37096
+ * @remarks
37097
+ * This method provides robust IPFS content fetching by trying multiple gateways
37098
+ * in sequence until one succeeds. It supports both ipfs:// URLs and raw CIDs.
37099
+ *
37100
+ * The default gateway list includes public gateways, but you should provide
37101
+ * your own gateways for production use to ensure reliability and privacy.
37102
+ *
37103
+ * @param url - The IPFS URL (ipfs://...) or CID to fetch
37104
+ * @param options - Optional configuration
37105
+ * @param options.gateways - Array of IPFS gateway URLs to try (must end with /)
37106
+ * @returns Promise resolving to the fetched content as a Blob
37107
+ * @throws {Error} When all gateways fail to fetch the content
37108
+ *
37109
+ * @example
37110
+ * ```typescript
37111
+ * // Fetch from IPFS with custom gateways
37112
+ * const encryptedBlob = await vana.data.fetchFromIPFS(file.url, {
37113
+ * gateways: [
37114
+ * 'https://my-private-gateway.com/ipfs/',
37115
+ * 'https://dweb.link/ipfs/',
37116
+ * 'https://ipfs.io/ipfs/'
37117
+ * ]
37118
+ * });
37119
+ *
37120
+ * // Decrypt the fetched content
37121
+ * const encryptionKey = await generateEncryptionKey(walletClient);
37122
+ * const decryptedBlob = await decryptBlob(encryptedBlob, encryptionKey, platform);
37123
+ *
37124
+ * // With raw CID
37125
+ * const blob = await vana.data.fetchFromIPFS('QmXxx...', {
37126
+ * gateways: ['https://ipfs.io/ipfs/']
37127
+ * });
37128
+ * ```
37129
+ */
37130
+ async fetchFromIPFS(url, options) {
37131
+ const defaultGateways = [
37132
+ "https://dweb.link/ipfs/",
37133
+ "https://ipfs.io/ipfs/"
37134
+ ];
37135
+ const gateways = options?.gateways || this.context.ipfsGateways || defaultGateways;
37136
+ let cid;
37137
+ if (url.startsWith("ipfs://")) {
37138
+ cid = url.replace("ipfs://", "");
37139
+ } else if (url.startsWith("Qm") || url.startsWith("bafy")) {
37140
+ cid = url;
37141
+ } else {
37142
+ throw new Error(
37143
+ `Invalid IPFS URL format. Expected ipfs://... or a raw CID, got: ${url}`
37144
+ );
37145
+ }
37146
+ const errors = [];
37147
+ for (let i = 0; i < gateways.length; i++) {
37148
+ const gateway = gateways[i];
37149
+ const isLastGateway = i === gateways.length - 1;
37150
+ const gatewayUrl = gateway.endsWith("/") ? `${gateway}${cid}` : `${gateway}/${cid}`;
37151
+ try {
37152
+ console.debug(`Trying IPFS gateway: ${gatewayUrl}`);
37153
+ const response = await fetch(gatewayUrl);
37154
+ if (response.ok) {
37155
+ const blob = await response.blob();
37156
+ if (blob.size > 0) {
37157
+ console.debug(`Successfully fetched from gateway: ${gateway}`);
37158
+ return blob;
37159
+ } else {
37160
+ if (isLastGateway) {
37161
+ throw new Error("Empty response");
37162
+ }
37163
+ errors.push({
37164
+ gateway,
37165
+ error: "Empty response"
37166
+ });
37167
+ }
37168
+ } else {
37169
+ if (isLastGateway) {
37170
+ if (response.status === 403) {
37171
+ throw new Error(`HTTP error! status: 403 ${response.statusText}`);
37172
+ } else if (response.status === 404) {
37173
+ throw new Error(`HTTP error! status: 404 ${response.statusText}`);
37174
+ } else {
37175
+ throw new Error(
37176
+ `HTTP error! status: ${response.status} ${response.statusText}`
37177
+ );
37178
+ }
37179
+ }
37180
+ errors.push({
37181
+ gateway,
37182
+ error: `HTTP ${response.status} ${response.statusText}`
37183
+ });
37184
+ }
37185
+ } catch (error) {
37186
+ if (isLastGateway && error instanceof Error && (error.message.includes("Empty response") || error.message.includes("HTTP error!"))) {
37187
+ throw error;
37188
+ }
37189
+ errors.push({
37190
+ gateway,
37191
+ error: error instanceof Error ? error.message : "Unknown error"
37192
+ });
37193
+ }
37194
+ }
37195
+ const errorDetails = errors.map((e) => `${e.gateway}: ${e.error}`).join("\n ");
37196
+ throw new Error(
37197
+ `Failed to fetch IPFS content ${cid} from all gateways:
37198
+ ${errorDetails}`
37199
+ );
37200
+ }
37565
37201
  /**
37566
37202
  * Validates a data schema against the Vana meta-schema.
37567
37203
  *
@@ -37683,9 +37319,589 @@ var DataController = class {
37683
37319
  }
37684
37320
  };
37685
37321
 
37322
+ // src/controllers/schemas.ts
37323
+ import { getContract as getContract2, decodeEventLog as decodeEventLog2 } from "viem";
37324
+ var SchemaController = class {
37325
+ constructor(context) {
37326
+ this.context = context;
37327
+ }
37328
+ /**
37329
+ * Creates a new schema with automatic validation and IPFS upload.
37330
+ *
37331
+ * @remarks
37332
+ * This is the primary method for creating schemas on the Vana network. It handles
37333
+ * the complete workflow including schema validation, IPFS upload, and blockchain
37334
+ * registration. The schema definition is stored unencrypted on IPFS to enable
37335
+ * public access and reusability.
37336
+ *
37337
+ * The method automatically:
37338
+ * - Validates the schema definition against the Vana metaschema
37339
+ * - Uploads the definition to IPFS to generate a permanent URL
37340
+ * - Registers the schema on the blockchain with the generated URL
37341
+ *
37342
+ * @param params - Schema creation parameters including name, type, and definition
37343
+ * @returns Promise resolving to creation results with schema ID and transaction hash
37344
+ * @throws {SchemaValidationError} When the schema definition is invalid
37345
+ * @throws {Error} When IPFS upload or blockchain registration fails
37346
+ * @example
37347
+ * ```typescript
37348
+ * // Create a JSON schema for user profiles
37349
+ * const result = await vana.schemas.create({
37350
+ * name: "User Profile",
37351
+ * type: "personal",
37352
+ * definition: {
37353
+ * type: "object",
37354
+ * properties: {
37355
+ * name: { type: "string" },
37356
+ * age: { type: "number", minimum: 0 }
37357
+ * },
37358
+ * required: ["name"]
37359
+ * }
37360
+ * });
37361
+ *
37362
+ * console.log(`Schema created with ID: ${result.schemaId}`);
37363
+ * ```
37364
+ */
37365
+ async create(params) {
37366
+ const { name, type, definition } = params;
37367
+ try {
37368
+ let schemaDefinition;
37369
+ if (typeof definition === "string") {
37370
+ try {
37371
+ schemaDefinition = JSON.parse(definition);
37372
+ } catch {
37373
+ throw new SchemaValidationError(
37374
+ "Invalid JSON in schema definition",
37375
+ []
37376
+ );
37377
+ }
37378
+ } else {
37379
+ schemaDefinition = definition;
37380
+ }
37381
+ const dataSchema = {
37382
+ name,
37383
+ version: "1.0.0",
37384
+ dialect: "json",
37385
+ schema: schemaDefinition
37386
+ };
37387
+ validateDataSchema(dataSchema);
37388
+ if (!this.context.storageManager) {
37389
+ if (this.context.validateStorageRequired) {
37390
+ this.context.validateStorageRequired();
37391
+ throw new Error("Storage validation failed");
37392
+ } else {
37393
+ throw new Error(
37394
+ "Storage manager not configured. Please provide storage providers in VanaConfig."
37395
+ );
37396
+ }
37397
+ }
37398
+ const schemaBlob = new Blob([JSON.stringify(schemaDefinition)], {
37399
+ type: "application/json"
37400
+ });
37401
+ const uploadResult = await this.context.storageManager.upload(
37402
+ schemaBlob,
37403
+ `${name.replace(/[^a-zA-Z0-9]/g, "_")}.json`,
37404
+ "ipfs"
37405
+ // Use IPFS for public schema storage
37406
+ );
37407
+ const chainId = this.context.walletClient.chain?.id;
37408
+ if (!chainId) {
37409
+ throw new Error("Chain ID not available");
37410
+ }
37411
+ const dataRefinerRegistryAddress = getContractAddress(
37412
+ chainId,
37413
+ "DataRefinerRegistry"
37414
+ );
37415
+ const dataRefinerRegistryAbi = getAbi("DataRefinerRegistry");
37416
+ const userAddress = await this.getUserAddress();
37417
+ const txHash = await this.context.walletClient.writeContract({
37418
+ address: dataRefinerRegistryAddress,
37419
+ abi: dataRefinerRegistryAbi,
37420
+ functionName: "addSchema",
37421
+ args: [name, type, uploadResult.url],
37422
+ account: this.context.walletClient.account || userAddress,
37423
+ chain: this.context.walletClient.chain || null
37424
+ });
37425
+ const receipt = await this.context.publicClient.waitForTransactionReceipt(
37426
+ {
37427
+ hash: txHash,
37428
+ timeout: 3e4
37429
+ // 30 seconds timeout
37430
+ }
37431
+ );
37432
+ let schemaId = 0;
37433
+ for (const log of receipt.logs) {
37434
+ try {
37435
+ const decoded = decodeEventLog2({
37436
+ abi: dataRefinerRegistryAbi,
37437
+ data: log.data,
37438
+ topics: log.topics
37439
+ });
37440
+ if (decoded.eventName === "SchemaAdded") {
37441
+ schemaId = Number(decoded.args.schemaId);
37442
+ break;
37443
+ }
37444
+ } catch {
37445
+ }
37446
+ }
37447
+ return {
37448
+ schemaId,
37449
+ definitionUrl: uploadResult.url,
37450
+ transactionHash: txHash
37451
+ };
37452
+ } catch (error) {
37453
+ if (error instanceof SchemaValidationError) {
37454
+ throw error;
37455
+ }
37456
+ throw new Error(
37457
+ `Schema creation failed: ${error instanceof Error ? error.message : "Unknown error"}`
37458
+ );
37459
+ }
37460
+ }
37461
+ /**
37462
+ * Retrieves a schema by its ID.
37463
+ *
37464
+ * @param schemaId - The ID of the schema to retrieve
37465
+ * @returns Promise resolving to the schema object
37466
+ * @throws {Error} When the schema is not found or chain is unavailable
37467
+ * @example
37468
+ * ```typescript
37469
+ * const schema = await vana.schemas.get(1);
37470
+ * console.log(`Schema: ${schema.name} (${schema.type})`);
37471
+ * ```
37472
+ */
37473
+ async get(schemaId) {
37474
+ try {
37475
+ const chainId = this.context.walletClient.chain?.id;
37476
+ if (!chainId) {
37477
+ throw new Error("Chain ID not available");
37478
+ }
37479
+ const dataRefinerRegistryAddress = getContractAddress(
37480
+ chainId,
37481
+ "DataRefinerRegistry"
37482
+ );
37483
+ const dataRefinerRegistryAbi = getAbi("DataRefinerRegistry");
37484
+ const dataRefinerRegistry = getContract2({
37485
+ address: dataRefinerRegistryAddress,
37486
+ abi: dataRefinerRegistryAbi,
37487
+ client: this.context.publicClient
37488
+ });
37489
+ const schemaData = await dataRefinerRegistry.read.schemas([
37490
+ BigInt(schemaId)
37491
+ ]);
37492
+ if (!schemaData) {
37493
+ throw new Error(`Schema with ID ${schemaId} not found`);
37494
+ }
37495
+ const schemaObj = schemaData;
37496
+ if (!schemaObj.name || !schemaObj.typ || !schemaObj.definitionUrl) {
37497
+ throw new Error("Incomplete schema data");
37498
+ }
37499
+ return {
37500
+ id: schemaId,
37501
+ name: schemaObj.name,
37502
+ type: schemaObj.typ,
37503
+ definitionUrl: schemaObj.definitionUrl
37504
+ };
37505
+ } catch (error) {
37506
+ throw new Error(
37507
+ `Failed to get schema: ${error instanceof Error ? error.message : "Unknown error"}`
37508
+ );
37509
+ }
37510
+ }
37511
+ /**
37512
+ * Gets the total number of schemas registered on the network.
37513
+ *
37514
+ * @returns Promise resolving to the total schema count
37515
+ * @throws {Error} When the count cannot be retrieved
37516
+ * @example
37517
+ * ```typescript
37518
+ * const count = await vana.schemas.count();
37519
+ * console.log(`Total schemas: ${count}`);
37520
+ * ```
37521
+ */
37522
+ async count() {
37523
+ try {
37524
+ const chainId = this.context.walletClient.chain?.id;
37525
+ if (!chainId) {
37526
+ throw new Error("Chain ID not available");
37527
+ }
37528
+ const dataRefinerRegistryAddress = getContractAddress(
37529
+ chainId,
37530
+ "DataRefinerRegistry"
37531
+ );
37532
+ const dataRefinerRegistryAbi = getAbi("DataRefinerRegistry");
37533
+ const dataRefinerRegistry = getContract2({
37534
+ address: dataRefinerRegistryAddress,
37535
+ abi: dataRefinerRegistryAbi,
37536
+ client: this.context.publicClient
37537
+ });
37538
+ const count = await dataRefinerRegistry.read.schemasCount();
37539
+ return Number(count);
37540
+ } catch (error) {
37541
+ throw new Error(
37542
+ `Failed to get schemas count: ${error instanceof Error ? error.message : "Unknown error"}`
37543
+ );
37544
+ }
37545
+ }
37546
+ /**
37547
+ * Lists all schemas with pagination.
37548
+ *
37549
+ * @param options - Optional parameters for listing schemas
37550
+ * @param options.limit - Maximum number of schemas to return
37551
+ * @param options.offset - Number of schemas to skip
37552
+ * @returns Promise resolving to an array of schemas
37553
+ * @example
37554
+ * ```typescript
37555
+ * // Get all schemas
37556
+ * const schemas = await vana.schemas.list();
37557
+ *
37558
+ * // Get schemas with pagination
37559
+ * const schemas = await vana.schemas.list({ limit: 10, offset: 0 });
37560
+ * ```
37561
+ */
37562
+ async list(options = {}) {
37563
+ const { limit = 100, offset = 0 } = options;
37564
+ try {
37565
+ const totalCount = await this.count();
37566
+ const schemas = [];
37567
+ const start = offset;
37568
+ const end = Math.min(start + limit, totalCount);
37569
+ for (let i = start; i < end; i++) {
37570
+ try {
37571
+ const schema = await this.get(i + 1);
37572
+ schemas.push(schema);
37573
+ } catch (error) {
37574
+ console.warn(`Failed to retrieve schema ${i + 1}:`, error);
37575
+ }
37576
+ }
37577
+ return schemas;
37578
+ } catch (error) {
37579
+ throw new Error(
37580
+ `Failed to list schemas: ${error instanceof Error ? error.message : "Unknown error"}`
37581
+ );
37582
+ }
37583
+ }
37584
+ /**
37585
+ * Adds a schema using the legacy method (low-level API).
37586
+ *
37587
+ * @deprecated Use create() instead for the high-level API with automatic IPFS upload
37588
+ * @param params - Schema parameters including pre-generated definition URL
37589
+ * @returns Promise resolving to the add schema result
37590
+ */
37591
+ async addSchema(params) {
37592
+ try {
37593
+ const chainId = this.context.walletClient.chain?.id;
37594
+ if (!chainId) {
37595
+ throw new Error("Chain ID not available");
37596
+ }
37597
+ const dataRefinerRegistryAddress = getContractAddress(
37598
+ chainId,
37599
+ "DataRefinerRegistry"
37600
+ );
37601
+ const dataRefinerRegistryAbi = getAbi("DataRefinerRegistry");
37602
+ const userAddress = await this.getUserAddress();
37603
+ const txHash = await this.context.walletClient.writeContract({
37604
+ address: dataRefinerRegistryAddress,
37605
+ abi: dataRefinerRegistryAbi,
37606
+ functionName: "addSchema",
37607
+ args: [params.name, params.type, params.definitionUrl],
37608
+ account: this.context.walletClient.account || userAddress,
37609
+ chain: this.context.walletClient.chain || null
37610
+ });
37611
+ return {
37612
+ schemaId: 0,
37613
+ // TODO: Parse from transaction receipt
37614
+ transactionHash: txHash
37615
+ };
37616
+ } catch (error) {
37617
+ throw new Error(
37618
+ `Failed to add schema: ${error instanceof Error ? error.message : "Unknown error"}`
37619
+ );
37620
+ }
37621
+ }
37622
+ /**
37623
+ * Gets the user's wallet address.
37624
+ *
37625
+ * @private
37626
+ * @returns Promise resolving to the user's address
37627
+ */
37628
+ async getUserAddress() {
37629
+ if (!this.context.walletClient.account) {
37630
+ throw new Error("No wallet account connected");
37631
+ }
37632
+ if (typeof this.context.walletClient.account === "string") {
37633
+ return this.context.walletClient.account;
37634
+ }
37635
+ if (typeof this.context.walletClient.account === "object" && this.context.walletClient.account.address) {
37636
+ return this.context.walletClient.account.address;
37637
+ }
37638
+ throw new Error("Unable to determine wallet address");
37639
+ }
37640
+ };
37641
+
37642
+ // src/controllers/server.ts
37643
+ var ServerController = class {
37644
+ constructor(context) {
37645
+ this.context = context;
37646
+ __publicField(this, "PERSONAL_SERVER_BASE_URL", process.env.NEXT_PUBLIC_PERSONAL_SERVER_BASE_URL);
37647
+ }
37648
+ async getIdentity(request) {
37649
+ try {
37650
+ const response = await fetch(
37651
+ `${this.PERSONAL_SERVER_BASE_URL}/identity?address=${request.userAddress}`,
37652
+ {
37653
+ method: "GET",
37654
+ headers: {
37655
+ "Content-Type": "application/json"
37656
+ }
37657
+ }
37658
+ );
37659
+ console.debug("\u{1F50D} Debug - getIdentity response", response);
37660
+ if (!response.ok) {
37661
+ const errorText = await response.text();
37662
+ throw new NetworkError(
37663
+ `Local identity API request failed: ${response.status} ${response.statusText} - ${errorText}`
37664
+ );
37665
+ }
37666
+ const serverResponse = await response.json();
37667
+ return {
37668
+ kind: serverResponse.personal_server.kind,
37669
+ address: serverResponse.personal_server.address,
37670
+ public_key: serverResponse.personal_server.public_key,
37671
+ base_url: this.PERSONAL_SERVER_BASE_URL || "",
37672
+ name: "Hosted Vana Server"
37673
+ };
37674
+ } catch (error) {
37675
+ if (error instanceof NetworkError || error instanceof PersonalServerError) {
37676
+ throw error;
37677
+ }
37678
+ throw new PersonalServerError(
37679
+ `Failed to get personal server identity: ${error instanceof Error ? error.message : "Unknown error"}`
37680
+ );
37681
+ }
37682
+ }
37683
+ /**
37684
+ * Creates an operation via the personal server API.
37685
+ *
37686
+ * @remarks
37687
+ * This method submits a computation request to the personal server API.
37688
+ * The response includes the operation ID.
37689
+ * @param params - The request parameters object
37690
+ * @param params.permissionId - The permission ID authorizing this operation
37691
+ * @returns A Promise that resolves to an operation response with status and control URLs
37692
+ * @throws {PersonalServerError} When server request fails or parameters are invalid
37693
+ * @throws {NetworkError} When personal server API communication fails
37694
+ * @example
37695
+ * ```typescript
37696
+ * const response = await vana.server.createOperation({
37697
+ * permissionId: 123,
37698
+ * });
37699
+ *
37700
+ * console.log(`Operation created: ${response.id}`);
37701
+ * ```
37702
+ */
37703
+ async createOperation(params) {
37704
+ try {
37705
+ const requestData = {
37706
+ permission_id: params.permissionId
37707
+ };
37708
+ const requestJson = JSON.stringify(requestData);
37709
+ const signature = await this.createSignature(requestJson);
37710
+ const requestBody = {
37711
+ app_signature: signature,
37712
+ operation_request_json: requestJson
37713
+ };
37714
+ console.debug("\u{1F50D} Debug - createOperation requestBody", requestBody);
37715
+ const response = await this.makeRequest(requestBody);
37716
+ return response;
37717
+ } catch (error) {
37718
+ if (error instanceof Error) {
37719
+ if (error instanceof NetworkError || error instanceof SerializationError || error instanceof SignatureError || error instanceof PersonalServerError) {
37720
+ throw error;
37721
+ }
37722
+ throw new PersonalServerError(
37723
+ `Personal server operation creation failed: ${error.message}`,
37724
+ error
37725
+ );
37726
+ }
37727
+ throw new PersonalServerError(
37728
+ "Personal server operation creation failed with unknown error"
37729
+ );
37730
+ }
37731
+ }
37732
+ /**
37733
+ * Polls the status of a computation request for updates and results.
37734
+ *
37735
+ * @remarks
37736
+ * This method checks the current status of a computation request by querying
37737
+ * the personal server API using the provided operation ID. It returns the current
37738
+ * status, any available output, and error information. The method can be
37739
+ * called periodically until the operation completes or fails.
37740
+ *
37741
+ * Common status values include: `starting`, `processing`, `succeeded`, `failed`, `canceled`.
37742
+ * @param operationId - The operation ID returned from the initial request submission
37743
+ * @returns A Promise that resolves to the current operation response with status and results
37744
+ * @throws {NetworkError} When the polling request fails or returns invalid data
37745
+ * @example
37746
+ * ```typescript
37747
+ * // Poll until completion
37748
+ * let result = await vana.server.getOperation(response.id);
37749
+ *
37750
+ * while (result.status === "processing") {
37751
+ * await new Promise(resolve => setTimeout(resolve, 1000));
37752
+ * result = await vana.server.getOperation(response.id);
37753
+ * }
37754
+ *
37755
+ * if (result.status === "succeeded") {
37756
+ * console.log("Computation completed:", result.output);
37757
+ * }
37758
+ * ```
37759
+ */
37760
+ async getOperation(operationId) {
37761
+ try {
37762
+ console.debug("Polling Operation Status:", operationId);
37763
+ const response = await fetch(
37764
+ `${this.PERSONAL_SERVER_BASE_URL}/operations/${operationId}`,
37765
+ {
37766
+ method: "GET",
37767
+ headers: {
37768
+ "Content-Type": "application/json"
37769
+ }
37770
+ }
37771
+ );
37772
+ if (!response.ok) {
37773
+ const errorText = await response.text();
37774
+ console.debug("Polling Error Response:", {
37775
+ status: response.status,
37776
+ statusText: response.statusText,
37777
+ error: errorText
37778
+ });
37779
+ throw new NetworkError(
37780
+ `Status polling failed: ${response.status} ${response.statusText} - ${errorText}`
37781
+ );
37782
+ }
37783
+ const data = await response.json();
37784
+ console.debug("Polling Success Response:", data);
37785
+ return data;
37786
+ } catch (error) {
37787
+ if (error instanceof NetworkError) {
37788
+ throw error;
37789
+ }
37790
+ throw new NetworkError(
37791
+ `Failed to poll status: ${error instanceof Error ? error.message : "Unknown error"}`
37792
+ );
37793
+ }
37794
+ }
37795
+ async cancelOperation(operationId) {
37796
+ try {
37797
+ const response = await fetch(
37798
+ `${this.PERSONAL_SERVER_BASE_URL}/operations/${operationId}/cancel`,
37799
+ {
37800
+ method: "POST"
37801
+ }
37802
+ );
37803
+ if (!response.ok) {
37804
+ const errorText = await response.text();
37805
+ throw new PersonalServerError(
37806
+ `Failed to cancel operation: ${response.status} ${response.statusText} - ${errorText}`
37807
+ );
37808
+ }
37809
+ } catch (error) {
37810
+ if (error instanceof NetworkError) {
37811
+ throw error;
37812
+ }
37813
+ throw new NetworkError(
37814
+ `Failed to cancel operation: ${error instanceof Error ? error.message : "Unknown error"}`
37815
+ );
37816
+ }
37817
+ }
37818
+ /**
37819
+ * Makes the request to the personal server API.
37820
+ *
37821
+ * @param requestBody - The post request parameters to serialize
37822
+ * @returns JSON string representation of the request data
37823
+ */
37824
+ async makeRequest(requestBody) {
37825
+ try {
37826
+ console.debug("Personal Server Request:", {
37827
+ url: `${this.PERSONAL_SERVER_BASE_URL}/operations`,
37828
+ method: "POST",
37829
+ headers: {
37830
+ "Content-Type": "application/json"
37831
+ },
37832
+ body: requestBody
37833
+ });
37834
+ const response = await fetch(
37835
+ `${this.PERSONAL_SERVER_BASE_URL}/operations`,
37836
+ {
37837
+ method: "POST",
37838
+ headers: {
37839
+ "Content-Type": "application/json"
37840
+ },
37841
+ body: JSON.stringify(requestBody)
37842
+ }
37843
+ );
37844
+ if (!response.ok) {
37845
+ const errorText = await response.text();
37846
+ console.debug("Personal Server Error Response:", {
37847
+ status: response.status,
37848
+ statusText: response.statusText,
37849
+ error: errorText
37850
+ });
37851
+ throw new NetworkError(
37852
+ `Personal server API request failed: ${response.status} ${response.statusText} - ${errorText}`
37853
+ );
37854
+ }
37855
+ const data = await response.json();
37856
+ console.debug("Personal Server Success Response:", data);
37857
+ return data;
37858
+ } catch (error) {
37859
+ if (error instanceof NetworkError) {
37860
+ throw error;
37861
+ }
37862
+ throw new NetworkError(
37863
+ `Failed to make personal server API request: ${error instanceof Error ? error.message : "Unknown error"}`
37864
+ );
37865
+ }
37866
+ }
37867
+ /**
37868
+ * Creates a signature for the request JSON.
37869
+ *
37870
+ * @param requestJson - The JSON string to sign
37871
+ * @returns Promise resolving to the cryptographic signature
37872
+ */
37873
+ async createSignature(requestJson) {
37874
+ try {
37875
+ console.debug("\u{1F50D} Debug - createSignature", requestJson);
37876
+ const client = this.context.applicationClient || this.context.walletClient;
37877
+ const account = client.account;
37878
+ if (!account) {
37879
+ throw new SignatureError("No account available for signing");
37880
+ }
37881
+ if (account.type !== "local") {
37882
+ throw new SignatureError(
37883
+ "Only local accounts are supported for signing"
37884
+ );
37885
+ }
37886
+ console.debug("\u{1F50D} Debug - createSignature account", account);
37887
+ const signature = await account.signMessage({
37888
+ message: requestJson
37889
+ });
37890
+ return signature;
37891
+ } catch (error) {
37892
+ if (error instanceof Error && error.message.includes("User rejected")) {
37893
+ throw new SignatureError("User rejected the signature request");
37894
+ }
37895
+ throw new SignatureError(
37896
+ `Failed to create signature: ${error instanceof Error ? error.message : "Unknown error"}`
37897
+ );
37898
+ }
37899
+ }
37900
+ };
37901
+
37686
37902
  // src/contracts/contractController.ts
37687
37903
  import {
37688
- getContract as getContract2
37904
+ getContract as getContract3
37689
37905
  } from "viem";
37690
37906
 
37691
37907
  // src/core/client.ts
@@ -37786,7 +38002,7 @@ function getContractController(contract, client = createClient()) {
37786
38002
  const cacheKey = createCacheKey(contract, chainId);
37787
38003
  let controller = contractCache.get(cacheKey);
37788
38004
  if (!controller) {
37789
- controller = getContract2({
38005
+ controller = getContract3({
37790
38006
  address: getContractAddress(chainId, contract),
37791
38007
  abi: getAbi(contract),
37792
38008
  client
@@ -39445,7 +39661,7 @@ var moksha = {
39445
39661
  url: "https://moksha.vanascan.io"
39446
39662
  }
39447
39663
  },
39448
- subgraphUrl: "https://api.goldsky.com/api/public/project_cm168cz887zva010j39il7a6p/subgraphs/moksha/7.0.4/gn"
39664
+ subgraphUrl: "https://api.goldsky.com/api/public/project_cm168cz887zva010j39il7a6p/subgraphs/moksha/7.0.3/gn"
39449
39665
  };
39450
39666
  function getChainConfig(chainId) {
39451
39667
  switch (chainId) {
@@ -39457,11 +39673,53 @@ function getChainConfig(chainId) {
39457
39673
  return void 0;
39458
39674
  }
39459
39675
  }
39676
+ var mokshaTestnet2 = moksha;
39460
39677
  function getAllChains() {
39461
39678
  return [vanaMainnet2, moksha];
39462
39679
  }
39463
39680
 
39464
39681
  // src/core.ts
39682
+ var VanaCoreFactory = class {
39683
+ /**
39684
+ * Creates a VanaCore instance that enforces storage requirements at compile time.
39685
+ * Use this factory when you know you'll need storage-dependent operations.
39686
+ *
39687
+ * @param platform - The platform adapter for environment-specific operations
39688
+ * @param config - Configuration that includes required storage providers
39689
+ * @returns VanaCore instance with storage validation
39690
+ * @example
39691
+ * ```typescript
39692
+ * const vanaCore = VanaCoreFactory.createWithStorage(platformAdapter, {
39693
+ * walletClient: myWalletClient,
39694
+ * storage: {
39695
+ * providers: { ipfs: new IPFSStorage() },
39696
+ * defaultProvider: 'ipfs'
39697
+ * }
39698
+ * });
39699
+ * ```
39700
+ */
39701
+ static createWithStorage(platform, config) {
39702
+ const core = new VanaCore(platform, config);
39703
+ return core;
39704
+ }
39705
+ /**
39706
+ * Creates a VanaCore instance without storage requirements.
39707
+ * Storage-dependent operations will fail at runtime if not configured.
39708
+ *
39709
+ * @param platform - The platform adapter for environment-specific operations
39710
+ * @param config - Basic configuration without required storage
39711
+ * @returns VanaCore instance
39712
+ * @example
39713
+ * ```typescript
39714
+ * const vanaCore = VanaCoreFactory.create(platformAdapter, {
39715
+ * walletClient: myWalletClient
39716
+ * });
39717
+ * ```
39718
+ */
39719
+ static create(platform, config) {
39720
+ return new VanaCore(platform, config);
39721
+ }
39722
+ };
39465
39723
  var VanaCore = class {
39466
39724
  /**
39467
39725
  * Initializes a new VanaCore client instance with the provided configuration.
@@ -39469,6 +39727,10 @@ var VanaCore = class {
39469
39727
  * @remarks
39470
39728
  * The constructor validates the configuration, initializes storage providers if configured,
39471
39729
  * creates wallet and public clients, and sets up all SDK controllers with shared context.
39730
+ *
39731
+ * IMPORTANT: This constructor will validate storage requirements at runtime to fail fast.
39732
+ * Methods that require storage will throw runtime errors if storage is not configured.
39733
+ *
39472
39734
  * @param platform - The platform adapter for environment-specific operations
39473
39735
  * @param config - The configuration object specifying wallet or chain settings
39474
39736
  * @throws {InvalidConfigurationError} When the configuration is invalid or incomplete
@@ -39483,8 +39745,10 @@ var VanaCore = class {
39483
39745
  constructor(platform, config) {
39484
39746
  /** Manages gasless data access permissions and trusted server registry. */
39485
39747
  __publicField(this, "permissions");
39486
- /** Handles user data file operations and schema management. */
39748
+ /** Handles user data file operations. */
39487
39749
  __publicField(this, "data");
39750
+ /** Manages data schemas and refiners. */
39751
+ __publicField(this, "schemas");
39488
39752
  /** Provides personal server setup and trusted server interactions. */
39489
39753
  __publicField(this, "server");
39490
39754
  /** Offers low-level access to Vana protocol smart contracts. */
@@ -39493,9 +39757,13 @@ var VanaCore = class {
39493
39757
  __publicField(this, "platform");
39494
39758
  __publicField(this, "relayerCallbacks");
39495
39759
  __publicField(this, "storageManager");
39760
+ __publicField(this, "hasRequiredStorage");
39761
+ __publicField(this, "ipfsGateways");
39496
39762
  this.platform = platform;
39497
39763
  this.validateConfig(config);
39498
39764
  this.relayerCallbacks = config.relayerCallbacks;
39765
+ this.ipfsGateways = config.ipfsGateways;
39766
+ this.hasRequiredStorage = hasStorageConfig(config);
39499
39767
  if (config.storage?.providers) {
39500
39768
  this.storageManager = new StorageManager();
39501
39769
  for (const [name, provider] of Object.entries(config.storage.providers)) {
@@ -39550,14 +39818,70 @@ var VanaCore = class {
39550
39818
  relayerCallbacks: this.relayerCallbacks,
39551
39819
  storageManager: this.storageManager,
39552
39820
  subgraphUrl,
39553
- platform: this.platform
39821
+ platform: this.platform,
39554
39822
  // Pass the platform adapter to controllers
39823
+ validateStorageRequired: this.validateStorageRequired.bind(this),
39824
+ hasStorage: this.hasStorage.bind(this),
39825
+ ipfsGateways: this.ipfsGateways
39555
39826
  };
39556
39827
  this.permissions = new PermissionsController(sharedContext);
39557
39828
  this.data = new DataController(sharedContext);
39829
+ this.schemas = new SchemaController(sharedContext);
39558
39830
  this.server = new ServerController(sharedContext);
39559
39831
  this.protocol = new ProtocolController(sharedContext);
39560
39832
  }
39833
+ /**
39834
+ * Validates that storage is available for storage-dependent operations.
39835
+ * This method enforces the fail-fast principle by checking storage availability
39836
+ * at method call time rather than during expensive operations.
39837
+ *
39838
+ * @throws {InvalidConfigurationError} When storage is required but not configured
39839
+ * @example
39840
+ * ```typescript
39841
+ * // This will throw if storage is not configured
39842
+ * vana.validateStorageRequired();
39843
+ * await vana.data.uploadFile(file); // Safe to proceed
39844
+ * ```
39845
+ */
39846
+ validateStorageRequired() {
39847
+ if (!this.hasRequiredStorage) {
39848
+ throw new InvalidConfigurationError(
39849
+ "Storage configuration is required for this operation. Please configure storage providers in VanaConfig.storage, provide a relayerCallbacks.storeGrantFile implementation, or pass pre-stored URLs to avoid this dependency. \n\nFor better type safety, consider using VanaCoreFactory.createWithStorage() with VanaConfigWithStorage to catch this error at compile time."
39850
+ );
39851
+ }
39852
+ }
39853
+ /**
39854
+ * Checks whether storage is configured without throwing an error.
39855
+ *
39856
+ * @returns True if storage is properly configured
39857
+ * @example
39858
+ * ```typescript
39859
+ * if (vana.hasStorage()) {
39860
+ * await vana.data.uploadFile(file);
39861
+ * } else {
39862
+ * console.warn('Storage not configured - using pre-stored URLs only');
39863
+ * }
39864
+ * ```
39865
+ */
39866
+ hasStorage() {
39867
+ return this.hasRequiredStorage;
39868
+ }
39869
+ /**
39870
+ * Type guard to check if this instance has storage enabled at compile time.
39871
+ * Use this when you need TypeScript to understand that storage is available.
39872
+ *
39873
+ * @returns True if storage is configured, with type narrowing
39874
+ * @example
39875
+ * ```typescript
39876
+ * if (vana.isStorageEnabled()) {
39877
+ * // TypeScript knows storage is available here
39878
+ * await vana.data.uploadFile(file);
39879
+ * }
39880
+ * ```
39881
+ */
39882
+ isStorageEnabled() {
39883
+ return this.hasRequiredStorage;
39884
+ }
39561
39885
  /**
39562
39886
  * Validates the provided configuration object against all requirements.
39563
39887
  *
@@ -39746,23 +40070,23 @@ var VanaCore = class {
39746
40070
  return this.platform;
39747
40071
  }
39748
40072
  /**
39749
- * Encrypts user data using the Vana protocol standard encryption.
40073
+ * Encrypts data using the Vana protocol standard encryption.
39750
40074
  * This method automatically uses the correct platform adapter for the current environment.
39751
40075
  *
39752
40076
  * @param data The data to encrypt (string or Blob)
39753
- * @param walletSignature The wallet signature to use as encryption key
40077
+ * @param key The key to use as encryption key
39754
40078
  * @returns The encrypted data as Blob
39755
40079
  * @example
39756
40080
  * ```typescript
39757
40081
  * const encryptionKey = await generateEncryptionKey(walletClient);
39758
- * const encrypted = await vana.encryptUserData("sensitive data", encryptionKey);
40082
+ * const encrypted = await vana.encryptBlob("sensitive data", encryptionKey);
39759
40083
  * ```
39760
40084
  */
39761
- async encryptUserData(data, walletSignature) {
39762
- return encryptUserData(data, walletSignature, this.platform);
40085
+ async encryptBlob(data, key) {
40086
+ return encryptBlobWithSignedKey(data, key, this.platform);
39763
40087
  }
39764
40088
  /**
39765
- * Decrypts user data using the Vana protocol standard decryption.
40089
+ * Decrypts data that was encrypted using the Vana protocol.
39766
40090
  * This method automatically uses the correct platform adapter for the current environment.
39767
40091
  *
39768
40092
  * @param encryptedData The encrypted data (string or Blob)
@@ -39771,12 +40095,16 @@ var VanaCore = class {
39771
40095
  * @example
39772
40096
  * ```typescript
39773
40097
  * const encryptionKey = await generateEncryptionKey(walletClient);
39774
- * const decrypted = await vana.decryptUserData(encryptedData, encryptionKey);
40098
+ * const decrypted = await vana.decryptBlob(encryptedData, encryptionKey);
39775
40099
  * const text = await decrypted.text();
39776
40100
  * ```
39777
40101
  */
39778
- async decryptUserData(encryptedData, walletSignature) {
39779
- return decryptUserData(encryptedData, walletSignature, this.platform);
40102
+ async decryptBlob(encryptedData, walletSignature) {
40103
+ return decryptBlobWithSignedKey(
40104
+ encryptedData,
40105
+ walletSignature,
40106
+ this.platform
40107
+ );
39780
40108
  }
39781
40109
  };
39782
40110
 
@@ -39807,7 +40135,7 @@ function createValidatedGrant(params) {
39807
40135
  try {
39808
40136
  validateGrant(grantFile, {
39809
40137
  schema: true,
39810
- grantee: params.to,
40138
+ grantee: params.grantee,
39811
40139
  operation: params.operation
39812
40140
  });
39813
40141
  } catch (error) {
@@ -40564,25 +40892,15 @@ var ApiClient = class {
40564
40892
  };
40565
40893
 
40566
40894
  // src/index.browser.ts
40567
- var VanaBrowser = class extends VanaCore {
40568
- /**
40569
- * Creates a Vana SDK instance configured for browser environments.
40570
- *
40571
- * @param config - SDK configuration object (wallet client or chain config)
40572
- * @example
40573
- * ```typescript
40574
- * // With wallet client
40575
- * const vana = new Vana({ walletClient });
40576
- *
40577
- * // With chain configuration
40578
- * const vana = new Vana({ chainId: 14800, account });
40579
- * ```
40580
- */
40895
+ var VanaBrowserImpl = class extends VanaCore {
40581
40896
  constructor(config) {
40582
40897
  super(new BrowserPlatformAdapter(), config);
40583
40898
  }
40584
40899
  };
40585
- var index_browser_default = VanaBrowser;
40900
+ function Vana(config) {
40901
+ return new VanaBrowserImpl(config);
40902
+ }
40903
+ var index_browser_default = Vana;
40586
40904
  export {
40587
40905
  ApiClient,
40588
40906
  AsyncQueue,
@@ -40627,8 +40945,10 @@ export {
40627
40945
  StorageError,
40628
40946
  StorageManager,
40629
40947
  UserRejectedRequestError,
40630
- VanaBrowser as Vana,
40631
- VanaBrowser,
40948
+ Vana,
40949
+ VanaBrowserImpl,
40950
+ VanaCore,
40951
+ VanaCoreFactory,
40632
40952
  VanaError,
40633
40953
  __contractCache,
40634
40954
  chains,
@@ -40641,13 +40961,13 @@ export {
40641
40961
  createGrantFile,
40642
40962
  createPlatformAdapterSafe,
40643
40963
  createValidatedGrant,
40644
- decryptUserData,
40964
+ decryptBlobWithSignedKey,
40645
40965
  decryptWithPrivateKey,
40646
40966
  decryptWithWalletPrivateKey,
40647
40967
  index_browser_default as default,
40648
40968
  detectPlatform,
40969
+ encryptBlobWithSignedKey,
40649
40970
  encryptFileKey,
40650
- encryptUserData,
40651
40971
  encryptWithWalletPublicKey,
40652
40972
  extractIpfsHash,
40653
40973
  fetchAndValidateSchema,
@@ -40671,13 +40991,11 @@ export {
40671
40991
  getPlatformCapabilities,
40672
40992
  isAPIResponse,
40673
40993
  isGrantExpired,
40674
- isIdentityServerOutput,
40675
40994
  isIpfsUrl,
40676
- isPersonalServerOutput,
40677
40995
  isPlatformSupported,
40678
40996
  isReplicateAPIResponse,
40679
40997
  moksha,
40680
- mokshaTestnet,
40998
+ mokshaTestnet2 as mokshaTestnet,
40681
40999
  parseReplicateOutput,
40682
41000
  retrieveAndValidateGrant,
40683
41001
  retrieveGrantFile,
@@ -40693,6 +41011,6 @@ export {
40693
41011
  validateGrantFile,
40694
41012
  validateGranteeAccess,
40695
41013
  validateOperationAccess,
40696
- vanaMainnet
41014
+ vanaMainnet2 as vanaMainnet
40697
41015
  };
40698
41016
  //# sourceMappingURL=index.browser.js.map