@opendatalabs/vana-sdk 0.1.0-alpha.793d5ba → 0.1.0-alpha.8eb4e46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/chains.browser.cjs.map +1 -1
- package/dist/chains.browser.js.map +1 -1
- package/dist/chains.cjs.map +1 -1
- package/dist/chains.js.map +1 -1
- package/dist/chains.node.cjs.map +1 -1
- package/dist/chains.node.js.map +1 -1
- package/dist/index.browser.d.ts +986 -272
- package/dist/index.browser.js +793 -586
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +797 -592
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.d.cts +987 -273
- package/dist/index.node.d.ts +987 -273
- package/dist/index.node.js +792 -586
- package/dist/index.node.js.map +1 -1
- package/dist/platform.browser.js +1 -57
- package/dist/platform.browser.js.map +1 -1
- package/dist/platform.cjs +1 -57
- package/dist/platform.cjs.map +1 -1
- package/dist/platform.js +1 -57
- package/dist/platform.js.map +1 -1
- package/dist/platform.node.cjs +1 -57
- package/dist/platform.node.cjs.map +1 -1
- package/dist/platform.node.js +1 -57
- package/dist/platform.node.js.map +1 -1
- package/package.json +10 -2
package/dist/index.browser.js
CHANGED
|
@@ -141,65 +141,9 @@ var init_browser = __esm({
|
|
|
141
141
|
try {
|
|
142
142
|
const eccrypto = await import("eccrypto-js");
|
|
143
143
|
const uncompressedKey = processWalletPublicKey(publicKey);
|
|
144
|
-
const iv = Buffer.from([
|
|
145
|
-
1,
|
|
146
|
-
2,
|
|
147
|
-
3,
|
|
148
|
-
4,
|
|
149
|
-
5,
|
|
150
|
-
6,
|
|
151
|
-
7,
|
|
152
|
-
8,
|
|
153
|
-
9,
|
|
154
|
-
10,
|
|
155
|
-
11,
|
|
156
|
-
12,
|
|
157
|
-
13,
|
|
158
|
-
14,
|
|
159
|
-
15,
|
|
160
|
-
16
|
|
161
|
-
]);
|
|
162
|
-
const ephemeralKey = Buffer.from([
|
|
163
|
-
17,
|
|
164
|
-
34,
|
|
165
|
-
51,
|
|
166
|
-
68,
|
|
167
|
-
85,
|
|
168
|
-
102,
|
|
169
|
-
119,
|
|
170
|
-
136,
|
|
171
|
-
153,
|
|
172
|
-
170,
|
|
173
|
-
187,
|
|
174
|
-
204,
|
|
175
|
-
221,
|
|
176
|
-
238,
|
|
177
|
-
255,
|
|
178
|
-
0,
|
|
179
|
-
16,
|
|
180
|
-
32,
|
|
181
|
-
48,
|
|
182
|
-
64,
|
|
183
|
-
80,
|
|
184
|
-
96,
|
|
185
|
-
112,
|
|
186
|
-
128,
|
|
187
|
-
144,
|
|
188
|
-
160,
|
|
189
|
-
176,
|
|
190
|
-
192,
|
|
191
|
-
208,
|
|
192
|
-
224,
|
|
193
|
-
240,
|
|
194
|
-
0
|
|
195
|
-
]);
|
|
196
144
|
const encryptedBuffer = await eccrypto.encrypt(
|
|
197
145
|
uncompressedKey,
|
|
198
|
-
Buffer.from(data)
|
|
199
|
-
{
|
|
200
|
-
iv,
|
|
201
|
-
ephemPrivateKey: ephemeralKey
|
|
202
|
-
}
|
|
146
|
+
Buffer.from(data)
|
|
203
147
|
);
|
|
204
148
|
const result = Buffer.concat([
|
|
205
149
|
encryptedBuffer.iv,
|
|
@@ -446,6 +390,9 @@ function isWalletConfig(config) {
|
|
|
446
390
|
function isChainConfig(config) {
|
|
447
391
|
return "chainId" in config && !("walletClient" in config);
|
|
448
392
|
}
|
|
393
|
+
function hasStorageConfig(config) {
|
|
394
|
+
return config.storage?.providers !== void 0 && Object.keys(config.storage.providers).length > 0;
|
|
395
|
+
}
|
|
449
396
|
|
|
450
397
|
// src/types/chains.ts
|
|
451
398
|
function isVanaChainId(chainId) {
|
|
@@ -741,55 +688,6 @@ function isReplicateAPIResponse(value) {
|
|
|
741
688
|
obj.status
|
|
742
689
|
);
|
|
743
690
|
}
|
|
744
|
-
function isIdentityServerOutput(value) {
|
|
745
|
-
console.debug("\u{1F50D} Type Guard: Checking value:", value);
|
|
746
|
-
console.debug("\u{1F50D} Type Guard: Value type:", typeof value);
|
|
747
|
-
if (typeof value !== "object" || value === null) {
|
|
748
|
-
console.debug("\u{1F50D} Type Guard: Failed - not object or null");
|
|
749
|
-
return false;
|
|
750
|
-
}
|
|
751
|
-
const obj = value;
|
|
752
|
-
console.debug("\u{1F50D} Type Guard: Object keys:", Object.keys(obj));
|
|
753
|
-
console.debug(
|
|
754
|
-
"\u{1F50D} Type Guard: user_address:",
|
|
755
|
-
obj.user_address,
|
|
756
|
-
typeof obj.user_address
|
|
757
|
-
);
|
|
758
|
-
if (typeof obj.user_address !== "string") {
|
|
759
|
-
console.debug("\u{1F50D} Type Guard: Failed - user_address not string");
|
|
760
|
-
return false;
|
|
761
|
-
}
|
|
762
|
-
console.debug(
|
|
763
|
-
"\u{1F50D} Type Guard: personal_server:",
|
|
764
|
-
obj.personal_server,
|
|
765
|
-
typeof obj.personal_server
|
|
766
|
-
);
|
|
767
|
-
if (typeof obj.personal_server !== "object" || obj.personal_server === null) {
|
|
768
|
-
console.debug("\u{1F50D} Type Guard: Failed - personal_server not object or null");
|
|
769
|
-
return false;
|
|
770
|
-
}
|
|
771
|
-
const personalServer = obj.personal_server;
|
|
772
|
-
console.debug(
|
|
773
|
-
"\u{1F50D} Type Guard: Personal server keys:",
|
|
774
|
-
Object.keys(personalServer)
|
|
775
|
-
);
|
|
776
|
-
console.debug("\u{1F50D} Type Guard: address:", personalServer.address);
|
|
777
|
-
console.debug("\u{1F50D} Type Guard: public_key:", personalServer.public_key);
|
|
778
|
-
const hasAddress = "address" in personalServer;
|
|
779
|
-
const hasPublicKey = "public_key" in personalServer;
|
|
780
|
-
console.debug(
|
|
781
|
-
"\u{1F50D} Type Guard: Has address:",
|
|
782
|
-
hasAddress,
|
|
783
|
-
"Has public_key:",
|
|
784
|
-
hasPublicKey
|
|
785
|
-
);
|
|
786
|
-
return hasAddress && hasPublicKey;
|
|
787
|
-
}
|
|
788
|
-
function isPersonalServerOutput(value) {
|
|
789
|
-
if (typeof value !== "object" || value === null) return false;
|
|
790
|
-
const obj = value;
|
|
791
|
-
return "user_address" in obj && "identity" in obj && typeof obj.user_address === "string" && typeof obj.identity === "object";
|
|
792
|
-
}
|
|
793
691
|
function isAPIResponse(value) {
|
|
794
692
|
if (typeof value !== "object" || value === null) return false;
|
|
795
693
|
const obj = value;
|
|
@@ -7820,6 +7718,12 @@ var DataRefinerRegistryABI = [
|
|
|
7820
7718
|
name: "schemaId",
|
|
7821
7719
|
type: "uint256"
|
|
7822
7720
|
},
|
|
7721
|
+
{
|
|
7722
|
+
indexed: false,
|
|
7723
|
+
internalType: "string",
|
|
7724
|
+
name: "schemaDefinitionUrl",
|
|
7725
|
+
type: "string"
|
|
7726
|
+
},
|
|
7823
7727
|
{
|
|
7824
7728
|
indexed: false,
|
|
7825
7729
|
internalType: "string",
|
|
@@ -7923,7 +7827,7 @@ var DataRefinerRegistryABI = [
|
|
|
7923
7827
|
{
|
|
7924
7828
|
indexed: false,
|
|
7925
7829
|
internalType: "string",
|
|
7926
|
-
name: "
|
|
7830
|
+
name: "dialect",
|
|
7927
7831
|
type: "string"
|
|
7928
7832
|
},
|
|
7929
7833
|
{
|
|
@@ -8019,6 +7923,40 @@ var DataRefinerRegistryABI = [
|
|
|
8019
7923
|
stateMutability: "nonpayable",
|
|
8020
7924
|
type: "function"
|
|
8021
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
|
+
},
|
|
8022
7960
|
{
|
|
8023
7961
|
inputs: [
|
|
8024
7962
|
{
|
|
@@ -8042,7 +7980,7 @@ var DataRefinerRegistryABI = [
|
|
|
8042
7980
|
type: "string"
|
|
8043
7981
|
}
|
|
8044
7982
|
],
|
|
8045
|
-
name: "
|
|
7983
|
+
name: "addRefinerWithSchemaId",
|
|
8046
7984
|
outputs: [
|
|
8047
7985
|
{
|
|
8048
7986
|
internalType: "uint256",
|
|
@@ -8062,7 +8000,7 @@ var DataRefinerRegistryABI = [
|
|
|
8062
8000
|
},
|
|
8063
8001
|
{
|
|
8064
8002
|
internalType: "string",
|
|
8065
|
-
name: "
|
|
8003
|
+
name: "dialect",
|
|
8066
8004
|
type: "string"
|
|
8067
8005
|
},
|
|
8068
8006
|
{
|
|
@@ -8425,7 +8363,7 @@ var DataRefinerRegistryABI = [
|
|
|
8425
8363
|
},
|
|
8426
8364
|
{
|
|
8427
8365
|
internalType: "string",
|
|
8428
|
-
name: "
|
|
8366
|
+
name: "dialect",
|
|
8429
8367
|
type: "string"
|
|
8430
8368
|
},
|
|
8431
8369
|
{
|
|
@@ -33342,7 +33280,7 @@ function getAbi(contract) {
|
|
|
33342
33280
|
import { keccak256, toHex } from "viem";
|
|
33343
33281
|
function createGrantFile(params) {
|
|
33344
33282
|
const grantFile = {
|
|
33345
|
-
grantee: params.
|
|
33283
|
+
grantee: params.grantee,
|
|
33346
33284
|
operation: params.operation,
|
|
33347
33285
|
parameters: params.parameters
|
|
33348
33286
|
};
|
|
@@ -33762,7 +33700,7 @@ var PermissionsController = class {
|
|
|
33762
33700
|
* @example
|
|
33763
33701
|
* ```typescript
|
|
33764
33702
|
* const txHash = await vana.permissions.grant({
|
|
33765
|
-
*
|
|
33703
|
+
* grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
33766
33704
|
* operation: "llm_inference",
|
|
33767
33705
|
* parameters: {
|
|
33768
33706
|
* model: "gpt-4",
|
|
@@ -33791,7 +33729,7 @@ var PermissionsController = class {
|
|
|
33791
33729
|
* @example
|
|
33792
33730
|
* ```typescript
|
|
33793
33731
|
* const { preview, confirm } = await vana.permissions.prepareGrant({
|
|
33794
|
-
*
|
|
33732
|
+
* grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
33795
33733
|
* operation: "llm_inference",
|
|
33796
33734
|
* files: [1, 2, 3],
|
|
33797
33735
|
* parameters: { model: "gpt-4", prompt: "Analyze my social media data" }
|
|
@@ -33840,9 +33778,13 @@ var PermissionsController = class {
|
|
|
33840
33778
|
console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
|
|
33841
33779
|
if (!grantUrl) {
|
|
33842
33780
|
if (!this.context.relayerCallbacks?.storeGrantFile && !this.context.storageManager) {
|
|
33843
|
-
|
|
33844
|
-
|
|
33845
|
-
|
|
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
|
+
}
|
|
33846
33788
|
}
|
|
33847
33789
|
if (this.context.relayerCallbacks?.storeGrantFile) {
|
|
33848
33790
|
grantUrl = await this.context.relayerCallbacks.storeGrantFile(grantFile);
|
|
@@ -33866,7 +33808,7 @@ var PermissionsController = class {
|
|
|
33866
33808
|
grantUrl
|
|
33867
33809
|
);
|
|
33868
33810
|
const typedData = await this.composePermissionGrantMessage({
|
|
33869
|
-
|
|
33811
|
+
grantee: params.grantee,
|
|
33870
33812
|
operation: params.operation,
|
|
33871
33813
|
// Placeholder - real data is in IPFS
|
|
33872
33814
|
files: params.files,
|
|
@@ -33913,7 +33855,7 @@ var PermissionsController = class {
|
|
|
33913
33855
|
* @example
|
|
33914
33856
|
* ```typescript
|
|
33915
33857
|
* const { typedData, signature } = await vana.permissions.createAndSign({
|
|
33916
|
-
*
|
|
33858
|
+
* grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
33917
33859
|
* operation: "data_analysis",
|
|
33918
33860
|
* parameters: { analysisType: "sentiment" },
|
|
33919
33861
|
* });
|
|
@@ -33929,9 +33871,13 @@ var PermissionsController = class {
|
|
|
33929
33871
|
console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
|
|
33930
33872
|
if (!grantUrl) {
|
|
33931
33873
|
if (!this.context.relayerCallbacks?.storeGrantFile && !this.context.storageManager) {
|
|
33932
|
-
|
|
33933
|
-
|
|
33934
|
-
|
|
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
|
+
}
|
|
33935
33881
|
}
|
|
33936
33882
|
if (this.context.relayerCallbacks?.storeGrantFile) {
|
|
33937
33883
|
grantUrl = await this.context.relayerCallbacks.storeGrantFile(grantFile);
|
|
@@ -33955,7 +33901,7 @@ var PermissionsController = class {
|
|
|
33955
33901
|
grantUrl
|
|
33956
33902
|
);
|
|
33957
33903
|
const typedData = await this.composePermissionGrantMessage({
|
|
33958
|
-
|
|
33904
|
+
grantee: params.grantee,
|
|
33959
33905
|
operation: params.operation,
|
|
33960
33906
|
// Placeholder - real data is in IPFS
|
|
33961
33907
|
files: params.files,
|
|
@@ -34306,7 +34252,7 @@ var PermissionsController = class {
|
|
|
34306
34252
|
* Composes the EIP-712 typed data for PermissionGrant (new simplified format).
|
|
34307
34253
|
*
|
|
34308
34254
|
* @param params - The parameters for composing the permission grant message
|
|
34309
|
-
* @param params.
|
|
34255
|
+
* @param params.grantee - The recipient address for the permission grant
|
|
34310
34256
|
* @param params.operation - The type of operation being granted permission for
|
|
34311
34257
|
* @param params.files - Array of file IDs that the permission applies to
|
|
34312
34258
|
* @param params.grantUrl - URL where the grant details are stored
|
|
@@ -34399,36 +34345,45 @@ var PermissionsController = class {
|
|
|
34399
34345
|
return addresses[0];
|
|
34400
34346
|
}
|
|
34401
34347
|
/**
|
|
34402
|
-
*
|
|
34348
|
+
* Gets on-chain permission grant data without expensive off-chain resolution.
|
|
34403
34349
|
*
|
|
34404
34350
|
* @remarks
|
|
34405
|
-
* This method
|
|
34406
|
-
*
|
|
34407
|
-
*
|
|
34408
|
-
*
|
|
34409
|
-
*
|
|
34410
|
-
*
|
|
34411
|
-
*
|
|
34412
|
-
*
|
|
34413
|
-
*
|
|
34414
|
-
*
|
|
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
|
|
34415
34366
|
* @example
|
|
34416
34367
|
* ```typescript
|
|
34417
|
-
* // Get all
|
|
34418
|
-
* const
|
|
34368
|
+
* // Fast: Get all on-chain permission data
|
|
34369
|
+
* const grants = await vana.permissions.getUserPermissionGrantsOnChain({ limit: 20 });
|
|
34419
34370
|
*
|
|
34420
|
-
*
|
|
34421
|
-
*
|
|
34371
|
+
* // Display in UI immediately
|
|
34372
|
+
* grants.forEach(grant => {
|
|
34373
|
+
* console.log(`Permission ${grant.id}: ${grant.grantUrl}`);
|
|
34422
34374
|
* });
|
|
34423
34375
|
*
|
|
34424
|
-
* //
|
|
34425
|
-
* const
|
|
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);
|
|
34426
34380
|
* ```
|
|
34427
34381
|
*/
|
|
34428
|
-
async
|
|
34382
|
+
async getUserPermissionGrantsOnChain(options = {}) {
|
|
34383
|
+
const { limit = 50, subgraphUrl } = options;
|
|
34429
34384
|
try {
|
|
34430
34385
|
const userAddress = await this.getUserAddress();
|
|
34431
|
-
const graphqlEndpoint =
|
|
34386
|
+
const graphqlEndpoint = subgraphUrl || this.context.subgraphUrl;
|
|
34432
34387
|
if (!graphqlEndpoint) {
|
|
34433
34388
|
throw new BlockchainError(
|
|
34434
34389
|
"subgraphUrl is required. Please provide a valid subgraph endpoint or configure it in Vana constructor."
|
|
@@ -34450,16 +34405,6 @@ var PermissionsController = class {
|
|
|
34450
34405
|
}
|
|
34451
34406
|
}
|
|
34452
34407
|
`;
|
|
34453
|
-
console.info("Query:", query);
|
|
34454
|
-
console.info(
|
|
34455
|
-
"Body:",
|
|
34456
|
-
JSON.stringify({
|
|
34457
|
-
query,
|
|
34458
|
-
variables: {
|
|
34459
|
-
userId: userAddress.toLowerCase()
|
|
34460
|
-
}
|
|
34461
|
-
})
|
|
34462
|
-
);
|
|
34463
34408
|
const response = await fetch(graphqlEndpoint, {
|
|
34464
34409
|
method: "POST",
|
|
34465
34410
|
headers: {
|
|
@@ -34478,7 +34423,6 @@ var PermissionsController = class {
|
|
|
34478
34423
|
);
|
|
34479
34424
|
}
|
|
34480
34425
|
const result = await response.json();
|
|
34481
|
-
console.info("Result:", result);
|
|
34482
34426
|
if (result.errors) {
|
|
34483
34427
|
throw new BlockchainError(
|
|
34484
34428
|
`Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
|
|
@@ -34486,64 +34430,32 @@ var PermissionsController = class {
|
|
|
34486
34430
|
}
|
|
34487
34431
|
const userData = result.data?.user;
|
|
34488
34432
|
if (!userData || !userData.permissions?.length) {
|
|
34489
|
-
console.warn("No permissions found for user:", userAddress);
|
|
34490
34433
|
return [];
|
|
34491
34434
|
}
|
|
34492
|
-
const
|
|
34493
|
-
|
|
34494
|
-
|
|
34495
|
-
|
|
34496
|
-
|
|
34497
|
-
|
|
34498
|
-
|
|
34499
|
-
|
|
34500
|
-
|
|
34501
|
-
|
|
34502
|
-
|
|
34503
|
-
|
|
34504
|
-
|
|
34505
|
-
|
|
34506
|
-
} catch {
|
|
34507
|
-
}
|
|
34508
|
-
try {
|
|
34509
|
-
const fileIds = await this.getPermissionFileIds(
|
|
34510
|
-
BigInt(permission.id)
|
|
34511
|
-
);
|
|
34512
|
-
files = fileIds.map((id) => Number(id));
|
|
34513
|
-
} catch {
|
|
34514
|
-
}
|
|
34515
|
-
userPermissions.push({
|
|
34516
|
-
id: BigInt(permission.id),
|
|
34517
|
-
files,
|
|
34518
|
-
operation: operation || "",
|
|
34519
|
-
parameters: parameters || {},
|
|
34520
|
-
grant: permission.grant,
|
|
34521
|
-
grantor: userAddress.toLowerCase(),
|
|
34522
|
-
// Current user is the grantor
|
|
34523
|
-
grantee: granteeAddress || userAddress,
|
|
34524
|
-
// Application that received permission
|
|
34525
|
-
active: true,
|
|
34526
|
-
// Default to active if not specified
|
|
34527
|
-
grantedAt: Number(permission.addedAtBlock),
|
|
34528
|
-
nonce: Number(permission.nonce)
|
|
34529
|
-
});
|
|
34530
|
-
} catch (error) {
|
|
34531
|
-
console.error(
|
|
34532
|
-
"SDK Error: Failed to process permission:",
|
|
34533
|
-
permission.id,
|
|
34534
|
-
error
|
|
34535
|
-
);
|
|
34536
|
-
}
|
|
34537
|
-
}
|
|
34538
|
-
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) => {
|
|
34539
34449
|
if (a.id < b.id) return 1;
|
|
34540
34450
|
if (a.id > b.id) return -1;
|
|
34541
34451
|
return 0;
|
|
34542
34452
|
});
|
|
34543
34453
|
} catch (error) {
|
|
34544
|
-
|
|
34454
|
+
if (error instanceof BlockchainError || error instanceof NetworkError) {
|
|
34455
|
+
throw error;
|
|
34456
|
+
}
|
|
34545
34457
|
throw new BlockchainError(
|
|
34546
|
-
`Failed to fetch user
|
|
34458
|
+
`Failed to fetch user permission grants: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
34547
34459
|
);
|
|
34548
34460
|
}
|
|
34549
34461
|
}
|
|
@@ -35305,32 +35217,19 @@ async function decryptWithPrivateKey(encryptedData, privateKey, platformAdapter)
|
|
|
35305
35217
|
throw new Error(`Failed to decrypt with private key: ${error}`);
|
|
35306
35218
|
}
|
|
35307
35219
|
}
|
|
35308
|
-
async function
|
|
35220
|
+
async function encryptBlobWithSignedKey(data, key, platformAdapter) {
|
|
35309
35221
|
try {
|
|
35310
35222
|
const dataBuffer = data instanceof Blob ? await data.arrayBuffer() : new TextEncoder().encode(data);
|
|
35311
35223
|
const dataArray = new Uint8Array(dataBuffer);
|
|
35312
35224
|
const encrypted = await platformAdapter.crypto.encryptWithPassword(
|
|
35313
35225
|
dataArray,
|
|
35314
|
-
|
|
35226
|
+
key
|
|
35315
35227
|
);
|
|
35316
35228
|
return new Blob([encrypted], {
|
|
35317
35229
|
type: "application/octet-stream"
|
|
35318
35230
|
});
|
|
35319
35231
|
} catch (error) {
|
|
35320
|
-
throw new Error(`Failed to encrypt
|
|
35321
|
-
}
|
|
35322
|
-
}
|
|
35323
|
-
async function decryptUserData(encryptedData, walletSignature, platformAdapter) {
|
|
35324
|
-
try {
|
|
35325
|
-
const encryptedBuffer = encryptedData instanceof Blob ? await encryptedData.arrayBuffer() : new TextEncoder().encode(encryptedData);
|
|
35326
|
-
const encryptedArray = new Uint8Array(encryptedBuffer);
|
|
35327
|
-
const decrypted = await platformAdapter.crypto.decryptWithPassword(
|
|
35328
|
-
encryptedArray,
|
|
35329
|
-
walletSignature
|
|
35330
|
-
);
|
|
35331
|
-
return new Blob([decrypted], { type: "text/plain" });
|
|
35332
|
-
} catch (error) {
|
|
35333
|
-
throw new Error(`Failed to decrypt user data: ${error}`);
|
|
35232
|
+
throw new Error(`Failed to encrypt data: ${error}`);
|
|
35334
35233
|
}
|
|
35335
35234
|
}
|
|
35336
35235
|
async function generateEncryptionKeyPair(platformAdapter) {
|
|
@@ -35347,60 +35246,25 @@ async function generatePGPKeyPair(platformAdapter, options) {
|
|
|
35347
35246
|
throw new Error(`Failed to generate PGP key pair: ${error}`);
|
|
35348
35247
|
}
|
|
35349
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
|
+
}
|
|
35350
35262
|
|
|
35351
35263
|
// src/controllers/data.ts
|
|
35352
35264
|
var DataController = class {
|
|
35353
35265
|
constructor(context) {
|
|
35354
35266
|
this.context = context;
|
|
35355
35267
|
}
|
|
35356
|
-
/**
|
|
35357
|
-
* Uploads user data with automatic encryption and blockchain registration.
|
|
35358
|
-
*
|
|
35359
|
-
* @remarks
|
|
35360
|
-
* This is the primary method for uploading user data to the Vana network. It handles
|
|
35361
|
-
* the complete workflow including content normalization, schema validation, encryption,
|
|
35362
|
-
* storage upload, permission granting, and blockchain registration.
|
|
35363
|
-
*
|
|
35364
|
-
* The method automatically:
|
|
35365
|
-
* - Normalizes input content to a Blob
|
|
35366
|
-
* - Validates data against schema if provided
|
|
35367
|
-
* - Generates encryption keys and encrypts the data
|
|
35368
|
-
* - Uploads to the configured storage provider
|
|
35369
|
-
* - Grants permissions to specified applications
|
|
35370
|
-
* - Registers the file on the blockchain
|
|
35371
|
-
*
|
|
35372
|
-
* @param params - Upload parameters including content, filename, schema, and permissions
|
|
35373
|
-
* @returns Promise resolving to upload results with file ID and transaction hash
|
|
35374
|
-
* @throws {Error} When wallet is not connected or storage is not configured
|
|
35375
|
-
* @throws {SchemaValidationError} When schema validation fails
|
|
35376
|
-
* @throws {Error} When upload or blockchain registration fails
|
|
35377
|
-
* @example
|
|
35378
|
-
* ```typescript
|
|
35379
|
-
* // Basic file upload
|
|
35380
|
-
* const result = await vana.data.upload({
|
|
35381
|
-
* content: "My personal data",
|
|
35382
|
-
* filename: "diary.txt"
|
|
35383
|
-
* });
|
|
35384
|
-
*
|
|
35385
|
-
* // Upload with schema validation
|
|
35386
|
-
* const result = await vana.data.upload({
|
|
35387
|
-
* content: { name: "John", age: 30 },
|
|
35388
|
-
* filename: "profile.json",
|
|
35389
|
-
* schemaId: 1
|
|
35390
|
-
* });
|
|
35391
|
-
*
|
|
35392
|
-
* // Upload with permissions
|
|
35393
|
-
* const result = await vana.data.upload({
|
|
35394
|
-
* content: "Data for AI analysis",
|
|
35395
|
-
* filename: "analysis.txt",
|
|
35396
|
-
* permissions: [{
|
|
35397
|
-
* to: "0x1234...",
|
|
35398
|
-
* operation: "llm_inference",
|
|
35399
|
-
* parameters: { model: "gpt-4" }
|
|
35400
|
-
* }]
|
|
35401
|
-
* });
|
|
35402
|
-
* ```
|
|
35403
|
-
*/
|
|
35404
35268
|
async upload(params) {
|
|
35405
35269
|
const {
|
|
35406
35270
|
content,
|
|
@@ -35408,7 +35272,8 @@ var DataController = class {
|
|
|
35408
35272
|
schemaId,
|
|
35409
35273
|
permissions = [],
|
|
35410
35274
|
encrypt: encrypt2 = true,
|
|
35411
|
-
providerName
|
|
35275
|
+
providerName,
|
|
35276
|
+
owner
|
|
35412
35277
|
} = params;
|
|
35413
35278
|
try {
|
|
35414
35279
|
let blob;
|
|
@@ -35465,84 +35330,88 @@ var DataController = class {
|
|
|
35465
35330
|
this.context.walletClient,
|
|
35466
35331
|
DEFAULT_ENCRYPTION_SEED
|
|
35467
35332
|
);
|
|
35468
|
-
finalBlob = await
|
|
35333
|
+
finalBlob = await encryptBlobWithSignedKey(
|
|
35469
35334
|
blob,
|
|
35470
35335
|
encryptionKey,
|
|
35471
35336
|
this.context.platform
|
|
35472
35337
|
);
|
|
35473
35338
|
}
|
|
35474
35339
|
if (!this.context.storageManager) {
|
|
35475
|
-
|
|
35476
|
-
|
|
35477
|
-
|
|
35340
|
+
if (this.context.validateStorageRequired) {
|
|
35341
|
+
this.context.validateStorageRequired();
|
|
35342
|
+
throw new Error("Storage validation failed");
|
|
35343
|
+
} else {
|
|
35344
|
+
throw new Error(
|
|
35345
|
+
"Storage manager not configured. Please provide storage providers in VanaConfig."
|
|
35346
|
+
);
|
|
35347
|
+
}
|
|
35478
35348
|
}
|
|
35479
35349
|
const uploadResult = await this.context.storageManager.upload(
|
|
35480
35350
|
finalBlob,
|
|
35481
35351
|
filename,
|
|
35482
35352
|
providerName
|
|
35483
35353
|
);
|
|
35484
|
-
|
|
35485
|
-
|
|
35486
|
-
if (permissions.length > 0) {
|
|
35487
|
-
|
|
35488
|
-
|
|
35354
|
+
const userAddress = owner || await this.getUserAddress();
|
|
35355
|
+
let encryptedPermissions = [];
|
|
35356
|
+
if (permissions.length > 0 && encrypt2) {
|
|
35357
|
+
const userEncryptionKey = await generateEncryptionKey(
|
|
35358
|
+
this.context.walletClient,
|
|
35359
|
+
DEFAULT_ENCRYPTION_SEED
|
|
35489
35360
|
);
|
|
35490
|
-
|
|
35491
|
-
|
|
35492
|
-
|
|
35493
|
-
|
|
35494
|
-
|
|
35495
|
-
|
|
35496
|
-
|
|
35497
|
-
let txHash;
|
|
35498
|
-
if (schemaId !== void 0) {
|
|
35499
|
-
txHash = await this.context.walletClient.writeContract({
|
|
35500
|
-
address: dataRegistryAddress,
|
|
35501
|
-
abi: dataRegistryAbi,
|
|
35502
|
-
functionName: "addFileWithSchema",
|
|
35503
|
-
args: [uploadResult.url, BigInt(schemaId)],
|
|
35504
|
-
account: this.context.walletClient.account || userAddress,
|
|
35505
|
-
chain: this.context.walletClient.chain || null
|
|
35506
|
-
});
|
|
35507
|
-
} else {
|
|
35508
|
-
txHash = await this.context.walletClient.writeContract({
|
|
35509
|
-
address: dataRegistryAddress,
|
|
35510
|
-
abi: dataRegistryAbi,
|
|
35511
|
-
functionName: "addFile",
|
|
35512
|
-
args: [uploadResult.url],
|
|
35513
|
-
account: this.context.walletClient.account || userAddress,
|
|
35514
|
-
chain: this.context.walletClient.chain || null
|
|
35515
|
-
});
|
|
35516
|
-
}
|
|
35517
|
-
const receipt = await this.context.publicClient.waitForTransactionReceipt({
|
|
35518
|
-
hash: txHash,
|
|
35519
|
-
timeout: 3e4
|
|
35520
|
-
// 30 seconds timeout
|
|
35521
|
-
});
|
|
35522
|
-
let fileId = 0;
|
|
35523
|
-
for (const log of receipt.logs) {
|
|
35524
|
-
try {
|
|
35525
|
-
const decoded = decodeEventLog({
|
|
35526
|
-
abi: dataRegistryAbi,
|
|
35527
|
-
data: log.data,
|
|
35528
|
-
topics: log.topics
|
|
35529
|
-
});
|
|
35530
|
-
if (decoded.eventName === "FileAdded") {
|
|
35531
|
-
fileId = Number(decoded.args.fileId);
|
|
35532
|
-
break;
|
|
35361
|
+
encryptedPermissions = await Promise.all(
|
|
35362
|
+
permissions.map(async (permission) => {
|
|
35363
|
+
const publicKey = permission.publicKey;
|
|
35364
|
+
if (!publicKey) {
|
|
35365
|
+
throw new Error(
|
|
35366
|
+
`Public key required for permission to ${permission.grantee} when encryption is enabled`
|
|
35367
|
+
);
|
|
35533
35368
|
}
|
|
35534
|
-
|
|
35369
|
+
const encryptedKey = await encryptWithWalletPublicKey(
|
|
35370
|
+
userEncryptionKey,
|
|
35371
|
+
publicKey,
|
|
35372
|
+
this.context.platform
|
|
35373
|
+
);
|
|
35374
|
+
return {
|
|
35375
|
+
account: permission.grantee,
|
|
35376
|
+
key: encryptedKey
|
|
35377
|
+
};
|
|
35378
|
+
})
|
|
35379
|
+
);
|
|
35380
|
+
}
|
|
35381
|
+
let result;
|
|
35382
|
+
if (this.context.relayerCallbacks?.submitFileAdditionComplete) {
|
|
35383
|
+
result = await this.context.relayerCallbacks.submitFileAdditionComplete(
|
|
35384
|
+
{
|
|
35385
|
+
url: uploadResult.url,
|
|
35386
|
+
userAddress,
|
|
35387
|
+
permissions: encryptedPermissions,
|
|
35388
|
+
schemaId: schemaId || 0,
|
|
35389
|
+
ownerAddress: owner
|
|
35535
35390
|
}
|
|
35391
|
+
);
|
|
35392
|
+
} else if (this.context.relayerCallbacks?.submitFileAddition) {
|
|
35393
|
+
const needsComplexRegistration = schemaId !== void 0 || encryptedPermissions.length > 0;
|
|
35394
|
+
if (needsComplexRegistration) {
|
|
35395
|
+
throw new Error(
|
|
35396
|
+
"The configured relay callback does not support schemas or permissions. Please update your relay server implementation to provide the `submitFileAdditionComplete` callback."
|
|
35397
|
+
);
|
|
35536
35398
|
}
|
|
35537
|
-
|
|
35538
|
-
|
|
35539
|
-
|
|
35540
|
-
|
|
35399
|
+
result = await this.context.relayerCallbacks.submitFileAddition(
|
|
35400
|
+
uploadResult.url,
|
|
35401
|
+
userAddress
|
|
35402
|
+
);
|
|
35403
|
+
} else {
|
|
35404
|
+
result = await this.addFileWithPermissionsAndSchema(
|
|
35405
|
+
uploadResult.url,
|
|
35406
|
+
userAddress,
|
|
35407
|
+
encryptedPermissions,
|
|
35408
|
+
schemaId || 0
|
|
35409
|
+
);
|
|
35541
35410
|
}
|
|
35542
35411
|
return {
|
|
35543
|
-
fileId:
|
|
35412
|
+
fileId: result.fileId,
|
|
35544
35413
|
url: uploadResult.url,
|
|
35545
|
-
transactionHash:
|
|
35414
|
+
transactionHash: result.transactionHash,
|
|
35546
35415
|
size: uploadResult.size,
|
|
35547
35416
|
isValid,
|
|
35548
35417
|
validationErrors: validationErrors.length > 0 ? validationErrors : void 0
|
|
@@ -35553,6 +35422,142 @@ var DataController = class {
|
|
|
35553
35422
|
);
|
|
35554
35423
|
}
|
|
35555
35424
|
}
|
|
35425
|
+
/**
|
|
35426
|
+
* Decrypts a file owned by the user using their wallet signature.
|
|
35427
|
+
*
|
|
35428
|
+
* @remarks
|
|
35429
|
+
* This is the high-level convenience method for decrypting user files, serving as the
|
|
35430
|
+
* symmetrical counterpart to the `upload` method. It handles the complete decryption
|
|
35431
|
+
* workflow including key generation, URL protocol detection, content fetching, and
|
|
35432
|
+
* decryption.
|
|
35433
|
+
*
|
|
35434
|
+
* The method automatically:
|
|
35435
|
+
* - Generates the decryption key from the user's wallet signature
|
|
35436
|
+
* - Determines the appropriate fetch method based on the file URL protocol
|
|
35437
|
+
* - Fetches the encrypted content from IPFS or standard HTTP URLs
|
|
35438
|
+
* - Decrypts the content using the generated key
|
|
35439
|
+
*
|
|
35440
|
+
* For IPFS URLs, the method uses gateway fallback for improved reliability. For
|
|
35441
|
+
* standard HTTP URLs, it uses a simple fetch. If you need custom authentication
|
|
35442
|
+
* headers or specific gateway configurations, use the low-level primitives directly.
|
|
35443
|
+
*
|
|
35444
|
+
* @param file - The user file to decrypt (typically from getUserFiles)
|
|
35445
|
+
* @param encryptionSeed - Optional custom encryption seed (defaults to Vana standard)
|
|
35446
|
+
* @returns Promise resolving to the decrypted file content as a Blob
|
|
35447
|
+
* @throws {Error} When the wallet is not connected
|
|
35448
|
+
* @throws {Error} When fetching the encrypted content fails
|
|
35449
|
+
* @throws {Error} When decryption fails (wrong key or corrupted data)
|
|
35450
|
+
* @example
|
|
35451
|
+
* ```typescript
|
|
35452
|
+
* // Basic file decryption
|
|
35453
|
+
* const files = await vana.data.getUserFiles({ owner: userAddress });
|
|
35454
|
+
* const decryptedBlob = await vana.data.decryptFile(files[0]);
|
|
35455
|
+
*
|
|
35456
|
+
* // Convert to text
|
|
35457
|
+
* const text = await decryptedBlob.text();
|
|
35458
|
+
* console.log('Decrypted content:', text);
|
|
35459
|
+
*
|
|
35460
|
+
* // Convert to JSON
|
|
35461
|
+
* const json = JSON.parse(await decryptedBlob.text());
|
|
35462
|
+
* console.log('Decrypted data:', json);
|
|
35463
|
+
*
|
|
35464
|
+
* // With custom encryption seed
|
|
35465
|
+
* const decryptedBlob = await vana.data.decryptFile(
|
|
35466
|
+
* files[0],
|
|
35467
|
+
* "My custom encryption seed"
|
|
35468
|
+
* );
|
|
35469
|
+
*
|
|
35470
|
+
* // Save to file (in Node.js)
|
|
35471
|
+
* const buffer = await decryptedBlob.arrayBuffer();
|
|
35472
|
+
* fs.writeFileSync('decrypted-file.txt', Buffer.from(buffer));
|
|
35473
|
+
* ```
|
|
35474
|
+
*/
|
|
35475
|
+
async decryptFile(file, encryptionSeed) {
|
|
35476
|
+
try {
|
|
35477
|
+
const encryptionKey = await generateEncryptionKey(
|
|
35478
|
+
this.context.walletClient,
|
|
35479
|
+
encryptionSeed || DEFAULT_ENCRYPTION_SEED
|
|
35480
|
+
);
|
|
35481
|
+
let encryptedBlob;
|
|
35482
|
+
try {
|
|
35483
|
+
if (file.url.startsWith("ipfs://")) {
|
|
35484
|
+
encryptedBlob = await this.fetchFromIPFS(file.url);
|
|
35485
|
+
} else {
|
|
35486
|
+
encryptedBlob = await this.fetch(file.url);
|
|
35487
|
+
}
|
|
35488
|
+
} catch (fetchError) {
|
|
35489
|
+
const errorMessage = fetchError instanceof Error ? fetchError.message : "Unknown error";
|
|
35490
|
+
if (errorMessage.includes("Failed to fetch IPFS content") && errorMessage.includes("from all gateways")) {
|
|
35491
|
+
throw new Error(
|
|
35492
|
+
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
35493
|
+
);
|
|
35494
|
+
} else if (errorMessage.includes("Empty response")) {
|
|
35495
|
+
throw new Error("File is empty or could not be retrieved");
|
|
35496
|
+
} else if (errorMessage.includes("Network error:") || errorMessage.includes("Failed to fetch")) {
|
|
35497
|
+
throw new Error(
|
|
35498
|
+
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
35499
|
+
);
|
|
35500
|
+
} else if (errorMessage.includes("HTTP error!")) {
|
|
35501
|
+
const statusMatch = errorMessage.match(/status: (\d+)/);
|
|
35502
|
+
const status = statusMatch ? statusMatch[1] : "unknown";
|
|
35503
|
+
if (status === "500") {
|
|
35504
|
+
throw new Error(
|
|
35505
|
+
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
35506
|
+
);
|
|
35507
|
+
} else if (status === "403") {
|
|
35508
|
+
throw new Error(
|
|
35509
|
+
"Access denied. You may not have permission to access this file"
|
|
35510
|
+
);
|
|
35511
|
+
} else if (status === "404") {
|
|
35512
|
+
throw new Error(
|
|
35513
|
+
"File not found: The encrypted file is no longer available at the stored URL."
|
|
35514
|
+
);
|
|
35515
|
+
} else {
|
|
35516
|
+
throw new Error(
|
|
35517
|
+
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
35518
|
+
);
|
|
35519
|
+
}
|
|
35520
|
+
}
|
|
35521
|
+
throw fetchError;
|
|
35522
|
+
}
|
|
35523
|
+
if (encryptedBlob.size === 0) {
|
|
35524
|
+
throw new Error("File is empty or could not be retrieved");
|
|
35525
|
+
}
|
|
35526
|
+
let decryptedBlob;
|
|
35527
|
+
try {
|
|
35528
|
+
decryptedBlob = await decryptBlobWithSignedKey(
|
|
35529
|
+
encryptedBlob,
|
|
35530
|
+
encryptionKey,
|
|
35531
|
+
this.context.platform
|
|
35532
|
+
);
|
|
35533
|
+
} catch (decryptError) {
|
|
35534
|
+
const errorMessage = decryptError instanceof Error ? decryptError.message : "Unknown error";
|
|
35535
|
+
if (errorMessage.includes("not a valid OpenPGP message")) {
|
|
35536
|
+
throw new Error(
|
|
35537
|
+
"Invalid file format: This file doesn't appear to be encrypted with the Vana protocol"
|
|
35538
|
+
);
|
|
35539
|
+
} else if (errorMessage.includes("Session key decryption failed")) {
|
|
35540
|
+
throw new Error("Wrong encryption key");
|
|
35541
|
+
} else if (errorMessage.includes("Error decrypting message")) {
|
|
35542
|
+
throw new Error("Wrong encryption key");
|
|
35543
|
+
} else if (errorMessage.includes("File not found")) {
|
|
35544
|
+
throw new Error(
|
|
35545
|
+
"File not found: The encrypted file is no longer available"
|
|
35546
|
+
);
|
|
35547
|
+
} else {
|
|
35548
|
+
throw decryptError;
|
|
35549
|
+
}
|
|
35550
|
+
}
|
|
35551
|
+
return decryptedBlob;
|
|
35552
|
+
} catch (error) {
|
|
35553
|
+
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"))) {
|
|
35554
|
+
throw error;
|
|
35555
|
+
}
|
|
35556
|
+
throw new Error(
|
|
35557
|
+
`Failed to decrypt file: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
35558
|
+
);
|
|
35559
|
+
}
|
|
35560
|
+
}
|
|
35556
35561
|
/**
|
|
35557
35562
|
* Retrieves all data files owned by a specific user address.
|
|
35558
35563
|
*
|
|
@@ -36303,81 +36308,6 @@ var DataController = class {
|
|
|
36303
36308
|
);
|
|
36304
36309
|
}
|
|
36305
36310
|
}
|
|
36306
|
-
/**
|
|
36307
|
-
* Decrypts a file that was encrypted using the Vana protocol.
|
|
36308
|
-
*
|
|
36309
|
-
* @param file - The UserFile object containing the file URL and metadata
|
|
36310
|
-
* @param encryptionSeed - Optional custom encryption seed (defaults to Vana standard)
|
|
36311
|
-
* @returns Promise resolving to the decrypted file as a Blob
|
|
36312
|
-
*
|
|
36313
|
-
* This method handles the complete flow of:
|
|
36314
|
-
* 1. Generating the encryption key from the user's wallet signature
|
|
36315
|
-
* 2. Fetching the encrypted file from the stored URL
|
|
36316
|
-
* 3. Decrypting the file using the canonical Vana decryption method
|
|
36317
|
-
*/
|
|
36318
|
-
async decryptFile(file, encryptionSeed = DEFAULT_ENCRYPTION_SEED) {
|
|
36319
|
-
try {
|
|
36320
|
-
const encryptionKey = await generateEncryptionKey(
|
|
36321
|
-
this.context.walletClient,
|
|
36322
|
-
encryptionSeed
|
|
36323
|
-
);
|
|
36324
|
-
const fetchUrl = this.convertToDownloadUrl(file.url);
|
|
36325
|
-
console.debug(
|
|
36326
|
-
`Fetching encrypted file from URL: ${fetchUrl} (original: ${file.url})`
|
|
36327
|
-
);
|
|
36328
|
-
const response = await fetch(fetchUrl);
|
|
36329
|
-
if (!response.ok) {
|
|
36330
|
-
if (response.status === 404) {
|
|
36331
|
-
throw new Error(
|
|
36332
|
-
"File not found. The encrypted file may have been moved or deleted."
|
|
36333
|
-
);
|
|
36334
|
-
} else if (response.status === 403) {
|
|
36335
|
-
throw new Error(
|
|
36336
|
-
"Access denied. You may not have permission to access this file."
|
|
36337
|
-
);
|
|
36338
|
-
} else {
|
|
36339
|
-
throw new Error(
|
|
36340
|
-
`Network error: ${response.status} ${response.statusText}`
|
|
36341
|
-
);
|
|
36342
|
-
}
|
|
36343
|
-
}
|
|
36344
|
-
const encryptedBlob = await response.blob();
|
|
36345
|
-
console.debug(
|
|
36346
|
-
`Retrieved blob of size: ${encryptedBlob.size} bytes, type: ${encryptedBlob.type}`
|
|
36347
|
-
);
|
|
36348
|
-
if (encryptedBlob.size === 0) {
|
|
36349
|
-
throw new Error("File is empty or could not be retrieved.");
|
|
36350
|
-
}
|
|
36351
|
-
const decryptedBlob = await decryptUserData(
|
|
36352
|
-
encryptedBlob,
|
|
36353
|
-
encryptionKey,
|
|
36354
|
-
this.context.platform
|
|
36355
|
-
);
|
|
36356
|
-
return decryptedBlob;
|
|
36357
|
-
} catch (error) {
|
|
36358
|
-
console.error("Failed to decrypt file:", error);
|
|
36359
|
-
if (error instanceof Error) {
|
|
36360
|
-
if (error.message.includes("Session key decryption failed") || error.message.includes("Error decrypting message")) {
|
|
36361
|
-
throw new Error(
|
|
36362
|
-
"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."
|
|
36363
|
-
);
|
|
36364
|
-
} else if (error.message.includes("Failed to fetch") || error.message.includes("Network error")) {
|
|
36365
|
-
throw new Error(
|
|
36366
|
-
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
36367
|
-
);
|
|
36368
|
-
} else if (error.message.includes("File not found")) {
|
|
36369
|
-
throw new Error(
|
|
36370
|
-
"File not found: The encrypted file is no longer available at the stored URL."
|
|
36371
|
-
);
|
|
36372
|
-
} else if (error.message.includes("not a valid OpenPGP message") || error.message.includes("does not conform to a valid OpenPGP format")) {
|
|
36373
|
-
throw new Error(
|
|
36374
|
-
"Invalid file format: This file doesn't appear to be encrypted with the Vana protocol."
|
|
36375
|
-
);
|
|
36376
|
-
}
|
|
36377
|
-
}
|
|
36378
|
-
throw error;
|
|
36379
|
-
}
|
|
36380
|
-
}
|
|
36381
36311
|
/**
|
|
36382
36312
|
* Registers a file URL directly on the blockchain with a schema ID.
|
|
36383
36313
|
*
|
|
@@ -36438,26 +36368,6 @@ var DataController = class {
|
|
|
36438
36368
|
);
|
|
36439
36369
|
}
|
|
36440
36370
|
}
|
|
36441
|
-
/**
|
|
36442
|
-
* Converts IPFS and Google Drive URLs to direct download URLs for fetching.
|
|
36443
|
-
*
|
|
36444
|
-
* @param url - The URL to convert to a direct download URL
|
|
36445
|
-
* @returns The converted direct download URL or the original URL if not a special URL
|
|
36446
|
-
*/
|
|
36447
|
-
convertToDownloadUrl(url) {
|
|
36448
|
-
if (url.startsWith("ipfs://")) {
|
|
36449
|
-
const hash = url.replace("ipfs://", "");
|
|
36450
|
-
return `https://ipfs.io/ipfs/${hash}`;
|
|
36451
|
-
}
|
|
36452
|
-
if (url.includes("drive.google.com/file/d/")) {
|
|
36453
|
-
const fileIdMatch = url.match(/\/file\/d\/([a-zA-Z0-9-_]+)/);
|
|
36454
|
-
if (fileIdMatch) {
|
|
36455
|
-
const fileId = fileIdMatch[1];
|
|
36456
|
-
return `https://drive.google.com/uc?id=${fileId}&export=download`;
|
|
36457
|
-
}
|
|
36458
|
-
}
|
|
36459
|
-
return url;
|
|
36460
|
-
}
|
|
36461
36371
|
/**
|
|
36462
36372
|
* Gets the user's address from the wallet client.
|
|
36463
36373
|
*
|
|
@@ -36532,6 +36442,66 @@ var DataController = class {
|
|
|
36532
36442
|
);
|
|
36533
36443
|
}
|
|
36534
36444
|
}
|
|
36445
|
+
/**
|
|
36446
|
+
* Adds a file to the registry with permissions and schema.
|
|
36447
|
+
* This combines the functionality of addFileWithPermissions and schema validation.
|
|
36448
|
+
*
|
|
36449
|
+
* @param url - The URL of the file to register
|
|
36450
|
+
* @param ownerAddress - The address of the file owner
|
|
36451
|
+
* @param permissions - Array of permissions to grant (account and encrypted key)
|
|
36452
|
+
* @param schemaId - The schema ID to associate with the file (0 for no schema)
|
|
36453
|
+
* @returns Promise resolving to object with fileId and transactionHash
|
|
36454
|
+
*/
|
|
36455
|
+
async addFileWithPermissionsAndSchema(url, ownerAddress, permissions = [], schemaId = 0) {
|
|
36456
|
+
try {
|
|
36457
|
+
const chainId = this.context.walletClient.chain?.id;
|
|
36458
|
+
if (!chainId) {
|
|
36459
|
+
throw new Error("Chain ID not available");
|
|
36460
|
+
}
|
|
36461
|
+
const dataRegistryAddress = getContractAddress(chainId, "DataRegistry");
|
|
36462
|
+
const dataRegistryAbi = getAbi("DataRegistry");
|
|
36463
|
+
const txHash = await this.context.walletClient.writeContract({
|
|
36464
|
+
address: dataRegistryAddress,
|
|
36465
|
+
abi: dataRegistryAbi,
|
|
36466
|
+
functionName: "addFileWithPermissionsAndSchema",
|
|
36467
|
+
args: [url, ownerAddress, permissions, BigInt(schemaId)],
|
|
36468
|
+
account: this.context.walletClient.account || ownerAddress,
|
|
36469
|
+
chain: this.context.walletClient.chain || null
|
|
36470
|
+
});
|
|
36471
|
+
const receipt = await this.context.publicClient.waitForTransactionReceipt(
|
|
36472
|
+
{
|
|
36473
|
+
hash: txHash,
|
|
36474
|
+
timeout: 3e4
|
|
36475
|
+
// 30 seconds timeout
|
|
36476
|
+
}
|
|
36477
|
+
);
|
|
36478
|
+
let fileId = 0;
|
|
36479
|
+
for (const log of receipt.logs) {
|
|
36480
|
+
try {
|
|
36481
|
+
const decoded = decodeEventLog({
|
|
36482
|
+
abi: dataRegistryAbi,
|
|
36483
|
+
data: log.data,
|
|
36484
|
+
topics: log.topics
|
|
36485
|
+
});
|
|
36486
|
+
if (decoded.eventName === "FileAdded") {
|
|
36487
|
+
fileId = Number(decoded.args.fileId);
|
|
36488
|
+
break;
|
|
36489
|
+
}
|
|
36490
|
+
} catch {
|
|
36491
|
+
continue;
|
|
36492
|
+
}
|
|
36493
|
+
}
|
|
36494
|
+
return {
|
|
36495
|
+
fileId,
|
|
36496
|
+
transactionHash: txHash
|
|
36497
|
+
};
|
|
36498
|
+
} catch (error) {
|
|
36499
|
+
console.error("Failed to add file with permissions and schema:", error);
|
|
36500
|
+
throw new Error(
|
|
36501
|
+
`Failed to add file with permissions and schema: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
36502
|
+
);
|
|
36503
|
+
}
|
|
36504
|
+
}
|
|
36535
36505
|
/**
|
|
36536
36506
|
* Adds a new schema to the DataRefinerRegistry.
|
|
36537
36507
|
*
|
|
@@ -36686,7 +36656,7 @@ var DataController = class {
|
|
|
36686
36656
|
const txHash = await this.context.walletClient.writeContract({
|
|
36687
36657
|
address: dataRefinerRegistryAddress,
|
|
36688
36658
|
abi: dataRefinerRegistryAbi,
|
|
36689
|
-
functionName: "
|
|
36659
|
+
functionName: "addRefinerWithSchemaId",
|
|
36690
36660
|
args: [
|
|
36691
36661
|
BigInt(params.dlpId),
|
|
36692
36662
|
params.name,
|
|
@@ -36891,7 +36861,7 @@ var DataController = class {
|
|
|
36891
36861
|
this.context.walletClient,
|
|
36892
36862
|
DEFAULT_ENCRYPTION_SEED
|
|
36893
36863
|
);
|
|
36894
|
-
const encryptedData = await
|
|
36864
|
+
const encryptedData = await encryptBlobWithSignedKey(
|
|
36895
36865
|
data,
|
|
36896
36866
|
userEncryptionKey,
|
|
36897
36867
|
this.context.platform
|
|
@@ -37055,12 +37025,13 @@ var DataController = class {
|
|
|
37055
37025
|
privateKey,
|
|
37056
37026
|
this.context.platform
|
|
37057
37027
|
);
|
|
37058
|
-
|
|
37059
|
-
if (
|
|
37060
|
-
|
|
37028
|
+
let encryptedData;
|
|
37029
|
+
if (file.url.startsWith("ipfs://")) {
|
|
37030
|
+
encryptedData = await this.fetchFromIPFS(file.url);
|
|
37031
|
+
} else {
|
|
37032
|
+
encryptedData = await this.fetch(file.url);
|
|
37061
37033
|
}
|
|
37062
|
-
const
|
|
37063
|
-
const decryptedData = await decryptUserData(
|
|
37034
|
+
const decryptedData = await decryptBlobWithSignedKey(
|
|
37064
37035
|
encryptedData,
|
|
37065
37036
|
userEncryptionKey,
|
|
37066
37037
|
this.context.platform
|
|
@@ -37073,6 +37044,162 @@ var DataController = class {
|
|
|
37073
37044
|
);
|
|
37074
37045
|
}
|
|
37075
37046
|
}
|
|
37047
|
+
/**
|
|
37048
|
+
* Simple network-agnostic fetch utility for retrieving file content.
|
|
37049
|
+
*
|
|
37050
|
+
* @remarks
|
|
37051
|
+
* This is a thin wrapper around the global fetch API that returns the response as a Blob.
|
|
37052
|
+
* It provides a consistent interface for fetching encrypted content before decryption.
|
|
37053
|
+
* For IPFS URLs, consider using fetchFromIPFS for better reliability.
|
|
37054
|
+
*
|
|
37055
|
+
* @param url - The URL to fetch content from
|
|
37056
|
+
* @returns Promise resolving to the fetched content as a Blob
|
|
37057
|
+
* @throws {Error} When the fetch fails or returns a non-ok response
|
|
37058
|
+
*
|
|
37059
|
+
* @example
|
|
37060
|
+
* ```typescript
|
|
37061
|
+
* // Fetch and decrypt a file
|
|
37062
|
+
* const encryptionKey = await generateEncryptionKey(walletClient);
|
|
37063
|
+
* const encryptedBlob = await vana.data.fetch(file.url);
|
|
37064
|
+
* const decryptedBlob = await decryptBlob(encryptedBlob, encryptionKey, platform);
|
|
37065
|
+
*
|
|
37066
|
+
* // With custom headers for authentication
|
|
37067
|
+
* const response = await fetch(file.url, {
|
|
37068
|
+
* headers: { 'Authorization': 'Bearer token' }
|
|
37069
|
+
* });
|
|
37070
|
+
* const encryptedBlob = await response.blob();
|
|
37071
|
+
* ```
|
|
37072
|
+
*/
|
|
37073
|
+
async fetch(url) {
|
|
37074
|
+
try {
|
|
37075
|
+
const response = await fetch(url);
|
|
37076
|
+
if (!response.ok) {
|
|
37077
|
+
throw new Error(
|
|
37078
|
+
`HTTP error! status: ${response.status} ${response.statusText}`
|
|
37079
|
+
);
|
|
37080
|
+
}
|
|
37081
|
+
const blob = await response.blob();
|
|
37082
|
+
if (blob.size === 0) {
|
|
37083
|
+
throw new Error("Empty response");
|
|
37084
|
+
}
|
|
37085
|
+
return blob;
|
|
37086
|
+
} catch (error) {
|
|
37087
|
+
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
37088
|
+
throw new Error(
|
|
37089
|
+
`Network error: Failed to fetch from ${url}. The URL may be invalid or the server may not be accessible.`
|
|
37090
|
+
);
|
|
37091
|
+
}
|
|
37092
|
+
throw error;
|
|
37093
|
+
}
|
|
37094
|
+
}
|
|
37095
|
+
/**
|
|
37096
|
+
* Specialized IPFS fetcher with gateway fallback mechanism.
|
|
37097
|
+
*
|
|
37098
|
+
* @remarks
|
|
37099
|
+
* This method provides robust IPFS content fetching by trying multiple gateways
|
|
37100
|
+
* in sequence until one succeeds. It supports both ipfs:// URLs and raw CIDs.
|
|
37101
|
+
*
|
|
37102
|
+
* The default gateway list includes public gateways, but you should provide
|
|
37103
|
+
* your own gateways for production use to ensure reliability and privacy.
|
|
37104
|
+
*
|
|
37105
|
+
* @param url - The IPFS URL (ipfs://...) or CID to fetch
|
|
37106
|
+
* @param options - Optional configuration
|
|
37107
|
+
* @param options.gateways - Array of IPFS gateway URLs to try (must end with /)
|
|
37108
|
+
* @returns Promise resolving to the fetched content as a Blob
|
|
37109
|
+
* @throws {Error} When all gateways fail to fetch the content
|
|
37110
|
+
*
|
|
37111
|
+
* @example
|
|
37112
|
+
* ```typescript
|
|
37113
|
+
* // Fetch from IPFS with custom gateways
|
|
37114
|
+
* const encryptedBlob = await vana.data.fetchFromIPFS(file.url, {
|
|
37115
|
+
* gateways: [
|
|
37116
|
+
* 'https://my-private-gateway.com/ipfs/',
|
|
37117
|
+
* 'https://dweb.link/ipfs/',
|
|
37118
|
+
* 'https://ipfs.io/ipfs/'
|
|
37119
|
+
* ]
|
|
37120
|
+
* });
|
|
37121
|
+
*
|
|
37122
|
+
* // Decrypt the fetched content
|
|
37123
|
+
* const encryptionKey = await generateEncryptionKey(walletClient);
|
|
37124
|
+
* const decryptedBlob = await decryptBlob(encryptedBlob, encryptionKey, platform);
|
|
37125
|
+
*
|
|
37126
|
+
* // With raw CID
|
|
37127
|
+
* const blob = await vana.data.fetchFromIPFS('QmXxx...', {
|
|
37128
|
+
* gateways: ['https://ipfs.io/ipfs/']
|
|
37129
|
+
* });
|
|
37130
|
+
* ```
|
|
37131
|
+
*/
|
|
37132
|
+
async fetchFromIPFS(url, options) {
|
|
37133
|
+
const defaultGateways = [
|
|
37134
|
+
"https://dweb.link/ipfs/",
|
|
37135
|
+
"https://ipfs.io/ipfs/"
|
|
37136
|
+
];
|
|
37137
|
+
const gateways = options?.gateways || this.context.ipfsGateways || defaultGateways;
|
|
37138
|
+
let cid;
|
|
37139
|
+
if (url.startsWith("ipfs://")) {
|
|
37140
|
+
cid = url.replace("ipfs://", "");
|
|
37141
|
+
} else if (url.startsWith("Qm") || url.startsWith("bafy")) {
|
|
37142
|
+
cid = url;
|
|
37143
|
+
} else {
|
|
37144
|
+
throw new Error(
|
|
37145
|
+
`Invalid IPFS URL format. Expected ipfs://... or a raw CID, got: ${url}`
|
|
37146
|
+
);
|
|
37147
|
+
}
|
|
37148
|
+
const errors = [];
|
|
37149
|
+
for (let i = 0; i < gateways.length; i++) {
|
|
37150
|
+
const gateway = gateways[i];
|
|
37151
|
+
const isLastGateway = i === gateways.length - 1;
|
|
37152
|
+
const gatewayUrl = gateway.endsWith("/") ? `${gateway}${cid}` : `${gateway}/${cid}`;
|
|
37153
|
+
try {
|
|
37154
|
+
console.debug(`Trying IPFS gateway: ${gatewayUrl}`);
|
|
37155
|
+
const response = await fetch(gatewayUrl);
|
|
37156
|
+
if (response.ok) {
|
|
37157
|
+
const blob = await response.blob();
|
|
37158
|
+
if (blob.size > 0) {
|
|
37159
|
+
console.debug(`Successfully fetched from gateway: ${gateway}`);
|
|
37160
|
+
return blob;
|
|
37161
|
+
} else {
|
|
37162
|
+
if (isLastGateway) {
|
|
37163
|
+
throw new Error("Empty response");
|
|
37164
|
+
}
|
|
37165
|
+
errors.push({
|
|
37166
|
+
gateway,
|
|
37167
|
+
error: "Empty response"
|
|
37168
|
+
});
|
|
37169
|
+
}
|
|
37170
|
+
} else {
|
|
37171
|
+
if (isLastGateway) {
|
|
37172
|
+
if (response.status === 403) {
|
|
37173
|
+
throw new Error(`HTTP error! status: 403 ${response.statusText}`);
|
|
37174
|
+
} else if (response.status === 404) {
|
|
37175
|
+
throw new Error(`HTTP error! status: 404 ${response.statusText}`);
|
|
37176
|
+
} else {
|
|
37177
|
+
throw new Error(
|
|
37178
|
+
`HTTP error! status: ${response.status} ${response.statusText}`
|
|
37179
|
+
);
|
|
37180
|
+
}
|
|
37181
|
+
}
|
|
37182
|
+
errors.push({
|
|
37183
|
+
gateway,
|
|
37184
|
+
error: `HTTP ${response.status} ${response.statusText}`
|
|
37185
|
+
});
|
|
37186
|
+
}
|
|
37187
|
+
} catch (error) {
|
|
37188
|
+
if (isLastGateway && error instanceof Error && (error.message.includes("Empty response") || error.message.includes("HTTP error!"))) {
|
|
37189
|
+
throw error;
|
|
37190
|
+
}
|
|
37191
|
+
errors.push({
|
|
37192
|
+
gateway,
|
|
37193
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
37194
|
+
});
|
|
37195
|
+
}
|
|
37196
|
+
}
|
|
37197
|
+
const errorDetails = errors.map((e) => `${e.gateway}: ${e.error}`).join("\n ");
|
|
37198
|
+
throw new Error(
|
|
37199
|
+
`Failed to fetch IPFS content ${cid} from all gateways:
|
|
37200
|
+
${errorDetails}`
|
|
37201
|
+
);
|
|
37202
|
+
}
|
|
37076
37203
|
/**
|
|
37077
37204
|
* Validates a data schema against the Vana meta-schema.
|
|
37078
37205
|
*
|
|
@@ -37261,9 +37388,14 @@ var SchemaController = class {
|
|
|
37261
37388
|
};
|
|
37262
37389
|
validateDataSchema(dataSchema);
|
|
37263
37390
|
if (!this.context.storageManager) {
|
|
37264
|
-
|
|
37265
|
-
|
|
37266
|
-
|
|
37391
|
+
if (this.context.validateStorageRequired) {
|
|
37392
|
+
this.context.validateStorageRequired();
|
|
37393
|
+
throw new Error("Storage validation failed");
|
|
37394
|
+
} else {
|
|
37395
|
+
throw new Error(
|
|
37396
|
+
"Storage manager not configured. Please provide storage providers in VanaConfig."
|
|
37397
|
+
);
|
|
37398
|
+
}
|
|
37267
37399
|
}
|
|
37268
37400
|
const schemaBlob = new Blob([JSON.stringify(schemaDefinition)], {
|
|
37269
37401
|
type: "application/json"
|
|
@@ -37535,6 +37667,7 @@ var ServerController = class {
|
|
|
37535
37667
|
}
|
|
37536
37668
|
const serverResponse = await response.json();
|
|
37537
37669
|
return {
|
|
37670
|
+
kind: serverResponse.personal_server.kind,
|
|
37538
37671
|
address: serverResponse.personal_server.address,
|
|
37539
37672
|
public_key: serverResponse.personal_server.public_key,
|
|
37540
37673
|
base_url: this.PERSONAL_SERVER_BASE_URL || "",
|
|
@@ -39148,175 +39281,151 @@ var PinataStorage = class {
|
|
|
39148
39281
|
}
|
|
39149
39282
|
};
|
|
39150
39283
|
|
|
39151
|
-
// src/storage/providers/
|
|
39152
|
-
var
|
|
39153
|
-
constructor(
|
|
39154
|
-
this.
|
|
39155
|
-
if (!
|
|
39156
|
-
throw new
|
|
39157
|
-
"
|
|
39158
|
-
"MISSING_UPLOAD_URL",
|
|
39159
|
-
"server-proxy"
|
|
39160
|
-
);
|
|
39161
|
-
}
|
|
39162
|
-
if (!config.downloadUrl) {
|
|
39163
|
-
throw new StorageError(
|
|
39164
|
-
"Download URL is required",
|
|
39165
|
-
"MISSING_DOWNLOAD_URL",
|
|
39166
|
-
"server-proxy"
|
|
39284
|
+
// src/storage/providers/callback-storage.ts
|
|
39285
|
+
var CallbackStorage = class {
|
|
39286
|
+
constructor(callbacks) {
|
|
39287
|
+
this.callbacks = callbacks;
|
|
39288
|
+
if (!callbacks.upload || !callbacks.download) {
|
|
39289
|
+
throw new Error(
|
|
39290
|
+
"CallbackStorage requires both upload and download callbacks"
|
|
39167
39291
|
);
|
|
39168
39292
|
}
|
|
39169
39293
|
}
|
|
39170
39294
|
/**
|
|
39171
|
-
*
|
|
39172
|
-
*
|
|
39173
|
-
* @remarks
|
|
39174
|
-
* This method sends the file to your configured upload endpoint via FormData.
|
|
39175
|
-
* Your server is responsible for handling the actual storage implementation
|
|
39176
|
-
* and must return a JSON response with `success: true` and an `identifier` field.
|
|
39177
|
-
*
|
|
39178
|
-
* @param file - The file to upload
|
|
39179
|
-
* @param filename - Optional custom filename
|
|
39180
|
-
* @returns Promise that resolves to the server-provided identifier
|
|
39181
|
-
* @throws {StorageError} When the upload fails or server returns an error
|
|
39295
|
+
* Upload a file using the provided callback
|
|
39182
39296
|
*
|
|
39183
|
-
* @
|
|
39184
|
-
*
|
|
39185
|
-
*
|
|
39186
|
-
* console.log("File uploaded with identifier:", identifier);
|
|
39187
|
-
* ```
|
|
39297
|
+
* @param file - The blob to upload
|
|
39298
|
+
* @param filename - Optional filename for the upload
|
|
39299
|
+
* @returns The upload result with URL and metadata
|
|
39188
39300
|
*/
|
|
39189
39301
|
async upload(file, filename) {
|
|
39190
39302
|
try {
|
|
39191
|
-
const
|
|
39192
|
-
|
|
39193
|
-
if (filename) {
|
|
39194
|
-
formData.append("name", filename);
|
|
39195
|
-
}
|
|
39196
|
-
const response = await fetch(this.config.uploadUrl, {
|
|
39197
|
-
method: "POST",
|
|
39198
|
-
body: formData
|
|
39199
|
-
});
|
|
39200
|
-
if (!response.ok) {
|
|
39201
|
-
const _errorText = await response.text();
|
|
39202
|
-
throw new StorageError(
|
|
39203
|
-
`Server upload failed: ${response.status} ${response.statusText}`,
|
|
39204
|
-
"UPLOAD_FAILED",
|
|
39205
|
-
"server-proxy"
|
|
39206
|
-
);
|
|
39207
|
-
}
|
|
39208
|
-
const result = await response.json();
|
|
39209
|
-
if (!result.success) {
|
|
39303
|
+
const result = await this.callbacks.upload(file, filename);
|
|
39304
|
+
if (!result.url || result.url.trim() === "") {
|
|
39210
39305
|
throw new StorageError(
|
|
39211
|
-
|
|
39212
|
-
"
|
|
39213
|
-
"
|
|
39214
|
-
);
|
|
39215
|
-
}
|
|
39216
|
-
if (!result.identifier) {
|
|
39217
|
-
throw new StorageError(
|
|
39218
|
-
"Server upload succeeded but no identifier returned",
|
|
39219
|
-
"NO_IDENTIFIER_RETURNED",
|
|
39220
|
-
"server-proxy"
|
|
39306
|
+
"Upload callback returned invalid result: missing or empty url",
|
|
39307
|
+
"INVALID_UPLOAD_RESULT",
|
|
39308
|
+
"callback-storage"
|
|
39221
39309
|
);
|
|
39222
39310
|
}
|
|
39223
|
-
return
|
|
39224
|
-
url: result.url || result.identifier,
|
|
39225
|
-
size: file.size,
|
|
39226
|
-
contentType: file.type || "application/octet-stream"
|
|
39227
|
-
};
|
|
39311
|
+
return result;
|
|
39228
39312
|
} catch (error) {
|
|
39229
39313
|
if (error instanceof StorageError) {
|
|
39230
39314
|
throw error;
|
|
39231
39315
|
}
|
|
39232
39316
|
throw new StorageError(
|
|
39233
|
-
`
|
|
39317
|
+
`Upload failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39234
39318
|
"UPLOAD_ERROR",
|
|
39235
|
-
"
|
|
39319
|
+
"callback-storage",
|
|
39320
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
39236
39321
|
);
|
|
39237
39322
|
}
|
|
39238
39323
|
}
|
|
39239
39324
|
/**
|
|
39240
|
-
*
|
|
39241
|
-
*
|
|
39242
|
-
* @remarks
|
|
39243
|
-
* This method sends the identifier to your configured download endpoint via POST request.
|
|
39244
|
-
* Your server is responsible for retrieving the file from your storage backend
|
|
39245
|
-
* and returning the file content as a blob response.
|
|
39325
|
+
* Download a file using the provided callback
|
|
39246
39326
|
*
|
|
39247
|
-
* @param url - The
|
|
39248
|
-
* @returns
|
|
39249
|
-
* @throws {StorageError} When the download fails or file is not found
|
|
39250
|
-
*
|
|
39251
|
-
* @example
|
|
39252
|
-
* ```typescript
|
|
39253
|
-
* const fileBlob = await serverStorage.download("file-123");
|
|
39254
|
-
* const url = URL.createObjectURL(fileBlob);
|
|
39255
|
-
* ```
|
|
39327
|
+
* @param url - The URL or identifier to download
|
|
39328
|
+
* @returns The downloaded blob
|
|
39256
39329
|
*/
|
|
39257
39330
|
async download(url) {
|
|
39258
39331
|
try {
|
|
39259
|
-
const identifier = this.
|
|
39260
|
-
const
|
|
39261
|
-
|
|
39262
|
-
headers: {
|
|
39263
|
-
"Content-Type": "application/json"
|
|
39264
|
-
},
|
|
39265
|
-
body: JSON.stringify({ identifier })
|
|
39266
|
-
});
|
|
39267
|
-
if (!response.ok) {
|
|
39268
|
-
const _errorText = await response.text();
|
|
39332
|
+
const identifier = this.callbacks.extractIdentifier ? this.callbacks.extractIdentifier(url) : url;
|
|
39333
|
+
const blob = await this.callbacks.download(identifier);
|
|
39334
|
+
if (!(blob instanceof Blob)) {
|
|
39269
39335
|
throw new StorageError(
|
|
39270
|
-
|
|
39271
|
-
"
|
|
39272
|
-
"
|
|
39336
|
+
"Download callback returned invalid result: expected Blob",
|
|
39337
|
+
"INVALID_DOWNLOAD_RESULT",
|
|
39338
|
+
"callback-storage"
|
|
39273
39339
|
);
|
|
39274
39340
|
}
|
|
39275
|
-
return
|
|
39341
|
+
return blob;
|
|
39276
39342
|
} catch (error) {
|
|
39277
39343
|
if (error instanceof StorageError) {
|
|
39278
39344
|
throw error;
|
|
39279
39345
|
}
|
|
39280
39346
|
throw new StorageError(
|
|
39281
|
-
`
|
|
39347
|
+
`Download failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39282
39348
|
"DOWNLOAD_ERROR",
|
|
39283
|
-
"
|
|
39349
|
+
"callback-storage",
|
|
39350
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
39284
39351
|
);
|
|
39285
39352
|
}
|
|
39286
39353
|
}
|
|
39287
|
-
|
|
39288
|
-
|
|
39289
|
-
|
|
39290
|
-
|
|
39291
|
-
|
|
39292
|
-
|
|
39293
|
-
|
|
39294
|
-
|
|
39295
|
-
|
|
39296
|
-
|
|
39297
|
-
|
|
39298
|
-
|
|
39299
|
-
|
|
39354
|
+
/**
|
|
39355
|
+
* List files using the provided callback (if available)
|
|
39356
|
+
*
|
|
39357
|
+
* @param options - Optional list options including filters and pagination
|
|
39358
|
+
* @returns Array of storage files
|
|
39359
|
+
*/
|
|
39360
|
+
async list(options) {
|
|
39361
|
+
if (!this.callbacks.list) {
|
|
39362
|
+
throw new StorageError(
|
|
39363
|
+
"List operation not supported - no list callback provided",
|
|
39364
|
+
"NOT_SUPPORTED",
|
|
39365
|
+
"callback-storage"
|
|
39366
|
+
);
|
|
39367
|
+
}
|
|
39368
|
+
try {
|
|
39369
|
+
const result = await this.callbacks.list(options?.namePattern, options);
|
|
39370
|
+
return result.items.map((item, index) => ({
|
|
39371
|
+
id: item.identifier,
|
|
39372
|
+
name: item.identifier.split("/").pop() || `file-${index}`,
|
|
39373
|
+
url: item.identifier,
|
|
39374
|
+
size: item.size || 0,
|
|
39375
|
+
contentType: "application/octet-stream",
|
|
39376
|
+
createdAt: item.lastModified || /* @__PURE__ */ new Date(),
|
|
39377
|
+
metadata: item.metadata
|
|
39378
|
+
}));
|
|
39379
|
+
} catch (error) {
|
|
39380
|
+
throw new StorageError(
|
|
39381
|
+
`List failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39382
|
+
"LIST_ERROR",
|
|
39383
|
+
"callback-storage",
|
|
39384
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
39385
|
+
);
|
|
39386
|
+
}
|
|
39300
39387
|
}
|
|
39301
39388
|
/**
|
|
39302
|
-
*
|
|
39389
|
+
* Delete a file using the provided callback (if available)
|
|
39303
39390
|
*
|
|
39304
|
-
* @param url - URL or identifier
|
|
39305
|
-
* @returns
|
|
39391
|
+
* @param url - The URL or identifier to delete
|
|
39392
|
+
* @returns True if deletion succeeded
|
|
39306
39393
|
*/
|
|
39307
|
-
|
|
39308
|
-
|
|
39394
|
+
async delete(url) {
|
|
39395
|
+
if (!this.callbacks.delete) {
|
|
39396
|
+
throw new StorageError(
|
|
39397
|
+
"Delete operation not supported - no delete callback provided",
|
|
39398
|
+
"NOT_SUPPORTED",
|
|
39399
|
+
"callback-storage"
|
|
39400
|
+
);
|
|
39401
|
+
}
|
|
39402
|
+
try {
|
|
39403
|
+
const identifier = this.callbacks.extractIdentifier ? this.callbacks.extractIdentifier(url) : url;
|
|
39404
|
+
return await this.callbacks.delete(identifier);
|
|
39405
|
+
} catch (error) {
|
|
39406
|
+
throw new StorageError(
|
|
39407
|
+
`Delete failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39408
|
+
"DELETE_ERROR",
|
|
39409
|
+
"callback-storage",
|
|
39410
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
39411
|
+
);
|
|
39412
|
+
}
|
|
39309
39413
|
}
|
|
39414
|
+
/**
|
|
39415
|
+
* Get provider configuration
|
|
39416
|
+
*
|
|
39417
|
+
* @returns Provider configuration metadata
|
|
39418
|
+
*/
|
|
39310
39419
|
getConfig() {
|
|
39311
39420
|
return {
|
|
39312
|
-
name: "
|
|
39313
|
-
type: "
|
|
39421
|
+
name: "callback-storage",
|
|
39422
|
+
type: "callback",
|
|
39314
39423
|
requiresAuth: false,
|
|
39315
39424
|
features: {
|
|
39316
39425
|
upload: true,
|
|
39317
39426
|
download: true,
|
|
39318
|
-
list:
|
|
39319
|
-
delete:
|
|
39427
|
+
list: !!this.callbacks.list,
|
|
39428
|
+
delete: !!this.callbacks.delete
|
|
39320
39429
|
}
|
|
39321
39430
|
};
|
|
39322
39431
|
}
|
|
@@ -39548,6 +39657,47 @@ function getAllChains() {
|
|
|
39548
39657
|
}
|
|
39549
39658
|
|
|
39550
39659
|
// src/core.ts
|
|
39660
|
+
var VanaCoreFactory = class {
|
|
39661
|
+
/**
|
|
39662
|
+
* Creates a VanaCore instance that enforces storage requirements at compile time.
|
|
39663
|
+
* Use this factory when you know you'll need storage-dependent operations.
|
|
39664
|
+
*
|
|
39665
|
+
* @param platform - The platform adapter for environment-specific operations
|
|
39666
|
+
* @param config - Configuration that includes required storage providers
|
|
39667
|
+
* @returns VanaCore instance with storage validation
|
|
39668
|
+
* @example
|
|
39669
|
+
* ```typescript
|
|
39670
|
+
* const vanaCore = VanaCoreFactory.createWithStorage(platformAdapter, {
|
|
39671
|
+
* walletClient: myWalletClient,
|
|
39672
|
+
* storage: {
|
|
39673
|
+
* providers: { ipfs: new IPFSStorage() },
|
|
39674
|
+
* defaultProvider: 'ipfs'
|
|
39675
|
+
* }
|
|
39676
|
+
* });
|
|
39677
|
+
* ```
|
|
39678
|
+
*/
|
|
39679
|
+
static createWithStorage(platform, config) {
|
|
39680
|
+
const core = new VanaCore(platform, config);
|
|
39681
|
+
return core;
|
|
39682
|
+
}
|
|
39683
|
+
/**
|
|
39684
|
+
* Creates a VanaCore instance without storage requirements.
|
|
39685
|
+
* Storage-dependent operations will fail at runtime if not configured.
|
|
39686
|
+
*
|
|
39687
|
+
* @param platform - The platform adapter for environment-specific operations
|
|
39688
|
+
* @param config - Basic configuration without required storage
|
|
39689
|
+
* @returns VanaCore instance
|
|
39690
|
+
* @example
|
|
39691
|
+
* ```typescript
|
|
39692
|
+
* const vanaCore = VanaCoreFactory.create(platformAdapter, {
|
|
39693
|
+
* walletClient: myWalletClient
|
|
39694
|
+
* });
|
|
39695
|
+
* ```
|
|
39696
|
+
*/
|
|
39697
|
+
static create(platform, config) {
|
|
39698
|
+
return new VanaCore(platform, config);
|
|
39699
|
+
}
|
|
39700
|
+
};
|
|
39551
39701
|
var VanaCore = class {
|
|
39552
39702
|
/**
|
|
39553
39703
|
* Initializes a new VanaCore client instance with the provided configuration.
|
|
@@ -39555,6 +39705,10 @@ var VanaCore = class {
|
|
|
39555
39705
|
* @remarks
|
|
39556
39706
|
* The constructor validates the configuration, initializes storage providers if configured,
|
|
39557
39707
|
* creates wallet and public clients, and sets up all SDK controllers with shared context.
|
|
39708
|
+
*
|
|
39709
|
+
* IMPORTANT: This constructor will validate storage requirements at runtime to fail fast.
|
|
39710
|
+
* Methods that require storage will throw runtime errors if storage is not configured.
|
|
39711
|
+
*
|
|
39558
39712
|
* @param platform - The platform adapter for environment-specific operations
|
|
39559
39713
|
* @param config - The configuration object specifying wallet or chain settings
|
|
39560
39714
|
* @throws {InvalidConfigurationError} When the configuration is invalid or incomplete
|
|
@@ -39581,9 +39735,13 @@ var VanaCore = class {
|
|
|
39581
39735
|
__publicField(this, "platform");
|
|
39582
39736
|
__publicField(this, "relayerCallbacks");
|
|
39583
39737
|
__publicField(this, "storageManager");
|
|
39738
|
+
__publicField(this, "hasRequiredStorage");
|
|
39739
|
+
__publicField(this, "ipfsGateways");
|
|
39584
39740
|
this.platform = platform;
|
|
39585
39741
|
this.validateConfig(config);
|
|
39586
39742
|
this.relayerCallbacks = config.relayerCallbacks;
|
|
39743
|
+
this.ipfsGateways = config.ipfsGateways;
|
|
39744
|
+
this.hasRequiredStorage = hasStorageConfig(config);
|
|
39587
39745
|
if (config.storage?.providers) {
|
|
39588
39746
|
this.storageManager = new StorageManager();
|
|
39589
39747
|
for (const [name, provider] of Object.entries(config.storage.providers)) {
|
|
@@ -39638,8 +39796,11 @@ var VanaCore = class {
|
|
|
39638
39796
|
relayerCallbacks: this.relayerCallbacks,
|
|
39639
39797
|
storageManager: this.storageManager,
|
|
39640
39798
|
subgraphUrl,
|
|
39641
|
-
platform: this.platform
|
|
39799
|
+
platform: this.platform,
|
|
39642
39800
|
// Pass the platform adapter to controllers
|
|
39801
|
+
validateStorageRequired: this.validateStorageRequired.bind(this),
|
|
39802
|
+
hasStorage: this.hasStorage.bind(this),
|
|
39803
|
+
ipfsGateways: this.ipfsGateways
|
|
39643
39804
|
};
|
|
39644
39805
|
this.permissions = new PermissionsController(sharedContext);
|
|
39645
39806
|
this.data = new DataController(sharedContext);
|
|
@@ -39647,6 +39808,58 @@ var VanaCore = class {
|
|
|
39647
39808
|
this.server = new ServerController(sharedContext);
|
|
39648
39809
|
this.protocol = new ProtocolController(sharedContext);
|
|
39649
39810
|
}
|
|
39811
|
+
/**
|
|
39812
|
+
* Validates that storage is available for storage-dependent operations.
|
|
39813
|
+
* This method enforces the fail-fast principle by checking storage availability
|
|
39814
|
+
* at method call time rather than during expensive operations.
|
|
39815
|
+
*
|
|
39816
|
+
* @throws {InvalidConfigurationError} When storage is required but not configured
|
|
39817
|
+
* @example
|
|
39818
|
+
* ```typescript
|
|
39819
|
+
* // This will throw if storage is not configured
|
|
39820
|
+
* vana.validateStorageRequired();
|
|
39821
|
+
* await vana.data.uploadFile(file); // Safe to proceed
|
|
39822
|
+
* ```
|
|
39823
|
+
*/
|
|
39824
|
+
validateStorageRequired() {
|
|
39825
|
+
if (!this.hasRequiredStorage) {
|
|
39826
|
+
throw new InvalidConfigurationError(
|
|
39827
|
+
"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."
|
|
39828
|
+
);
|
|
39829
|
+
}
|
|
39830
|
+
}
|
|
39831
|
+
/**
|
|
39832
|
+
* Checks whether storage is configured without throwing an error.
|
|
39833
|
+
*
|
|
39834
|
+
* @returns True if storage is properly configured
|
|
39835
|
+
* @example
|
|
39836
|
+
* ```typescript
|
|
39837
|
+
* if (vana.hasStorage()) {
|
|
39838
|
+
* await vana.data.uploadFile(file);
|
|
39839
|
+
* } else {
|
|
39840
|
+
* console.warn('Storage not configured - using pre-stored URLs only');
|
|
39841
|
+
* }
|
|
39842
|
+
* ```
|
|
39843
|
+
*/
|
|
39844
|
+
hasStorage() {
|
|
39845
|
+
return this.hasRequiredStorage;
|
|
39846
|
+
}
|
|
39847
|
+
/**
|
|
39848
|
+
* Type guard to check if this instance has storage enabled at compile time.
|
|
39849
|
+
* Use this when you need TypeScript to understand that storage is available.
|
|
39850
|
+
*
|
|
39851
|
+
* @returns True if storage is configured, with type narrowing
|
|
39852
|
+
* @example
|
|
39853
|
+
* ```typescript
|
|
39854
|
+
* if (vana.isStorageEnabled()) {
|
|
39855
|
+
* // TypeScript knows storage is available here
|
|
39856
|
+
* await vana.data.uploadFile(file);
|
|
39857
|
+
* }
|
|
39858
|
+
* ```
|
|
39859
|
+
*/
|
|
39860
|
+
isStorageEnabled() {
|
|
39861
|
+
return this.hasRequiredStorage;
|
|
39862
|
+
}
|
|
39650
39863
|
/**
|
|
39651
39864
|
* Validates the provided configuration object against all requirements.
|
|
39652
39865
|
*
|
|
@@ -39835,23 +40048,23 @@ var VanaCore = class {
|
|
|
39835
40048
|
return this.platform;
|
|
39836
40049
|
}
|
|
39837
40050
|
/**
|
|
39838
|
-
* Encrypts
|
|
40051
|
+
* Encrypts data using the Vana protocol standard encryption.
|
|
39839
40052
|
* This method automatically uses the correct platform adapter for the current environment.
|
|
39840
40053
|
*
|
|
39841
40054
|
* @param data The data to encrypt (string or Blob)
|
|
39842
|
-
* @param
|
|
40055
|
+
* @param key The key to use as encryption key
|
|
39843
40056
|
* @returns The encrypted data as Blob
|
|
39844
40057
|
* @example
|
|
39845
40058
|
* ```typescript
|
|
39846
40059
|
* const encryptionKey = await generateEncryptionKey(walletClient);
|
|
39847
|
-
* const encrypted = await vana.
|
|
40060
|
+
* const encrypted = await vana.encryptBlob("sensitive data", encryptionKey);
|
|
39848
40061
|
* ```
|
|
39849
40062
|
*/
|
|
39850
|
-
async
|
|
39851
|
-
return
|
|
40063
|
+
async encryptBlob(data, key) {
|
|
40064
|
+
return encryptBlobWithSignedKey(data, key, this.platform);
|
|
39852
40065
|
}
|
|
39853
40066
|
/**
|
|
39854
|
-
* Decrypts
|
|
40067
|
+
* Decrypts data that was encrypted using the Vana protocol.
|
|
39855
40068
|
* This method automatically uses the correct platform adapter for the current environment.
|
|
39856
40069
|
*
|
|
39857
40070
|
* @param encryptedData The encrypted data (string or Blob)
|
|
@@ -39860,12 +40073,16 @@ var VanaCore = class {
|
|
|
39860
40073
|
* @example
|
|
39861
40074
|
* ```typescript
|
|
39862
40075
|
* const encryptionKey = await generateEncryptionKey(walletClient);
|
|
39863
|
-
* const decrypted = await vana.
|
|
40076
|
+
* const decrypted = await vana.decryptBlob(encryptedData, encryptionKey);
|
|
39864
40077
|
* const text = await decrypted.text();
|
|
39865
40078
|
* ```
|
|
39866
40079
|
*/
|
|
39867
|
-
async
|
|
39868
|
-
return
|
|
40080
|
+
async decryptBlob(encryptedData, walletSignature) {
|
|
40081
|
+
return decryptBlobWithSignedKey(
|
|
40082
|
+
encryptedData,
|
|
40083
|
+
walletSignature,
|
|
40084
|
+
this.platform
|
|
40085
|
+
);
|
|
39869
40086
|
}
|
|
39870
40087
|
};
|
|
39871
40088
|
|
|
@@ -39896,7 +40113,7 @@ function createValidatedGrant(params) {
|
|
|
39896
40113
|
try {
|
|
39897
40114
|
validateGrant(grantFile, {
|
|
39898
40115
|
schema: true,
|
|
39899
|
-
grantee: params.
|
|
40116
|
+
grantee: params.grantee,
|
|
39900
40117
|
operation: params.operation
|
|
39901
40118
|
});
|
|
39902
40119
|
} catch (error) {
|
|
@@ -40653,31 +40870,22 @@ var ApiClient = class {
|
|
|
40653
40870
|
};
|
|
40654
40871
|
|
|
40655
40872
|
// src/index.browser.ts
|
|
40656
|
-
var
|
|
40657
|
-
/**
|
|
40658
|
-
* Creates a Vana SDK instance configured for browser environments.
|
|
40659
|
-
*
|
|
40660
|
-
* @param config - SDK configuration object (wallet client or chain config)
|
|
40661
|
-
* @example
|
|
40662
|
-
* ```typescript
|
|
40663
|
-
* // With wallet client
|
|
40664
|
-
* const vana = new Vana({ walletClient });
|
|
40665
|
-
*
|
|
40666
|
-
* // With chain configuration
|
|
40667
|
-
* const vana = new Vana({ chainId: 14800, account });
|
|
40668
|
-
* ```
|
|
40669
|
-
*/
|
|
40873
|
+
var VanaBrowserImpl = class extends VanaCore {
|
|
40670
40874
|
constructor(config) {
|
|
40671
40875
|
super(new BrowserPlatformAdapter(), config);
|
|
40672
40876
|
}
|
|
40673
40877
|
};
|
|
40674
|
-
|
|
40878
|
+
function Vana(config) {
|
|
40879
|
+
return new VanaBrowserImpl(config);
|
|
40880
|
+
}
|
|
40881
|
+
var index_browser_default = Vana;
|
|
40675
40882
|
export {
|
|
40676
40883
|
ApiClient,
|
|
40677
40884
|
AsyncQueue,
|
|
40678
40885
|
BaseController,
|
|
40679
40886
|
BlockchainError,
|
|
40680
40887
|
BrowserPlatformAdapter,
|
|
40888
|
+
CallbackStorage,
|
|
40681
40889
|
CircuitBreaker,
|
|
40682
40890
|
ContractFactory,
|
|
40683
40891
|
ContractNotFoundError,
|
|
@@ -40710,14 +40918,15 @@ export {
|
|
|
40710
40918
|
SchemaValidator,
|
|
40711
40919
|
SerializationError,
|
|
40712
40920
|
ServerController,
|
|
40713
|
-
ServerProxyStorage,
|
|
40714
40921
|
ServerUrlMismatchError,
|
|
40715
40922
|
SignatureError,
|
|
40716
40923
|
StorageError,
|
|
40717
40924
|
StorageManager,
|
|
40718
40925
|
UserRejectedRequestError,
|
|
40719
|
-
|
|
40720
|
-
|
|
40926
|
+
Vana,
|
|
40927
|
+
VanaBrowserImpl,
|
|
40928
|
+
VanaCore,
|
|
40929
|
+
VanaCoreFactory,
|
|
40721
40930
|
VanaError,
|
|
40722
40931
|
__contractCache,
|
|
40723
40932
|
chains,
|
|
@@ -40730,13 +40939,13 @@ export {
|
|
|
40730
40939
|
createGrantFile,
|
|
40731
40940
|
createPlatformAdapterSafe,
|
|
40732
40941
|
createValidatedGrant,
|
|
40733
|
-
|
|
40942
|
+
decryptBlobWithSignedKey,
|
|
40734
40943
|
decryptWithPrivateKey,
|
|
40735
40944
|
decryptWithWalletPrivateKey,
|
|
40736
40945
|
index_browser_default as default,
|
|
40737
40946
|
detectPlatform,
|
|
40947
|
+
encryptBlobWithSignedKey,
|
|
40738
40948
|
encryptFileKey,
|
|
40739
|
-
encryptUserData,
|
|
40740
40949
|
encryptWithWalletPublicKey,
|
|
40741
40950
|
extractIpfsHash,
|
|
40742
40951
|
fetchAndValidateSchema,
|
|
@@ -40760,9 +40969,7 @@ export {
|
|
|
40760
40969
|
getPlatformCapabilities,
|
|
40761
40970
|
isAPIResponse,
|
|
40762
40971
|
isGrantExpired,
|
|
40763
|
-
isIdentityServerOutput,
|
|
40764
40972
|
isIpfsUrl,
|
|
40765
|
-
isPersonalServerOutput,
|
|
40766
40973
|
isPlatformSupported,
|
|
40767
40974
|
isReplicateAPIResponse,
|
|
40768
40975
|
moksha,
|