@opendatalabs/vana-sdk 0.1.0-alpha.c17525f → 0.1.0-alpha.cb72de2
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 +207 -436
- package/dist/chains.browser.cjs +4 -1
- package/dist/chains.browser.cjs.map +1 -1
- package/dist/chains.browser.d.cts +2 -1
- package/dist/chains.browser.d.ts +2 -1
- package/dist/chains.browser.js +3 -1
- package/dist/chains.browser.js.map +1 -1
- package/dist/chains.cjs +4 -1
- package/dist/chains.cjs.map +1 -1
- package/dist/chains.d.cts +1 -1
- package/dist/chains.d.ts +1 -1
- package/dist/chains.js +3 -1
- package/dist/chains.js.map +1 -1
- package/dist/chains.node.cjs +4 -1
- package/dist/chains.node.cjs.map +1 -1
- package/dist/chains.node.d.cts +1 -1
- package/dist/chains.node.d.ts +1 -1
- package/dist/chains.node.js +3 -1
- package/dist/chains.node.js.map +1 -1
- package/dist/index.browser.d.ts +5835 -3600
- package/dist/index.browser.js +2059 -924
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.cts +1 -31179
- package/dist/index.node.cjs +2145 -981
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.d.cts +5871 -3608
- package/dist/index.node.d.ts +5871 -3608
- package/dist/index.node.js +2102 -940
- package/dist/index.node.js.map +1 -1
- package/dist/platform.browser.d.ts +69 -0
- package/dist/platform.browser.js +79 -181
- package/dist/platform.browser.js.map +1 -1
- package/dist/platform.cjs +122 -197
- package/dist/platform.cjs.map +1 -1
- package/dist/platform.js +122 -197
- package/dist/platform.js.map +1 -1
- package/dist/platform.node.cjs +122 -197
- package/dist/platform.node.cjs.map +1 -1
- package/dist/platform.node.d.cts +70 -0
- package/dist/platform.node.d.ts +70 -0
- package/dist/platform.node.js +122 -197
- package/dist/platform.node.js.map +1 -1
- package/package.json +24 -18
package/dist/index.browser.js
CHANGED
|
@@ -29,10 +29,27 @@ function parseEncryptedDataBuffer(encryptedBuffer) {
|
|
|
29
29
|
mac: encryptedBuffer.slice(-32)
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
""
|
|
35
|
-
)
|
|
32
|
+
function toBase64(str) {
|
|
33
|
+
if (typeof Buffer !== "undefined") {
|
|
34
|
+
return Buffer.from(str, "utf8").toString("base64");
|
|
35
|
+
} else if (typeof btoa !== "undefined") {
|
|
36
|
+
return btoa(str);
|
|
37
|
+
} else {
|
|
38
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
39
|
+
let result = "";
|
|
40
|
+
let i = 0;
|
|
41
|
+
while (i < str.length) {
|
|
42
|
+
const a = str.charCodeAt(i++);
|
|
43
|
+
const b = i < str.length ? str.charCodeAt(i++) : 0;
|
|
44
|
+
const c = i < str.length ? str.charCodeAt(i++) : 0;
|
|
45
|
+
const bitmap = a << 16 | b << 8 | c;
|
|
46
|
+
result += chars.charAt(bitmap >> 18 & 63);
|
|
47
|
+
result += chars.charAt(bitmap >> 12 & 63);
|
|
48
|
+
result += i - 2 < str.length ? chars.charAt(bitmap >> 6 & 63) : "=";
|
|
49
|
+
result += i - 1 < str.length ? chars.charAt(bitmap & 63) : "=";
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
36
53
|
}
|
|
37
54
|
var init_crypto_utils = __esm({
|
|
38
55
|
"src/platform/shared/crypto-utils.ts"() {
|
|
@@ -84,147 +101,59 @@ var init_error_utils = __esm({
|
|
|
84
101
|
|
|
85
102
|
// src/platform/browser.ts
|
|
86
103
|
import * as openpgp from "openpgp";
|
|
87
|
-
|
|
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;
|
|
104
|
+
var BrowserCryptoAdapter, BrowserPGPAdapter, BrowserHttpAdapter, BrowserCacheAdapter, BrowserPlatformAdapter, browserPlatformAdapter;
|
|
95
105
|
var init_browser = __esm({
|
|
96
106
|
"src/platform/browser.ts"() {
|
|
97
107
|
"use strict";
|
|
98
108
|
init_crypto_utils();
|
|
99
109
|
init_pgp_utils();
|
|
100
110
|
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
111
|
BrowserCryptoAdapter = class {
|
|
191
112
|
async encryptWithPublicKey(data, publicKeyHex) {
|
|
192
113
|
try {
|
|
193
|
-
const
|
|
194
|
-
|
|
114
|
+
const eccrypto = await import("eccrypto-js");
|
|
115
|
+
const publicKeyBuffer = Buffer.from(publicKeyHex, "hex");
|
|
116
|
+
const encrypted = await eccrypto.encrypt(
|
|
117
|
+
publicKeyBuffer,
|
|
118
|
+
Buffer.from(data, "utf8")
|
|
119
|
+
);
|
|
120
|
+
const result = Buffer.concat([
|
|
121
|
+
encrypted.iv,
|
|
122
|
+
encrypted.ephemPublicKey,
|
|
123
|
+
encrypted.ciphertext,
|
|
124
|
+
encrypted.mac
|
|
125
|
+
]);
|
|
126
|
+
return result.toString("hex");
|
|
195
127
|
} catch (error) {
|
|
196
128
|
throw new Error(`Encryption failed: ${error}`);
|
|
197
129
|
}
|
|
198
130
|
}
|
|
199
131
|
async decryptWithPrivateKey(encryptedData, privateKeyHex) {
|
|
200
132
|
try {
|
|
201
|
-
const
|
|
202
|
-
|
|
133
|
+
const eccrypto = await import("eccrypto-js");
|
|
134
|
+
const privateKeyBuffer = processWalletPrivateKey(privateKeyHex);
|
|
135
|
+
const encryptedBuffer = Buffer.from(encryptedData, "hex");
|
|
136
|
+
const { iv, ephemPublicKey, ciphertext, mac } = parseEncryptedDataBuffer(encryptedBuffer);
|
|
137
|
+
const encryptedObj = { iv, ephemPublicKey, ciphertext, mac };
|
|
138
|
+
const decryptedBuffer = await eccrypto.decrypt(
|
|
139
|
+
privateKeyBuffer,
|
|
140
|
+
encryptedObj
|
|
141
|
+
);
|
|
142
|
+
return decryptedBuffer.toString("utf8");
|
|
203
143
|
} catch (error) {
|
|
204
144
|
throw new Error(`Decryption failed: ${error}`);
|
|
205
145
|
}
|
|
206
146
|
}
|
|
207
147
|
async generateKeyPair() {
|
|
208
148
|
try {
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
);
|
|
149
|
+
const eccrypto = await import("eccrypto-js");
|
|
150
|
+
const privateKeyBytes = new Uint8Array(32);
|
|
151
|
+
crypto.getRandomValues(privateKeyBytes);
|
|
152
|
+
const privateKey = Buffer.from(privateKeyBytes);
|
|
153
|
+
const publicKey = eccrypto.getPublicCompressed(privateKey);
|
|
225
154
|
return {
|
|
226
|
-
|
|
227
|
-
|
|
155
|
+
privateKey: privateKey.toString("hex"),
|
|
156
|
+
publicKey: publicKey.toString("hex")
|
|
228
157
|
};
|
|
229
158
|
} catch (error) {
|
|
230
159
|
throw wrapCryptoError("key generation", error);
|
|
@@ -234,65 +163,9 @@ var init_browser = __esm({
|
|
|
234
163
|
try {
|
|
235
164
|
const eccrypto = await import("eccrypto-js");
|
|
236
165
|
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
166
|
const encryptedBuffer = await eccrypto.encrypt(
|
|
290
167
|
uncompressedKey,
|
|
291
|
-
Buffer.from(data)
|
|
292
|
-
{
|
|
293
|
-
iv,
|
|
294
|
-
ephemPrivateKey: ephemeralKey
|
|
295
|
-
}
|
|
168
|
+
Buffer.from(data)
|
|
296
169
|
);
|
|
297
170
|
const result = Buffer.concat([
|
|
298
171
|
encryptedBuffer.iv,
|
|
@@ -407,15 +280,62 @@ var init_browser = __esm({
|
|
|
407
280
|
return fetch(url, options);
|
|
408
281
|
}
|
|
409
282
|
};
|
|
283
|
+
BrowserCacheAdapter = class {
|
|
284
|
+
constructor() {
|
|
285
|
+
__publicField(this, "prefix", "vana_cache_");
|
|
286
|
+
}
|
|
287
|
+
get(key) {
|
|
288
|
+
try {
|
|
289
|
+
if (typeof sessionStorage === "undefined") {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
return sessionStorage.getItem(this.prefix + key);
|
|
293
|
+
} catch {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
set(key, value) {
|
|
298
|
+
try {
|
|
299
|
+
if (typeof sessionStorage !== "undefined") {
|
|
300
|
+
sessionStorage.setItem(this.prefix + key, value);
|
|
301
|
+
}
|
|
302
|
+
} catch {
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
delete(key) {
|
|
306
|
+
try {
|
|
307
|
+
if (typeof sessionStorage !== "undefined") {
|
|
308
|
+
sessionStorage.removeItem(this.prefix + key);
|
|
309
|
+
}
|
|
310
|
+
} catch {
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
clear() {
|
|
314
|
+
try {
|
|
315
|
+
if (typeof sessionStorage === "undefined") {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
const keys = Object.keys(sessionStorage);
|
|
319
|
+
for (const key of keys) {
|
|
320
|
+
if (key.startsWith(this.prefix)) {
|
|
321
|
+
sessionStorage.removeItem(key);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
} catch {
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
};
|
|
410
328
|
BrowserPlatformAdapter = class {
|
|
411
329
|
constructor() {
|
|
412
330
|
__publicField(this, "crypto");
|
|
413
331
|
__publicField(this, "pgp");
|
|
414
332
|
__publicField(this, "http");
|
|
333
|
+
__publicField(this, "cache");
|
|
415
334
|
__publicField(this, "platform", "browser");
|
|
416
335
|
this.crypto = new BrowserCryptoAdapter();
|
|
417
336
|
this.pgp = new BrowserPGPAdapter();
|
|
418
337
|
this.http = new BrowserHttpAdapter();
|
|
338
|
+
this.cache = new BrowserCacheAdapter();
|
|
419
339
|
}
|
|
420
340
|
};
|
|
421
341
|
browserPlatformAdapter = new BrowserPlatformAdapter();
|
|
@@ -539,6 +459,9 @@ function isWalletConfig(config) {
|
|
|
539
459
|
function isChainConfig(config) {
|
|
540
460
|
return "chainId" in config && !("walletClient" in config);
|
|
541
461
|
}
|
|
462
|
+
function hasStorageConfig(config) {
|
|
463
|
+
return config.storage?.providers !== void 0 && Object.keys(config.storage.providers).length > 0;
|
|
464
|
+
}
|
|
542
465
|
|
|
543
466
|
// src/types/chains.ts
|
|
544
467
|
function isVanaChainId(chainId) {
|
|
@@ -562,8 +485,8 @@ var StorageError = class extends Error {
|
|
|
562
485
|
import Ajv from "ajv";
|
|
563
486
|
import addFormats from "ajv-formats";
|
|
564
487
|
|
|
565
|
-
// src/schemas/
|
|
566
|
-
var
|
|
488
|
+
// src/schemas/dataSchema.schema.json
|
|
489
|
+
var dataSchema_schema_default = {
|
|
567
490
|
$id: "https://vana.org/data-schema.json",
|
|
568
491
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
569
492
|
title: "Schema",
|
|
@@ -635,7 +558,7 @@ var SchemaValidator = class {
|
|
|
635
558
|
strict: false
|
|
636
559
|
});
|
|
637
560
|
addFormats(this.ajv);
|
|
638
|
-
this.dataSchemaValidator = this.ajv.compile(
|
|
561
|
+
this.dataSchemaValidator = this.ajv.compile(dataSchema_schema_default);
|
|
639
562
|
}
|
|
640
563
|
/**
|
|
641
564
|
* Validates a data schema against the Vana meta-schema
|
|
@@ -834,55 +757,6 @@ function isReplicateAPIResponse(value) {
|
|
|
834
757
|
obj.status
|
|
835
758
|
);
|
|
836
759
|
}
|
|
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
760
|
function isAPIResponse(value) {
|
|
887
761
|
if (typeof value !== "object" || value === null) return false;
|
|
888
762
|
const obj = value;
|
|
@@ -995,276 +869,45 @@ var PermissionError = class extends VanaError {
|
|
|
995
869
|
}
|
|
996
870
|
};
|
|
997
871
|
|
|
998
|
-
// src/
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
},
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
}
|
|
1037
|
-
},
|
|
1038
|
-
VanaTreasury: {
|
|
1039
|
-
addresses: {
|
|
1040
|
-
14800: "0x94a1E56e555ac48d092f490fB10CDFaB434915eD",
|
|
1041
|
-
1480: "0x94a1E56e555ac48d092f490fB10CDFaB434915eD"
|
|
1042
|
-
}
|
|
1043
|
-
},
|
|
1044
|
-
ComputeInstructionRegistry: {
|
|
1045
|
-
addresses: {
|
|
1046
|
-
14800: "0x5786B12b4c6Ba2bFAF0e77Ed30Bf6d32805563A5",
|
|
1047
|
-
1480: "0x5786B12b4c6Ba2bFAF0e77Ed30Bf6d32805563A5"
|
|
1048
|
-
}
|
|
1049
|
-
},
|
|
1050
|
-
// TEE Pool Variants
|
|
1051
|
-
TeePoolEphemeralStandard: {
|
|
1052
|
-
addresses: {
|
|
1053
|
-
14800: "0xe124bae846D5ec157f75Bd9e68ca87C4d2AB835A",
|
|
1054
|
-
1480: "0xe124bae846D5ec157f75Bd9e68ca87C4d2AB835A"
|
|
1055
|
-
}
|
|
1056
|
-
},
|
|
1057
|
-
TeePoolPersistentStandard: {
|
|
1058
|
-
addresses: {
|
|
1059
|
-
14800: "0xe8bB8d0629651Cf33e0845d743976Dc1f0971d76",
|
|
1060
|
-
1480: "0xe8bB8d0629651Cf33e0845d743976Dc1f0971d76"
|
|
1061
|
-
}
|
|
1062
|
-
},
|
|
1063
|
-
TeePoolPersistentGpu: {
|
|
1064
|
-
addresses: {
|
|
1065
|
-
14800: "0x1c346Cd74f8551f8fa13f3F4b6b8dAE22338E6a9",
|
|
1066
|
-
1480: "0x1c346Cd74f8551f8fa13f3F4b6b8dAE22338E6a9"
|
|
1067
|
-
}
|
|
1068
|
-
},
|
|
1069
|
-
TeePoolDedicatedStandard: {
|
|
1070
|
-
addresses: {
|
|
1071
|
-
14800: "0xf024b7ac5E8417416f53B41ecfa58C8e9396687d",
|
|
1072
|
-
1480: "0xf024b7ac5E8417416f53B41ecfa58C8e9396687d"
|
|
1073
|
-
}
|
|
1074
|
-
},
|
|
1075
|
-
TeePoolDedicatedGpu: {
|
|
1076
|
-
addresses: {
|
|
1077
|
-
14800: "0xB1686FA9620bBf851714d1cB47b8a4Bf4664644E",
|
|
1078
|
-
1480: "0xB1686FA9620bBf851714d1cB47b8a4Bf4664644E"
|
|
1079
|
-
}
|
|
1080
|
-
},
|
|
1081
|
-
// DLP Reward System
|
|
1082
|
-
VanaEpoch: {
|
|
1083
|
-
addresses: {
|
|
1084
|
-
14800: "0x2063cFF0609D59bCCc196E20Eb58A8696a6b15A0",
|
|
1085
|
-
1480: "0x2063cFF0609D59bCCc196E20Eb58A8696a6b15A0"
|
|
1086
|
-
}
|
|
1087
|
-
},
|
|
1088
|
-
DLPRegistry: {
|
|
1089
|
-
addresses: {
|
|
1090
|
-
14800: "0x4D59880a924526d1dD33260552Ff4328b1E18a43",
|
|
1091
|
-
1480: "0x4D59880a924526d1dD33260552Ff4328b1E18a43"
|
|
1092
|
-
}
|
|
1093
|
-
},
|
|
1094
|
-
DLPRegistryTreasury: {
|
|
1095
|
-
addresses: {
|
|
1096
|
-
14800: "0xb12ce1d27bEeFe39b6F0110b1AB77C21Aa0c9F9a",
|
|
1097
|
-
1480: "0xb12ce1d27bEeFe39b6F0110b1AB77C21Aa0c9F9a"
|
|
1098
|
-
}
|
|
1099
|
-
},
|
|
1100
|
-
DLPPerformance: {
|
|
1101
|
-
addresses: {
|
|
1102
|
-
14800: "0x847715C7DB37cF286611182Be0bD333cbfa29cc1",
|
|
1103
|
-
1480: "0x847715C7DB37cF286611182Be0bD333cbfa29cc1"
|
|
1104
|
-
}
|
|
1105
|
-
},
|
|
1106
|
-
DLPRewardDeployer: {
|
|
1107
|
-
addresses: {
|
|
1108
|
-
14800: "0xEFD0F9Ba9De70586b7c4189971cF754adC923B04",
|
|
1109
|
-
1480: "0xEFD0F9Ba9De70586b7c4189971cF754adC923B04"
|
|
1110
|
-
}
|
|
1111
|
-
},
|
|
1112
|
-
DLPRewardDeployerTreasury: {
|
|
1113
|
-
addresses: {
|
|
1114
|
-
14800: "0xb547ca8Fe4990fe330FeAeb1C2EBb42F925Af5b8",
|
|
1115
|
-
1480: "0xb547ca8Fe4990fe330FeAeb1C2EBb42F925Af5b8"
|
|
1116
|
-
}
|
|
1117
|
-
},
|
|
1118
|
-
DLPRewardSwap: {
|
|
1119
|
-
addresses: {
|
|
1120
|
-
14800: "0x7c6862C46830F0fc3bF3FF509EA1bD0EE7267fB0",
|
|
1121
|
-
1480: "0x7c6862C46830F0fc3bF3FF509EA1bD0EE7267fB0"
|
|
1122
|
-
}
|
|
1123
|
-
},
|
|
1124
|
-
SwapHelper: {
|
|
1125
|
-
addresses: {
|
|
1126
|
-
14800: "0x55D5e6F73326315bF2E091e97F04f0770e5C54e2",
|
|
1127
|
-
1480: "0x55D5e6F73326315bF2E091e97F04f0770e5C54e2"
|
|
1128
|
-
}
|
|
1129
|
-
},
|
|
1130
|
-
// VanaPool (Staking)
|
|
1131
|
-
VanaPoolStaking: {
|
|
1132
|
-
addresses: {
|
|
1133
|
-
14800: "0x641C18E2F286c86f96CE95C8ec1EB9fC0415Ca0e",
|
|
1134
|
-
1480: "0x641C18E2F286c86f96CE95C8ec1EB9fC0415Ca0e"
|
|
1135
|
-
}
|
|
1136
|
-
},
|
|
1137
|
-
VanaPoolEntity: {
|
|
1138
|
-
addresses: {
|
|
1139
|
-
14800: "0x44f20490A82e1f1F1cC25Dd3BA8647034eDdce30",
|
|
1140
|
-
1480: "0x44f20490A82e1f1F1cC25Dd3BA8647034eDdce30"
|
|
1141
|
-
}
|
|
1142
|
-
},
|
|
1143
|
-
VanaPoolTreasury: {
|
|
1144
|
-
addresses: {
|
|
1145
|
-
14800: "0x143BE72CF2541604A7691933CAccd6D9cC17c003",
|
|
1146
|
-
1480: "0x143BE72CF2541604A7691933CAccd6D9cC17c003"
|
|
1147
|
-
}
|
|
1148
|
-
},
|
|
1149
|
-
// DLP Deployment Contracts
|
|
1150
|
-
DAT: {
|
|
1151
|
-
addresses: {
|
|
1152
|
-
14800: "0xA706b93ccED89f13340673889e29F0a5cd84212d",
|
|
1153
|
-
1480: "0xA706b93ccED89f13340673889e29F0a5cd84212d"
|
|
1154
|
-
}
|
|
1155
|
-
},
|
|
1156
|
-
DATFactory: {
|
|
1157
|
-
addresses: {
|
|
1158
|
-
14800: "0x40f8bccF35a75ecef63BC3B1B3E06ffEB9220644",
|
|
1159
|
-
1480: "0x40f8bccF35a75ecef63BC3B1B3E06ffEB9220644"
|
|
1160
|
-
}
|
|
1161
|
-
},
|
|
1162
|
-
DATPausable: {
|
|
1163
|
-
addresses: {
|
|
1164
|
-
14800: "0xe69FE86f0B95cC2f8416Fe22815c85DC8887e76e",
|
|
1165
|
-
1480: "0xe69FE86f0B95cC2f8416Fe22815c85DC8887e76e"
|
|
1166
|
-
}
|
|
1167
|
-
},
|
|
1168
|
-
DATVotes: {
|
|
1169
|
-
addresses: {
|
|
1170
|
-
14800: "0xaE04c8A77E9B27869eb563720524A9aE0baf1831",
|
|
1171
|
-
1480: "0xaE04c8A77E9B27869eb563720524A9aE0baf1831"
|
|
1172
|
-
}
|
|
1173
|
-
},
|
|
1174
|
-
// Utility Contracts (no ABIs in SDK)
|
|
1175
|
-
Multicall3: {
|
|
1176
|
-
addresses: {
|
|
1177
|
-
14800: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E",
|
|
1178
|
-
1480: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E"
|
|
1179
|
-
}
|
|
1180
|
-
},
|
|
1181
|
-
Multisend: {
|
|
1182
|
-
addresses: {
|
|
1183
|
-
14800: "0x8807e8BCDFbaA8c2761760f3FBA37F6f7F2C5b2d",
|
|
1184
|
-
1480: "0x8807e8BCDFbaA8c2761760f3FBA37F6f7F2C5b2d"
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
};
|
|
1188
|
-
var LEGACY_CONTRACTS = {
|
|
1189
|
-
// DEPRECATED: Original Intel SGX TeePool (PRO-347)
|
|
1190
|
-
TeePool: {
|
|
1191
|
-
addresses: {
|
|
1192
|
-
14800: "0x3c92fD91639b41f13338CE62f19131e7d19eaa0D",
|
|
1193
|
-
1480: "0x3c92fD91639b41f13338CE62f19131e7d19eaa0D"
|
|
1194
|
-
}
|
|
1195
|
-
},
|
|
1196
|
-
// DEPRECATED: DLPRoot system (replaced by VanaPool + DLPRewards)
|
|
1197
|
-
DLPRootEpoch: {
|
|
1198
|
-
addresses: {
|
|
1199
|
-
14800: "0xc3d176cF6BccFCB9225b53B87a95147218e1537F",
|
|
1200
|
-
1480: "0xc3d176cF6BccFCB9225b53B87a95147218e1537F"
|
|
1201
|
-
}
|
|
1202
|
-
},
|
|
1203
|
-
DLPRootCore: {
|
|
1204
|
-
addresses: {
|
|
1205
|
-
14800: "0x0aBa5e28228c323A67712101d61a54d4ff5720FD",
|
|
1206
|
-
1480: "0x0aBa5e28228c323A67712101d61a54d4ff5720FD"
|
|
1207
|
-
}
|
|
1208
|
-
},
|
|
1209
|
-
DLPRoot: {
|
|
1210
|
-
addresses: {
|
|
1211
|
-
14800: "0xff14346dF2B8Fd0c95BF34f1c92e49417b508AD5",
|
|
1212
|
-
1480: "0xff14346dF2B8Fd0c95BF34f1c92e49417b508AD5"
|
|
1213
|
-
}
|
|
1214
|
-
},
|
|
1215
|
-
DLPRootMetrics: {
|
|
1216
|
-
addresses: {
|
|
1217
|
-
14800: "0xbb532917B6407c060Afd9Cb7d53527eCb91d6662",
|
|
1218
|
-
1480: "0xbb532917B6407c060Afd9Cb7d53527eCb91d6662"
|
|
1219
|
-
}
|
|
1220
|
-
},
|
|
1221
|
-
DLPRootStakesTreasury: {
|
|
1222
|
-
addresses: {
|
|
1223
|
-
14800: "0x52c3260ED5C235fcA43524CF508e29c897318775",
|
|
1224
|
-
1480: "0x52c3260ED5C235fcA43524CF508e29c897318775"
|
|
1225
|
-
}
|
|
1226
|
-
},
|
|
1227
|
-
DLPRootRewardsTreasury: {
|
|
1228
|
-
addresses: {
|
|
1229
|
-
14800: "0xDBFb6B8b9E2eCAEbdE64d665cD553dB81e524479",
|
|
1230
|
-
1480: "0xDBFb6B8b9E2eCAEbdE64d665cD553dB81e524479"
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
};
|
|
1234
|
-
var CONTRACT_ADDRESSES = {
|
|
1235
|
-
14800: Object.fromEntries(
|
|
1236
|
-
Object.entries(CONTRACTS).map(([name, info]) => [name, info.addresses[14800]]).filter(([, addr]) => addr)
|
|
1237
|
-
),
|
|
1238
|
-
1480: Object.fromEntries(
|
|
1239
|
-
Object.entries(CONTRACTS).map(([name, info]) => [name, info.addresses[1480]]).filter(([, addr]) => addr)
|
|
1240
|
-
)
|
|
1241
|
-
};
|
|
1242
|
-
var UTILITY_ADDRESSES = {
|
|
1243
|
-
14800: {
|
|
1244
|
-
Multicall3: CONTRACTS.Multicall3.addresses[14800],
|
|
1245
|
-
Multisend: CONTRACTS.Multisend.addresses[14800]
|
|
1246
|
-
},
|
|
1247
|
-
1480: {
|
|
1248
|
-
Multicall3: CONTRACTS.Multicall3.addresses[1480],
|
|
1249
|
-
Multisend: CONTRACTS.Multisend.addresses[1480]
|
|
1250
|
-
}
|
|
1251
|
-
};
|
|
1252
|
-
var LEGACY_ADDRESSES = {
|
|
1253
|
-
14800: Object.fromEntries(
|
|
1254
|
-
Object.entries(LEGACY_CONTRACTS).map(([name, info]) => [name, info.addresses[14800]]).filter(([, addr]) => addr)
|
|
1255
|
-
),
|
|
1256
|
-
1480: Object.fromEntries(
|
|
1257
|
-
Object.entries(LEGACY_CONTRACTS).map(([name, info]) => [name, info.addresses[1480]]).filter(([, addr]) => addr)
|
|
1258
|
-
)
|
|
1259
|
-
};
|
|
1260
|
-
var getContractAddress = (chainId, contract) => {
|
|
1261
|
-
const contractAddress = CONTRACT_ADDRESSES[chainId]?.[contract];
|
|
1262
|
-
if (!contractAddress) {
|
|
1263
|
-
throw new Error(
|
|
1264
|
-
`Contract address not found for ${contract} on chain ${chainId}`
|
|
1265
|
-
);
|
|
872
|
+
// src/utils/transactionParsing.ts
|
|
873
|
+
import { parseEventLogs } from "viem";
|
|
874
|
+
|
|
875
|
+
// src/config/eventMappings.ts
|
|
876
|
+
var EVENT_MAPPINGS = {
|
|
877
|
+
// Permission operations
|
|
878
|
+
grant: {
|
|
879
|
+
contract: "DataPermissions",
|
|
880
|
+
event: "PermissionAdded"
|
|
881
|
+
},
|
|
882
|
+
revoke: {
|
|
883
|
+
contract: "DataPermissions",
|
|
884
|
+
event: "PermissionRevoked"
|
|
885
|
+
},
|
|
886
|
+
trustServer: {
|
|
887
|
+
contract: "DataPermissions",
|
|
888
|
+
event: "ServerTrusted"
|
|
889
|
+
},
|
|
890
|
+
untrustServer: {
|
|
891
|
+
contract: "DataPermissions",
|
|
892
|
+
event: "ServerUntrusted"
|
|
893
|
+
},
|
|
894
|
+
// Data registry operations
|
|
895
|
+
addFile: {
|
|
896
|
+
contract: "DataRegistry",
|
|
897
|
+
event: "FileAdded"
|
|
898
|
+
},
|
|
899
|
+
addRefinement: {
|
|
900
|
+
contract: "DataRegistry",
|
|
901
|
+
event: "RefinementAdded"
|
|
902
|
+
},
|
|
903
|
+
updateRefinement: {
|
|
904
|
+
contract: "DataRegistry",
|
|
905
|
+
event: "RefinementUpdated"
|
|
906
|
+
},
|
|
907
|
+
addFilePermission: {
|
|
908
|
+
contract: "DataRegistry",
|
|
909
|
+
event: "PermissionGranted"
|
|
1266
910
|
}
|
|
1267
|
-
return contractAddress;
|
|
1268
911
|
};
|
|
1269
912
|
|
|
1270
913
|
// src/abi/ComputeEngineImplementation.ts
|
|
@@ -7913,6 +7556,12 @@ var DataRefinerRegistryABI = [
|
|
|
7913
7556
|
name: "schemaId",
|
|
7914
7557
|
type: "uint256"
|
|
7915
7558
|
},
|
|
7559
|
+
{
|
|
7560
|
+
indexed: false,
|
|
7561
|
+
internalType: "string",
|
|
7562
|
+
name: "schemaDefinitionUrl",
|
|
7563
|
+
type: "string"
|
|
7564
|
+
},
|
|
7916
7565
|
{
|
|
7917
7566
|
indexed: false,
|
|
7918
7567
|
internalType: "string",
|
|
@@ -8016,7 +7665,7 @@ var DataRefinerRegistryABI = [
|
|
|
8016
7665
|
{
|
|
8017
7666
|
indexed: false,
|
|
8018
7667
|
internalType: "string",
|
|
8019
|
-
name: "
|
|
7668
|
+
name: "dialect",
|
|
8020
7669
|
type: "string"
|
|
8021
7670
|
},
|
|
8022
7671
|
{
|
|
@@ -8112,6 +7761,40 @@ var DataRefinerRegistryABI = [
|
|
|
8112
7761
|
stateMutability: "nonpayable",
|
|
8113
7762
|
type: "function"
|
|
8114
7763
|
},
|
|
7764
|
+
{
|
|
7765
|
+
inputs: [
|
|
7766
|
+
{
|
|
7767
|
+
internalType: "uint256",
|
|
7768
|
+
name: "dlpId",
|
|
7769
|
+
type: "uint256"
|
|
7770
|
+
},
|
|
7771
|
+
{
|
|
7772
|
+
internalType: "string",
|
|
7773
|
+
name: "name",
|
|
7774
|
+
type: "string"
|
|
7775
|
+
},
|
|
7776
|
+
{
|
|
7777
|
+
internalType: "string",
|
|
7778
|
+
name: "schemaDefinitionUrl",
|
|
7779
|
+
type: "string"
|
|
7780
|
+
},
|
|
7781
|
+
{
|
|
7782
|
+
internalType: "string",
|
|
7783
|
+
name: "refinementInstructionUrl",
|
|
7784
|
+
type: "string"
|
|
7785
|
+
}
|
|
7786
|
+
],
|
|
7787
|
+
name: "addRefiner",
|
|
7788
|
+
outputs: [
|
|
7789
|
+
{
|
|
7790
|
+
internalType: "uint256",
|
|
7791
|
+
name: "",
|
|
7792
|
+
type: "uint256"
|
|
7793
|
+
}
|
|
7794
|
+
],
|
|
7795
|
+
stateMutability: "nonpayable",
|
|
7796
|
+
type: "function"
|
|
7797
|
+
},
|
|
8115
7798
|
{
|
|
8116
7799
|
inputs: [
|
|
8117
7800
|
{
|
|
@@ -8135,7 +7818,7 @@ var DataRefinerRegistryABI = [
|
|
|
8135
7818
|
type: "string"
|
|
8136
7819
|
}
|
|
8137
7820
|
],
|
|
8138
|
-
name: "
|
|
7821
|
+
name: "addRefinerWithSchemaId",
|
|
8139
7822
|
outputs: [
|
|
8140
7823
|
{
|
|
8141
7824
|
internalType: "uint256",
|
|
@@ -8155,7 +7838,7 @@ var DataRefinerRegistryABI = [
|
|
|
8155
7838
|
},
|
|
8156
7839
|
{
|
|
8157
7840
|
internalType: "string",
|
|
8158
|
-
name: "
|
|
7841
|
+
name: "dialect",
|
|
8159
7842
|
type: "string"
|
|
8160
7843
|
},
|
|
8161
7844
|
{
|
|
@@ -8518,7 +8201,7 @@ var DataRefinerRegistryABI = [
|
|
|
8518
8201
|
},
|
|
8519
8202
|
{
|
|
8520
8203
|
internalType: "string",
|
|
8521
|
-
name: "
|
|
8204
|
+
name: "dialect",
|
|
8522
8205
|
type: "string"
|
|
8523
8206
|
},
|
|
8524
8207
|
{
|
|
@@ -33431,11 +33114,337 @@ function getAbi(contract) {
|
|
|
33431
33114
|
return abi;
|
|
33432
33115
|
}
|
|
33433
33116
|
|
|
33117
|
+
// src/utils/transactionParsing.ts
|
|
33118
|
+
async function parseTransactionResult(context, hash, operation) {
|
|
33119
|
+
const mapping = EVENT_MAPPINGS[operation];
|
|
33120
|
+
try {
|
|
33121
|
+
console.debug(`\u{1F50D} Parsing ${operation} transaction: ${hash}`);
|
|
33122
|
+
const receipt = await context.publicClient.waitForTransactionReceipt({
|
|
33123
|
+
hash,
|
|
33124
|
+
timeout: 3e4
|
|
33125
|
+
// 30 second timeout
|
|
33126
|
+
});
|
|
33127
|
+
console.debug(`\u2705 Transaction confirmed in block ${receipt.blockNumber}`);
|
|
33128
|
+
const abi = getAbi(mapping.contract);
|
|
33129
|
+
const events = parseEventLogs({
|
|
33130
|
+
logs: receipt.logs,
|
|
33131
|
+
abi,
|
|
33132
|
+
eventName: mapping.event,
|
|
33133
|
+
strict: true
|
|
33134
|
+
// Only return logs that conform to the ABI
|
|
33135
|
+
});
|
|
33136
|
+
if (events.length === 0) {
|
|
33137
|
+
throw new BlockchainError(
|
|
33138
|
+
`No ${mapping.event} event found in transaction ${hash}. Transaction may have failed or reverted.`
|
|
33139
|
+
);
|
|
33140
|
+
}
|
|
33141
|
+
if (events.length > 1) {
|
|
33142
|
+
console.warn(
|
|
33143
|
+
`\u26A0\uFE0F Multiple ${mapping.event} events found in transaction ${hash}. Using the first one.`
|
|
33144
|
+
);
|
|
33145
|
+
}
|
|
33146
|
+
const event = events[0];
|
|
33147
|
+
console.debug(`\u{1F389} Found ${mapping.event} event with args:`, event.args);
|
|
33148
|
+
return {
|
|
33149
|
+
...event.args,
|
|
33150
|
+
transactionHash: hash,
|
|
33151
|
+
blockNumber: receipt.blockNumber,
|
|
33152
|
+
gasUsed: receipt.gasUsed
|
|
33153
|
+
};
|
|
33154
|
+
} catch (error) {
|
|
33155
|
+
if (error instanceof BlockchainError || error instanceof NetworkError) {
|
|
33156
|
+
throw error;
|
|
33157
|
+
}
|
|
33158
|
+
if (error instanceof Error && error.message.includes("timeout")) {
|
|
33159
|
+
throw new NetworkError(
|
|
33160
|
+
`Transaction ${hash} confirmation timeout after 30 seconds. The transaction may still be pending.`,
|
|
33161
|
+
error
|
|
33162
|
+
);
|
|
33163
|
+
}
|
|
33164
|
+
throw new BlockchainError(
|
|
33165
|
+
`Failed to parse ${operation} transaction ${hash}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
33166
|
+
error
|
|
33167
|
+
);
|
|
33168
|
+
}
|
|
33169
|
+
}
|
|
33170
|
+
|
|
33171
|
+
// src/config/addresses.ts
|
|
33172
|
+
var CONTRACTS = {
|
|
33173
|
+
// Core Platform Contracts
|
|
33174
|
+
DataPermissions: {
|
|
33175
|
+
addresses: {
|
|
33176
|
+
14800: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de",
|
|
33177
|
+
1480: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de"
|
|
33178
|
+
}
|
|
33179
|
+
},
|
|
33180
|
+
DataRegistry: {
|
|
33181
|
+
addresses: {
|
|
33182
|
+
14800: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C",
|
|
33183
|
+
1480: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C"
|
|
33184
|
+
}
|
|
33185
|
+
},
|
|
33186
|
+
TeePoolPhala: {
|
|
33187
|
+
addresses: {
|
|
33188
|
+
14800: "0xE8EC6BD73b23Ad40E6B9a6f4bD343FAc411bD99A",
|
|
33189
|
+
1480: "0xE8EC6BD73b23Ad40E6B9a6f4bD343FAc411bD99A"
|
|
33190
|
+
}
|
|
33191
|
+
},
|
|
33192
|
+
ComputeEngine: {
|
|
33193
|
+
addresses: {
|
|
33194
|
+
14800: "0xb2BFe33FA420c45F1Cf1287542ad81ae935447bd",
|
|
33195
|
+
1480: "0xb2BFe33FA420c45F1Cf1287542ad81ae935447bd"
|
|
33196
|
+
}
|
|
33197
|
+
},
|
|
33198
|
+
// Data Access Infrastructure
|
|
33199
|
+
DataRefinerRegistry: {
|
|
33200
|
+
addresses: {
|
|
33201
|
+
14800: "0x93c3EF89369fDcf08Be159D9DeF0F18AB6Be008c",
|
|
33202
|
+
1480: "0x93c3EF89369fDcf08Be159D9DeF0F18AB6Be008c"
|
|
33203
|
+
}
|
|
33204
|
+
},
|
|
33205
|
+
QueryEngine: {
|
|
33206
|
+
addresses: {
|
|
33207
|
+
14800: "0xd25Eb66EA2452cf3238A2eC6C1FD1B7F5B320490",
|
|
33208
|
+
1480: "0xd25Eb66EA2452cf3238A2eC6C1FD1B7F5B320490"
|
|
33209
|
+
}
|
|
33210
|
+
},
|
|
33211
|
+
VanaTreasury: {
|
|
33212
|
+
addresses: {
|
|
33213
|
+
14800: "0x94a1E56e555ac48d092f490fB10CDFaB434915eD",
|
|
33214
|
+
1480: "0x94a1E56e555ac48d092f490fB10CDFaB434915eD"
|
|
33215
|
+
}
|
|
33216
|
+
},
|
|
33217
|
+
ComputeInstructionRegistry: {
|
|
33218
|
+
addresses: {
|
|
33219
|
+
14800: "0x5786B12b4c6Ba2bFAF0e77Ed30Bf6d32805563A5",
|
|
33220
|
+
1480: "0x5786B12b4c6Ba2bFAF0e77Ed30Bf6d32805563A5"
|
|
33221
|
+
}
|
|
33222
|
+
},
|
|
33223
|
+
// TEE Pool Variants
|
|
33224
|
+
TeePoolEphemeralStandard: {
|
|
33225
|
+
addresses: {
|
|
33226
|
+
14800: "0xe124bae846D5ec157f75Bd9e68ca87C4d2AB835A",
|
|
33227
|
+
1480: "0xe124bae846D5ec157f75Bd9e68ca87C4d2AB835A"
|
|
33228
|
+
}
|
|
33229
|
+
},
|
|
33230
|
+
TeePoolPersistentStandard: {
|
|
33231
|
+
addresses: {
|
|
33232
|
+
14800: "0xe8bB8d0629651Cf33e0845d743976Dc1f0971d76",
|
|
33233
|
+
1480: "0xe8bB8d0629651Cf33e0845d743976Dc1f0971d76"
|
|
33234
|
+
}
|
|
33235
|
+
},
|
|
33236
|
+
TeePoolPersistentGpu: {
|
|
33237
|
+
addresses: {
|
|
33238
|
+
14800: "0x1c346Cd74f8551f8fa13f3F4b6b8dAE22338E6a9",
|
|
33239
|
+
1480: "0x1c346Cd74f8551f8fa13f3F4b6b8dAE22338E6a9"
|
|
33240
|
+
}
|
|
33241
|
+
},
|
|
33242
|
+
TeePoolDedicatedStandard: {
|
|
33243
|
+
addresses: {
|
|
33244
|
+
14800: "0xf024b7ac5E8417416f53B41ecfa58C8e9396687d",
|
|
33245
|
+
1480: "0xf024b7ac5E8417416f53B41ecfa58C8e9396687d"
|
|
33246
|
+
}
|
|
33247
|
+
},
|
|
33248
|
+
TeePoolDedicatedGpu: {
|
|
33249
|
+
addresses: {
|
|
33250
|
+
14800: "0xB1686FA9620bBf851714d1cB47b8a4Bf4664644E",
|
|
33251
|
+
1480: "0xB1686FA9620bBf851714d1cB47b8a4Bf4664644E"
|
|
33252
|
+
}
|
|
33253
|
+
},
|
|
33254
|
+
// DLP Reward System
|
|
33255
|
+
VanaEpoch: {
|
|
33256
|
+
addresses: {
|
|
33257
|
+
14800: "0x2063cFF0609D59bCCc196E20Eb58A8696a6b15A0",
|
|
33258
|
+
1480: "0x2063cFF0609D59bCCc196E20Eb58A8696a6b15A0"
|
|
33259
|
+
}
|
|
33260
|
+
},
|
|
33261
|
+
DLPRegistry: {
|
|
33262
|
+
addresses: {
|
|
33263
|
+
14800: "0x4D59880a924526d1dD33260552Ff4328b1E18a43",
|
|
33264
|
+
1480: "0x4D59880a924526d1dD33260552Ff4328b1E18a43"
|
|
33265
|
+
}
|
|
33266
|
+
},
|
|
33267
|
+
DLPRegistryTreasury: {
|
|
33268
|
+
addresses: {
|
|
33269
|
+
14800: "0xb12ce1d27bEeFe39b6F0110b1AB77C21Aa0c9F9a",
|
|
33270
|
+
1480: "0xb12ce1d27bEeFe39b6F0110b1AB77C21Aa0c9F9a"
|
|
33271
|
+
}
|
|
33272
|
+
},
|
|
33273
|
+
DLPPerformance: {
|
|
33274
|
+
addresses: {
|
|
33275
|
+
14800: "0x847715C7DB37cF286611182Be0bD333cbfa29cc1",
|
|
33276
|
+
1480: "0x847715C7DB37cF286611182Be0bD333cbfa29cc1"
|
|
33277
|
+
}
|
|
33278
|
+
},
|
|
33279
|
+
DLPRewardDeployer: {
|
|
33280
|
+
addresses: {
|
|
33281
|
+
14800: "0xEFD0F9Ba9De70586b7c4189971cF754adC923B04",
|
|
33282
|
+
1480: "0xEFD0F9Ba9De70586b7c4189971cF754adC923B04"
|
|
33283
|
+
}
|
|
33284
|
+
},
|
|
33285
|
+
DLPRewardDeployerTreasury: {
|
|
33286
|
+
addresses: {
|
|
33287
|
+
14800: "0xb547ca8Fe4990fe330FeAeb1C2EBb42F925Af5b8",
|
|
33288
|
+
1480: "0xb547ca8Fe4990fe330FeAeb1C2EBb42F925Af5b8"
|
|
33289
|
+
}
|
|
33290
|
+
},
|
|
33291
|
+
DLPRewardSwap: {
|
|
33292
|
+
addresses: {
|
|
33293
|
+
14800: "0x7c6862C46830F0fc3bF3FF509EA1bD0EE7267fB0",
|
|
33294
|
+
1480: "0x7c6862C46830F0fc3bF3FF509EA1bD0EE7267fB0"
|
|
33295
|
+
}
|
|
33296
|
+
},
|
|
33297
|
+
SwapHelper: {
|
|
33298
|
+
addresses: {
|
|
33299
|
+
14800: "0x55D5e6F73326315bF2E091e97F04f0770e5C54e2",
|
|
33300
|
+
1480: "0x55D5e6F73326315bF2E091e97F04f0770e5C54e2"
|
|
33301
|
+
}
|
|
33302
|
+
},
|
|
33303
|
+
// VanaPool (Staking)
|
|
33304
|
+
VanaPoolStaking: {
|
|
33305
|
+
addresses: {
|
|
33306
|
+
14800: "0x641C18E2F286c86f96CE95C8ec1EB9fC0415Ca0e",
|
|
33307
|
+
1480: "0x641C18E2F286c86f96CE95C8ec1EB9fC0415Ca0e"
|
|
33308
|
+
}
|
|
33309
|
+
},
|
|
33310
|
+
VanaPoolEntity: {
|
|
33311
|
+
addresses: {
|
|
33312
|
+
14800: "0x44f20490A82e1f1F1cC25Dd3BA8647034eDdce30",
|
|
33313
|
+
1480: "0x44f20490A82e1f1F1cC25Dd3BA8647034eDdce30"
|
|
33314
|
+
}
|
|
33315
|
+
},
|
|
33316
|
+
VanaPoolTreasury: {
|
|
33317
|
+
addresses: {
|
|
33318
|
+
14800: "0x143BE72CF2541604A7691933CAccd6D9cC17c003",
|
|
33319
|
+
1480: "0x143BE72CF2541604A7691933CAccd6D9cC17c003"
|
|
33320
|
+
}
|
|
33321
|
+
},
|
|
33322
|
+
// DLP Deployment Contracts
|
|
33323
|
+
DAT: {
|
|
33324
|
+
addresses: {
|
|
33325
|
+
14800: "0xA706b93ccED89f13340673889e29F0a5cd84212d",
|
|
33326
|
+
1480: "0xA706b93ccED89f13340673889e29F0a5cd84212d"
|
|
33327
|
+
}
|
|
33328
|
+
},
|
|
33329
|
+
DATFactory: {
|
|
33330
|
+
addresses: {
|
|
33331
|
+
14800: "0x40f8bccF35a75ecef63BC3B1B3E06ffEB9220644",
|
|
33332
|
+
1480: "0x40f8bccF35a75ecef63BC3B1B3E06ffEB9220644"
|
|
33333
|
+
}
|
|
33334
|
+
},
|
|
33335
|
+
DATPausable: {
|
|
33336
|
+
addresses: {
|
|
33337
|
+
14800: "0xe69FE86f0B95cC2f8416Fe22815c85DC8887e76e",
|
|
33338
|
+
1480: "0xe69FE86f0B95cC2f8416Fe22815c85DC8887e76e"
|
|
33339
|
+
}
|
|
33340
|
+
},
|
|
33341
|
+
DATVotes: {
|
|
33342
|
+
addresses: {
|
|
33343
|
+
14800: "0xaE04c8A77E9B27869eb563720524A9aE0baf1831",
|
|
33344
|
+
1480: "0xaE04c8A77E9B27869eb563720524A9aE0baf1831"
|
|
33345
|
+
}
|
|
33346
|
+
},
|
|
33347
|
+
// Utility Contracts (no ABIs in SDK)
|
|
33348
|
+
Multicall3: {
|
|
33349
|
+
addresses: {
|
|
33350
|
+
14800: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E",
|
|
33351
|
+
1480: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E"
|
|
33352
|
+
}
|
|
33353
|
+
},
|
|
33354
|
+
Multisend: {
|
|
33355
|
+
addresses: {
|
|
33356
|
+
14800: "0x8807e8BCDFbaA8c2761760f3FBA37F6f7F2C5b2d",
|
|
33357
|
+
1480: "0x8807e8BCDFbaA8c2761760f3FBA37F6f7F2C5b2d"
|
|
33358
|
+
}
|
|
33359
|
+
}
|
|
33360
|
+
};
|
|
33361
|
+
var LEGACY_CONTRACTS = {
|
|
33362
|
+
// DEPRECATED: Original Intel SGX TeePool (PRO-347)
|
|
33363
|
+
TeePool: {
|
|
33364
|
+
addresses: {
|
|
33365
|
+
14800: "0x3c92fD91639b41f13338CE62f19131e7d19eaa0D",
|
|
33366
|
+
1480: "0x3c92fD91639b41f13338CE62f19131e7d19eaa0D"
|
|
33367
|
+
}
|
|
33368
|
+
},
|
|
33369
|
+
// DEPRECATED: DLPRoot system (replaced by VanaPool + DLPRewards)
|
|
33370
|
+
DLPRootEpoch: {
|
|
33371
|
+
addresses: {
|
|
33372
|
+
14800: "0xc3d176cF6BccFCB9225b53B87a95147218e1537F",
|
|
33373
|
+
1480: "0xc3d176cF6BccFCB9225b53B87a95147218e1537F"
|
|
33374
|
+
}
|
|
33375
|
+
},
|
|
33376
|
+
DLPRootCore: {
|
|
33377
|
+
addresses: {
|
|
33378
|
+
14800: "0x0aBa5e28228c323A67712101d61a54d4ff5720FD",
|
|
33379
|
+
1480: "0x0aBa5e28228c323A67712101d61a54d4ff5720FD"
|
|
33380
|
+
}
|
|
33381
|
+
},
|
|
33382
|
+
DLPRoot: {
|
|
33383
|
+
addresses: {
|
|
33384
|
+
14800: "0xff14346dF2B8Fd0c95BF34f1c92e49417b508AD5",
|
|
33385
|
+
1480: "0xff14346dF2B8Fd0c95BF34f1c92e49417b508AD5"
|
|
33386
|
+
}
|
|
33387
|
+
},
|
|
33388
|
+
DLPRootMetrics: {
|
|
33389
|
+
addresses: {
|
|
33390
|
+
14800: "0xbb532917B6407c060Afd9Cb7d53527eCb91d6662",
|
|
33391
|
+
1480: "0xbb532917B6407c060Afd9Cb7d53527eCb91d6662"
|
|
33392
|
+
}
|
|
33393
|
+
},
|
|
33394
|
+
DLPRootStakesTreasury: {
|
|
33395
|
+
addresses: {
|
|
33396
|
+
14800: "0x52c3260ED5C235fcA43524CF508e29c897318775",
|
|
33397
|
+
1480: "0x52c3260ED5C235fcA43524CF508e29c897318775"
|
|
33398
|
+
}
|
|
33399
|
+
},
|
|
33400
|
+
DLPRootRewardsTreasury: {
|
|
33401
|
+
addresses: {
|
|
33402
|
+
14800: "0xDBFb6B8b9E2eCAEbdE64d665cD553dB81e524479",
|
|
33403
|
+
1480: "0xDBFb6B8b9E2eCAEbdE64d665cD553dB81e524479"
|
|
33404
|
+
}
|
|
33405
|
+
}
|
|
33406
|
+
};
|
|
33407
|
+
var CONTRACT_ADDRESSES = {
|
|
33408
|
+
14800: Object.fromEntries(
|
|
33409
|
+
Object.entries(CONTRACTS).map(([name, info]) => [name, info.addresses[14800]]).filter(([, addr]) => addr)
|
|
33410
|
+
),
|
|
33411
|
+
1480: Object.fromEntries(
|
|
33412
|
+
Object.entries(CONTRACTS).map(([name, info]) => [name, info.addresses[1480]]).filter(([, addr]) => addr)
|
|
33413
|
+
)
|
|
33414
|
+
};
|
|
33415
|
+
var UTILITY_ADDRESSES = {
|
|
33416
|
+
14800: {
|
|
33417
|
+
Multicall3: CONTRACTS.Multicall3.addresses[14800],
|
|
33418
|
+
Multisend: CONTRACTS.Multisend.addresses[14800]
|
|
33419
|
+
},
|
|
33420
|
+
1480: {
|
|
33421
|
+
Multicall3: CONTRACTS.Multicall3.addresses[1480],
|
|
33422
|
+
Multisend: CONTRACTS.Multisend.addresses[1480]
|
|
33423
|
+
}
|
|
33424
|
+
};
|
|
33425
|
+
var LEGACY_ADDRESSES = {
|
|
33426
|
+
14800: Object.fromEntries(
|
|
33427
|
+
Object.entries(LEGACY_CONTRACTS).map(([name, info]) => [name, info.addresses[14800]]).filter(([, addr]) => addr)
|
|
33428
|
+
),
|
|
33429
|
+
1480: Object.fromEntries(
|
|
33430
|
+
Object.entries(LEGACY_CONTRACTS).map(([name, info]) => [name, info.addresses[1480]]).filter(([, addr]) => addr)
|
|
33431
|
+
)
|
|
33432
|
+
};
|
|
33433
|
+
var getContractAddress = (chainId, contract) => {
|
|
33434
|
+
const contractAddress = CONTRACT_ADDRESSES[chainId]?.[contract];
|
|
33435
|
+
if (!contractAddress) {
|
|
33436
|
+
throw new Error(
|
|
33437
|
+
`Contract address not found for ${contract} on chain ${chainId}`
|
|
33438
|
+
);
|
|
33439
|
+
}
|
|
33440
|
+
return contractAddress;
|
|
33441
|
+
};
|
|
33442
|
+
|
|
33434
33443
|
// src/utils/grantFiles.ts
|
|
33435
33444
|
import { keccak256, toHex } from "viem";
|
|
33436
33445
|
function createGrantFile(params) {
|
|
33437
33446
|
const grantFile = {
|
|
33438
|
-
grantee: params.
|
|
33447
|
+
grantee: params.grantee,
|
|
33439
33448
|
operation: params.operation,
|
|
33440
33449
|
parameters: params.parameters
|
|
33441
33450
|
};
|
|
@@ -33832,6 +33841,91 @@ function validateOperationAccess(grantFile, requestedOperation) {
|
|
|
33832
33841
|
}
|
|
33833
33842
|
}
|
|
33834
33843
|
|
|
33844
|
+
// src/utils/signatureCache.ts
|
|
33845
|
+
init_crypto_utils();
|
|
33846
|
+
var SignatureCache = class {
|
|
33847
|
+
/**
|
|
33848
|
+
* Get a cached signature if it exists and hasn't expired
|
|
33849
|
+
*/
|
|
33850
|
+
static get(cache, walletAddress, messageHash) {
|
|
33851
|
+
const key = this.getCacheKey(walletAddress, messageHash);
|
|
33852
|
+
try {
|
|
33853
|
+
const stored = cache.get(key);
|
|
33854
|
+
if (!stored) return null;
|
|
33855
|
+
const cached = JSON.parse(stored);
|
|
33856
|
+
if (Date.now() > cached.expires) {
|
|
33857
|
+
cache.delete(key);
|
|
33858
|
+
return null;
|
|
33859
|
+
}
|
|
33860
|
+
return cached.signature;
|
|
33861
|
+
} catch {
|
|
33862
|
+
try {
|
|
33863
|
+
cache.delete(key);
|
|
33864
|
+
} catch {
|
|
33865
|
+
}
|
|
33866
|
+
return null;
|
|
33867
|
+
}
|
|
33868
|
+
}
|
|
33869
|
+
/**
|
|
33870
|
+
* Store a signature in the cache
|
|
33871
|
+
*/
|
|
33872
|
+
static set(cache, walletAddress, messageHash, signature, ttlHours = this.DEFAULT_TTL_HOURS) {
|
|
33873
|
+
const key = this.getCacheKey(walletAddress, messageHash);
|
|
33874
|
+
const cached = {
|
|
33875
|
+
signature,
|
|
33876
|
+
expires: Date.now() + ttlHours * 36e5
|
|
33877
|
+
// Convert hours to milliseconds
|
|
33878
|
+
};
|
|
33879
|
+
try {
|
|
33880
|
+
cache.set(key, JSON.stringify(cached));
|
|
33881
|
+
} catch {
|
|
33882
|
+
}
|
|
33883
|
+
}
|
|
33884
|
+
/**
|
|
33885
|
+
* Clear all cached signatures (useful for testing or explicit cleanup)
|
|
33886
|
+
*/
|
|
33887
|
+
static clear(cache) {
|
|
33888
|
+
try {
|
|
33889
|
+
cache.clear();
|
|
33890
|
+
} catch {
|
|
33891
|
+
}
|
|
33892
|
+
}
|
|
33893
|
+
static getCacheKey(walletAddress, messageHash) {
|
|
33894
|
+
return `${this.PREFIX}${walletAddress.toLowerCase()}:${messageHash}`;
|
|
33895
|
+
}
|
|
33896
|
+
static hashMessage(message) {
|
|
33897
|
+
const jsonString = JSON.stringify(message, this.bigIntReplacer);
|
|
33898
|
+
const base64Hash = toBase64(jsonString);
|
|
33899
|
+
const cleaned = base64Hash.replace(/[^a-zA-Z0-9]/g, "");
|
|
33900
|
+
if (cleaned.length > 32) {
|
|
33901
|
+
return cleaned.substring(0, 16) + cleaned.substring(cleaned.length - 16);
|
|
33902
|
+
}
|
|
33903
|
+
return cleaned.substring(0, 32);
|
|
33904
|
+
}
|
|
33905
|
+
/**
|
|
33906
|
+
* Custom JSON replacer that converts BigInt values to strings for serialization
|
|
33907
|
+
* This ensures deterministic cache key generation for EIP-712 typed data
|
|
33908
|
+
*/
|
|
33909
|
+
static bigIntReplacer(key, value) {
|
|
33910
|
+
if (typeof value === "bigint") {
|
|
33911
|
+
return `__BIGINT__${value.toString()}`;
|
|
33912
|
+
}
|
|
33913
|
+
return value;
|
|
33914
|
+
}
|
|
33915
|
+
};
|
|
33916
|
+
__publicField(SignatureCache, "PREFIX", "vana_sig_");
|
|
33917
|
+
__publicField(SignatureCache, "DEFAULT_TTL_HOURS", 2);
|
|
33918
|
+
async function withSignatureCache(cache, walletAddress, typedData, signFn, ttlHours) {
|
|
33919
|
+
const messageHash = SignatureCache.hashMessage(typedData);
|
|
33920
|
+
const cached = SignatureCache.get(cache, walletAddress, messageHash);
|
|
33921
|
+
if (cached) {
|
|
33922
|
+
return cached;
|
|
33923
|
+
}
|
|
33924
|
+
const signature = await signFn();
|
|
33925
|
+
SignatureCache.set(cache, walletAddress, messageHash, signature, ttlHours);
|
|
33926
|
+
return signature;
|
|
33927
|
+
}
|
|
33928
|
+
|
|
33835
33929
|
// src/controllers/permissions.ts
|
|
33836
33930
|
var PermissionsController = class {
|
|
33837
33931
|
constructor(context) {
|
|
@@ -33839,23 +33933,23 @@ var PermissionsController = class {
|
|
|
33839
33933
|
}
|
|
33840
33934
|
/**
|
|
33841
33935
|
* Grants permission for an application to access user data with gasless transactions.
|
|
33936
|
+
*
|
|
33937
|
+
* This method provides a complete end-to-end permission grant flow that returns
|
|
33938
|
+
* the permission ID and other relevant data immediately after successful submission.
|
|
33939
|
+
* For advanced users who need more control over the transaction lifecycle, use
|
|
33940
|
+
* `submitPermissionGrant()` instead.
|
|
33842
33941
|
*
|
|
33843
|
-
* @remarks
|
|
33844
|
-
* This method combines signature creation and gasless submission for a complete
|
|
33845
|
-
* end-to-end permission grant flow. It creates the grant file, stores it on IPFS,
|
|
33846
|
-
* generates an EIP-712 signature, and submits via relayer. The grant file contains
|
|
33847
|
-
* detailed parameters while the blockchain stores only a reference to enable
|
|
33848
|
-
* efficient permission queries.
|
|
33849
33942
|
* @param params - The permission grant configuration object
|
|
33850
|
-
* @returns
|
|
33943
|
+
* @returns Promise resolving to permission data from the PermissionAdded event
|
|
33851
33944
|
* @throws {RelayerError} When gasless transaction submission fails
|
|
33852
33945
|
* @throws {SignatureError} When user rejects the signature request
|
|
33853
33946
|
* @throws {SerializationError} When grant data cannot be serialized
|
|
33854
|
-
* @throws {BlockchainError} When permission grant
|
|
33947
|
+
* @throws {BlockchainError} When permission grant fails or event parsing fails
|
|
33948
|
+
* @throws {NetworkError} When transaction confirmation times out
|
|
33855
33949
|
* @example
|
|
33856
33950
|
* ```typescript
|
|
33857
|
-
* const
|
|
33858
|
-
*
|
|
33951
|
+
* const result = await vana.permissions.grant({
|
|
33952
|
+
* grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
33859
33953
|
* operation: "llm_inference",
|
|
33860
33954
|
* parameters: {
|
|
33861
33955
|
* model: "gpt-4",
|
|
@@ -33864,10 +33958,42 @@ var PermissionsController = class {
|
|
|
33864
33958
|
* },
|
|
33865
33959
|
* });
|
|
33866
33960
|
*
|
|
33867
|
-
* console.log(`Permission granted
|
|
33961
|
+
* console.log(`Permission ${result.permissionId} granted to ${result.user}`);
|
|
33962
|
+
* console.log(`Transaction: ${result.transactionHash}`);
|
|
33963
|
+
*
|
|
33964
|
+
* // Can immediately use the permission ID for other operations
|
|
33965
|
+
* await vana.permissions.revoke({ permissionId: result.permissionId });
|
|
33868
33966
|
* ```
|
|
33869
33967
|
*/
|
|
33870
33968
|
async grant(params) {
|
|
33969
|
+
const txHash = await this.submitPermissionGrant(params);
|
|
33970
|
+
return parseTransactionResult(this.context, txHash, "grant");
|
|
33971
|
+
}
|
|
33972
|
+
/**
|
|
33973
|
+
* Submits a permission grant transaction and returns the transaction hash immediately.
|
|
33974
|
+
*
|
|
33975
|
+
* This is the lower-level method that provides maximum control over transaction timing.
|
|
33976
|
+
* Use this when you want to handle transaction confirmation and event parsing separately,
|
|
33977
|
+
* or when submitting multiple transactions in batch.
|
|
33978
|
+
*
|
|
33979
|
+
* @param params - The permission grant configuration object
|
|
33980
|
+
* @returns Promise that resolves to the transaction hash when successfully submitted
|
|
33981
|
+
* @throws {RelayerError} When gasless transaction submission fails
|
|
33982
|
+
* @throws {SignatureError} When user rejects the signature request
|
|
33983
|
+
* @throws {SerializationError} When grant data cannot be serialized
|
|
33984
|
+
* @throws {BlockchainError} When permission grant preparation fails
|
|
33985
|
+
* @example
|
|
33986
|
+
* ```typescript
|
|
33987
|
+
* // Submit transaction and handle confirmation later
|
|
33988
|
+
* const txHash = await vana.permissions.submitPermissionGrant(params);
|
|
33989
|
+
* console.log(`Transaction submitted: ${txHash}`);
|
|
33990
|
+
*
|
|
33991
|
+
* // Later, when you need the permission data:
|
|
33992
|
+
* const result = await parseTransactionResult(context, txHash, 'grant');
|
|
33993
|
+
* console.log(`Permission ID: ${result.permissionId}`);
|
|
33994
|
+
* ```
|
|
33995
|
+
*/
|
|
33996
|
+
async submitPermissionGrant(params) {
|
|
33871
33997
|
const { typedData, signature } = await this.createAndSign(params);
|
|
33872
33998
|
return await this.submitSignedGrant(typedData, signature);
|
|
33873
33999
|
}
|
|
@@ -33884,7 +34010,7 @@ var PermissionsController = class {
|
|
|
33884
34010
|
* @example
|
|
33885
34011
|
* ```typescript
|
|
33886
34012
|
* const { preview, confirm } = await vana.permissions.prepareGrant({
|
|
33887
|
-
*
|
|
34013
|
+
* grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
33888
34014
|
* operation: "llm_inference",
|
|
33889
34015
|
* files: [1, 2, 3],
|
|
33890
34016
|
* parameters: { model: "gpt-4", prompt: "Analyze my social media data" }
|
|
@@ -33933,9 +34059,13 @@ var PermissionsController = class {
|
|
|
33933
34059
|
console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
|
|
33934
34060
|
if (!grantUrl) {
|
|
33935
34061
|
if (!this.context.relayerCallbacks?.storeGrantFile && !this.context.storageManager) {
|
|
33936
|
-
|
|
33937
|
-
|
|
33938
|
-
|
|
34062
|
+
if (this.context.validateStorageRequired) {
|
|
34063
|
+
this.context.validateStorageRequired();
|
|
34064
|
+
} else {
|
|
34065
|
+
throw new Error(
|
|
34066
|
+
"No storage available. Provide a grantUrl, configure relayerCallbacks.storeGrantFile, or storageManager."
|
|
34067
|
+
);
|
|
34068
|
+
}
|
|
33939
34069
|
}
|
|
33940
34070
|
if (this.context.relayerCallbacks?.storeGrantFile) {
|
|
33941
34071
|
grantUrl = await this.context.relayerCallbacks.storeGrantFile(grantFile);
|
|
@@ -33959,7 +34089,7 @@ var PermissionsController = class {
|
|
|
33959
34089
|
grantUrl
|
|
33960
34090
|
);
|
|
33961
34091
|
const typedData = await this.composePermissionGrantMessage({
|
|
33962
|
-
|
|
34092
|
+
grantee: params.grantee,
|
|
33963
34093
|
operation: params.operation,
|
|
33964
34094
|
// Placeholder - real data is in IPFS
|
|
33965
34095
|
files: params.files,
|
|
@@ -34006,7 +34136,7 @@ var PermissionsController = class {
|
|
|
34006
34136
|
* @example
|
|
34007
34137
|
* ```typescript
|
|
34008
34138
|
* const { typedData, signature } = await vana.permissions.createAndSign({
|
|
34009
|
-
*
|
|
34139
|
+
* grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
34010
34140
|
* operation: "data_analysis",
|
|
34011
34141
|
* parameters: { analysisType: "sentiment" },
|
|
34012
34142
|
* });
|
|
@@ -34022,9 +34152,13 @@ var PermissionsController = class {
|
|
|
34022
34152
|
console.debug("\u{1F50D} Debug - Grant URL from params:", grantUrl);
|
|
34023
34153
|
if (!grantUrl) {
|
|
34024
34154
|
if (!this.context.relayerCallbacks?.storeGrantFile && !this.context.storageManager) {
|
|
34025
|
-
|
|
34026
|
-
|
|
34027
|
-
|
|
34155
|
+
if (this.context.validateStorageRequired) {
|
|
34156
|
+
this.context.validateStorageRequired();
|
|
34157
|
+
} else {
|
|
34158
|
+
throw new Error(
|
|
34159
|
+
"No storage available. Provide a grantUrl, configure relayerCallbacks.storeGrantFile, or storageManager."
|
|
34160
|
+
);
|
|
34161
|
+
}
|
|
34028
34162
|
}
|
|
34029
34163
|
if (this.context.relayerCallbacks?.storeGrantFile) {
|
|
34030
34164
|
grantUrl = await this.context.relayerCallbacks.storeGrantFile(grantFile);
|
|
@@ -34048,7 +34182,7 @@ var PermissionsController = class {
|
|
|
34048
34182
|
grantUrl
|
|
34049
34183
|
);
|
|
34050
34184
|
const typedData = await this.composePermissionGrantMessage({
|
|
34051
|
-
|
|
34185
|
+
grantee: params.grantee,
|
|
34052
34186
|
operation: params.operation,
|
|
34053
34187
|
// Placeholder - real data is in IPFS
|
|
34054
34188
|
files: params.files,
|
|
@@ -34276,23 +34410,52 @@ var PermissionsController = class {
|
|
|
34276
34410
|
}
|
|
34277
34411
|
/**
|
|
34278
34412
|
* Revokes a previously granted permission.
|
|
34413
|
+
*
|
|
34414
|
+
* This method provides complete revocation with automatic event parsing to confirm
|
|
34415
|
+
* the permission was successfully revoked. For advanced users who need more control,
|
|
34416
|
+
* use `submitPermissionRevoke()` instead.
|
|
34279
34417
|
*
|
|
34280
34418
|
* @param params - Parameters for revoking the permission
|
|
34281
|
-
* @
|
|
34419
|
+
* @param params.permissionId - Permission identifier as bigint for contract compatibility.
|
|
34420
|
+
* Obtain from permission grants via `getUserPermissionGrantsOnChain()`.
|
|
34421
|
+
* @returns Promise resolving to revocation data from PermissionRevoked event
|
|
34422
|
+
* @throws {BlockchainError} When revocation fails or event parsing fails
|
|
34423
|
+
* @throws {UserRejectedRequestError} When user rejects the transaction
|
|
34424
|
+
* @throws {NetworkError} When transaction confirmation times out
|
|
34282
34425
|
* @example
|
|
34283
34426
|
* ```typescript
|
|
34284
|
-
* // Revoke a permission
|
|
34285
|
-
* const
|
|
34427
|
+
* // Revoke a permission and get confirmation
|
|
34428
|
+
* const result = await vana.permissions.revoke({
|
|
34286
34429
|
* permissionId: 123n
|
|
34287
34430
|
* });
|
|
34288
|
-
* console.log(
|
|
34289
|
-
*
|
|
34290
|
-
* // Wait for confirmation if needed
|
|
34291
|
-
* const receipt = await vana.core.waitForTransaction(txHash);
|
|
34292
|
-
* console.log('Revocation confirmed in block:', receipt.blockNumber);
|
|
34431
|
+
* console.log(`Permission ${result.permissionId} revoked in transaction ${result.transactionHash}`);
|
|
34432
|
+
* console.log(`Revoked in block ${result.blockNumber}`);
|
|
34293
34433
|
* ```
|
|
34294
34434
|
*/
|
|
34295
34435
|
async revoke(params) {
|
|
34436
|
+
const txHash = await this.submitPermissionRevoke(params);
|
|
34437
|
+
return parseTransactionResult(this.context, txHash, "revoke");
|
|
34438
|
+
}
|
|
34439
|
+
/**
|
|
34440
|
+
* Submits a permission revocation transaction and returns the transaction hash immediately.
|
|
34441
|
+
*
|
|
34442
|
+
* This is the lower-level method that provides maximum control over transaction timing.
|
|
34443
|
+
* Use this when you want to handle transaction confirmation and event parsing separately.
|
|
34444
|
+
*
|
|
34445
|
+
* @param params - Parameters for revoking the permission
|
|
34446
|
+
* @returns Promise resolving to the transaction hash when successfully submitted
|
|
34447
|
+
* @throws {BlockchainError} When revocation transaction fails
|
|
34448
|
+
* @throws {UserRejectedRequestError} When user rejects the transaction
|
|
34449
|
+
* @example
|
|
34450
|
+
* ```typescript
|
|
34451
|
+
* // Submit revocation and handle confirmation later
|
|
34452
|
+
* const txHash = await vana.permissions.submitPermissionRevoke({
|
|
34453
|
+
* permissionId: 123n
|
|
34454
|
+
* });
|
|
34455
|
+
* console.log(`Revocation submitted: ${txHash}`);
|
|
34456
|
+
* ```
|
|
34457
|
+
*/
|
|
34458
|
+
async submitPermissionRevoke(params) {
|
|
34296
34459
|
try {
|
|
34297
34460
|
if (!this.context.walletClient.chain?.id) {
|
|
34298
34461
|
throw new BlockchainError("Chain ID not available");
|
|
@@ -34399,7 +34562,7 @@ var PermissionsController = class {
|
|
|
34399
34562
|
* Composes the EIP-712 typed data for PermissionGrant (new simplified format).
|
|
34400
34563
|
*
|
|
34401
34564
|
* @param params - The parameters for composing the permission grant message
|
|
34402
|
-
* @param params.
|
|
34565
|
+
* @param params.grantee - The recipient address for the permission grant
|
|
34403
34566
|
* @param params.operation - The type of operation being granted permission for
|
|
34404
34567
|
* @param params.files - Array of file IDs that the permission applies to
|
|
34405
34568
|
* @param params.grantUrl - URL where the grant details are stored
|
|
@@ -34458,17 +34621,24 @@ var PermissionsController = class {
|
|
|
34458
34621
|
};
|
|
34459
34622
|
}
|
|
34460
34623
|
/**
|
|
34461
|
-
* Signs typed data using the wallet client.
|
|
34624
|
+
* Signs typed data using the wallet client with signature caching.
|
|
34462
34625
|
*
|
|
34463
34626
|
* @param typedData - The EIP-712 typed data structure to sign
|
|
34464
34627
|
* @returns Promise resolving to the cryptographic signature
|
|
34465
34628
|
*/
|
|
34466
34629
|
async signTypedData(typedData) {
|
|
34467
34630
|
try {
|
|
34468
|
-
const
|
|
34469
|
-
|
|
34631
|
+
const walletAddress = this.context.walletClient.account?.address || await this.getUserAddress();
|
|
34632
|
+
return await withSignatureCache(
|
|
34633
|
+
this.context.platform.cache,
|
|
34634
|
+
walletAddress,
|
|
34635
|
+
typedData,
|
|
34636
|
+
async () => {
|
|
34637
|
+
return await this.context.walletClient.signTypedData(
|
|
34638
|
+
typedData
|
|
34639
|
+
);
|
|
34640
|
+
}
|
|
34470
34641
|
);
|
|
34471
|
-
return signature;
|
|
34472
34642
|
} catch (error) {
|
|
34473
34643
|
if (error instanceof Error && error.message.includes("rejected")) {
|
|
34474
34644
|
throw new UserRejectedRequestError();
|
|
@@ -34492,36 +34662,45 @@ var PermissionsController = class {
|
|
|
34492
34662
|
return addresses[0];
|
|
34493
34663
|
}
|
|
34494
34664
|
/**
|
|
34495
|
-
*
|
|
34665
|
+
* Gets on-chain permission grant data without expensive off-chain resolution.
|
|
34496
34666
|
*
|
|
34497
34667
|
* @remarks
|
|
34498
|
-
* This method
|
|
34499
|
-
*
|
|
34500
|
-
*
|
|
34501
|
-
*
|
|
34502
|
-
*
|
|
34503
|
-
*
|
|
34504
|
-
*
|
|
34505
|
-
*
|
|
34506
|
-
*
|
|
34507
|
-
*
|
|
34668
|
+
* This method provides a fast, performance-focused way to retrieve permission grants
|
|
34669
|
+
* by querying only the subgraph without making expensive IPFS or individual contract calls.
|
|
34670
|
+
* It eliminates the N+1 query problem of the legacy `getUserPermissions()` method.
|
|
34671
|
+
*
|
|
34672
|
+
* The returned data contains all on-chain information but does NOT include resolved
|
|
34673
|
+
* operation details, parameters, or file IDs. Use `retrieveGrantFile()` separately
|
|
34674
|
+
* for specific grants when detailed data is needed.
|
|
34675
|
+
*
|
|
34676
|
+
* **Performance**: Completes in ~100-500ms regardless of permission count.
|
|
34677
|
+
* **Reliability**: Single point of failure (subgraph) with clear RPC fallback path.
|
|
34678
|
+
*
|
|
34679
|
+
* @param options - Options for retrieving permissions (limit, subgraph URL)
|
|
34680
|
+
* @returns A Promise that resolves to an array of `OnChainPermissionGrant` objects
|
|
34681
|
+
* @throws {BlockchainError} When subgraph query fails
|
|
34682
|
+
* @throws {NetworkError} When network requests fail
|
|
34508
34683
|
* @example
|
|
34509
34684
|
* ```typescript
|
|
34510
|
-
* // Get all
|
|
34511
|
-
* const
|
|
34685
|
+
* // Fast: Get all on-chain permission data
|
|
34686
|
+
* const grants = await vana.permissions.getUserPermissionGrantsOnChain({ limit: 20 });
|
|
34512
34687
|
*
|
|
34513
|
-
*
|
|
34514
|
-
*
|
|
34688
|
+
* // Display in UI immediately
|
|
34689
|
+
* grants.forEach(grant => {
|
|
34690
|
+
* console.log(`Permission ${grant.id}: ${grant.grantUrl}`);
|
|
34515
34691
|
* });
|
|
34516
34692
|
*
|
|
34517
|
-
* //
|
|
34518
|
-
* const
|
|
34693
|
+
* // Lazy load detailed data for specific permission when user clicks
|
|
34694
|
+
* const grantFile = await retrieveGrantFile(grants[0].grantUrl);
|
|
34695
|
+
* console.log(`Operation: ${grantFile.operation}`);
|
|
34696
|
+
* console.log(`Parameters:`, grantFile.parameters);
|
|
34519
34697
|
* ```
|
|
34520
34698
|
*/
|
|
34521
|
-
async
|
|
34699
|
+
async getUserPermissionGrantsOnChain(options = {}) {
|
|
34700
|
+
const { limit = 50, subgraphUrl } = options;
|
|
34522
34701
|
try {
|
|
34523
34702
|
const userAddress = await this.getUserAddress();
|
|
34524
|
-
const graphqlEndpoint =
|
|
34703
|
+
const graphqlEndpoint = subgraphUrl || this.context.subgraphUrl;
|
|
34525
34704
|
if (!graphqlEndpoint) {
|
|
34526
34705
|
throw new BlockchainError(
|
|
34527
34706
|
"subgraphUrl is required. Please provide a valid subgraph endpoint or configure it in Vana constructor."
|
|
@@ -34543,16 +34722,6 @@ var PermissionsController = class {
|
|
|
34543
34722
|
}
|
|
34544
34723
|
}
|
|
34545
34724
|
`;
|
|
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
34725
|
const response = await fetch(graphqlEndpoint, {
|
|
34557
34726
|
method: "POST",
|
|
34558
34727
|
headers: {
|
|
@@ -34571,7 +34740,6 @@ var PermissionsController = class {
|
|
|
34571
34740
|
);
|
|
34572
34741
|
}
|
|
34573
34742
|
const result = await response.json();
|
|
34574
|
-
console.info("Result:", result);
|
|
34575
34743
|
if (result.errors) {
|
|
34576
34744
|
throw new BlockchainError(
|
|
34577
34745
|
`Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
|
|
@@ -34579,64 +34747,32 @@ var PermissionsController = class {
|
|
|
34579
34747
|
}
|
|
34580
34748
|
const userData = result.data?.user;
|
|
34581
34749
|
if (!userData || !userData.permissions?.length) {
|
|
34582
|
-
console.warn("No permissions found for user:", userAddress);
|
|
34583
34750
|
return [];
|
|
34584
34751
|
}
|
|
34585
|
-
const
|
|
34586
|
-
|
|
34587
|
-
|
|
34588
|
-
|
|
34589
|
-
|
|
34590
|
-
|
|
34591
|
-
|
|
34592
|
-
|
|
34593
|
-
|
|
34594
|
-
|
|
34595
|
-
|
|
34596
|
-
|
|
34597
|
-
|
|
34598
|
-
|
|
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) => {
|
|
34752
|
+
const onChainGrants = userData.permissions.slice(0, limit).map((permission) => ({
|
|
34753
|
+
id: BigInt(permission.id),
|
|
34754
|
+
grantUrl: permission.grant,
|
|
34755
|
+
grantSignature: permission.grantSignature,
|
|
34756
|
+
grantHash: permission.grantHash,
|
|
34757
|
+
nonce: BigInt(permission.nonce),
|
|
34758
|
+
addedAtBlock: BigInt(permission.addedAtBlock),
|
|
34759
|
+
addedAtTimestamp: BigInt(permission.addedAtTimestamp || "0"),
|
|
34760
|
+
transactionHash: permission.transactionHash || "",
|
|
34761
|
+
grantor: userAddress,
|
|
34762
|
+
active: true
|
|
34763
|
+
// TODO: Add revocation status from subgraph when available
|
|
34764
|
+
}));
|
|
34765
|
+
return onChainGrants.sort((a, b) => {
|
|
34632
34766
|
if (a.id < b.id) return 1;
|
|
34633
34767
|
if (a.id > b.id) return -1;
|
|
34634
34768
|
return 0;
|
|
34635
34769
|
});
|
|
34636
34770
|
} catch (error) {
|
|
34637
|
-
|
|
34771
|
+
if (error instanceof BlockchainError || error instanceof NetworkError) {
|
|
34772
|
+
throw error;
|
|
34773
|
+
}
|
|
34638
34774
|
throw new BlockchainError(
|
|
34639
|
-
`Failed to fetch user
|
|
34775
|
+
`Failed to fetch user permission grants: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
34640
34776
|
);
|
|
34641
34777
|
}
|
|
34642
34778
|
}
|
|
@@ -35336,15 +35472,22 @@ import { getContract, decodeEventLog } from "viem";
|
|
|
35336
35472
|
|
|
35337
35473
|
// src/utils/encryption.ts
|
|
35338
35474
|
var DEFAULT_ENCRYPTION_SEED = "Please sign to retrieve your encryption key";
|
|
35339
|
-
async function generateEncryptionKey(wallet, seed = DEFAULT_ENCRYPTION_SEED) {
|
|
35475
|
+
async function generateEncryptionKey(wallet, platformAdapter, seed = DEFAULT_ENCRYPTION_SEED) {
|
|
35340
35476
|
if (!wallet.account) {
|
|
35341
35477
|
throw new Error("Wallet account is required for encryption key generation");
|
|
35342
35478
|
}
|
|
35343
|
-
const
|
|
35344
|
-
|
|
35345
|
-
|
|
35346
|
-
|
|
35347
|
-
|
|
35479
|
+
const messageData = { message: seed };
|
|
35480
|
+
return await withSignatureCache(
|
|
35481
|
+
platformAdapter.cache,
|
|
35482
|
+
wallet.account.address,
|
|
35483
|
+
messageData,
|
|
35484
|
+
async () => {
|
|
35485
|
+
return await wallet.signMessage({
|
|
35486
|
+
account: wallet.account,
|
|
35487
|
+
message: seed
|
|
35488
|
+
});
|
|
35489
|
+
}
|
|
35490
|
+
);
|
|
35348
35491
|
}
|
|
35349
35492
|
async function encryptWithWalletPublicKey(data, publicKey, platformAdapter) {
|
|
35350
35493
|
try {
|
|
@@ -35398,32 +35541,19 @@ async function decryptWithPrivateKey(encryptedData, privateKey, platformAdapter)
|
|
|
35398
35541
|
throw new Error(`Failed to decrypt with private key: ${error}`);
|
|
35399
35542
|
}
|
|
35400
35543
|
}
|
|
35401
|
-
async function
|
|
35544
|
+
async function encryptBlobWithSignedKey(data, key, platformAdapter) {
|
|
35402
35545
|
try {
|
|
35403
35546
|
const dataBuffer = data instanceof Blob ? await data.arrayBuffer() : new TextEncoder().encode(data);
|
|
35404
35547
|
const dataArray = new Uint8Array(dataBuffer);
|
|
35405
35548
|
const encrypted = await platformAdapter.crypto.encryptWithPassword(
|
|
35406
35549
|
dataArray,
|
|
35407
|
-
|
|
35550
|
+
key
|
|
35408
35551
|
);
|
|
35409
35552
|
return new Blob([encrypted], {
|
|
35410
35553
|
type: "application/octet-stream"
|
|
35411
35554
|
});
|
|
35412
35555
|
} catch (error) {
|
|
35413
|
-
throw new Error(`Failed to encrypt
|
|
35414
|
-
}
|
|
35415
|
-
}
|
|
35416
|
-
async function decryptUserData(encryptedData, walletSignature, platformAdapter) {
|
|
35417
|
-
try {
|
|
35418
|
-
const encryptedBuffer = encryptedData instanceof Blob ? await encryptedData.arrayBuffer() : new TextEncoder().encode(encryptedData);
|
|
35419
|
-
const encryptedArray = new Uint8Array(encryptedBuffer);
|
|
35420
|
-
const decrypted = await platformAdapter.crypto.decryptWithPassword(
|
|
35421
|
-
encryptedArray,
|
|
35422
|
-
walletSignature
|
|
35423
|
-
);
|
|
35424
|
-
return new Blob([decrypted], { type: "text/plain" });
|
|
35425
|
-
} catch (error) {
|
|
35426
|
-
throw new Error(`Failed to decrypt user data: ${error}`);
|
|
35556
|
+
throw new Error(`Failed to encrypt data: ${error}`);
|
|
35427
35557
|
}
|
|
35428
35558
|
}
|
|
35429
35559
|
async function generateEncryptionKeyPair(platformAdapter) {
|
|
@@ -35440,12 +35570,315 @@ async function generatePGPKeyPair(platformAdapter, options) {
|
|
|
35440
35570
|
throw new Error(`Failed to generate PGP key pair: ${error}`);
|
|
35441
35571
|
}
|
|
35442
35572
|
}
|
|
35573
|
+
async function decryptBlobWithSignedKey(encryptedData, key, platformAdapter) {
|
|
35574
|
+
try {
|
|
35575
|
+
const encryptedBuffer = encryptedData instanceof Blob ? await encryptedData.arrayBuffer() : new TextEncoder().encode(encryptedData);
|
|
35576
|
+
const encryptedArray = new Uint8Array(encryptedBuffer);
|
|
35577
|
+
const decrypted = await platformAdapter.crypto.decryptWithPassword(
|
|
35578
|
+
encryptedArray,
|
|
35579
|
+
key
|
|
35580
|
+
);
|
|
35581
|
+
return new Blob([decrypted], { type: "text/plain" });
|
|
35582
|
+
} catch (error) {
|
|
35583
|
+
throw new Error(`Failed to decrypt data: ${error}`);
|
|
35584
|
+
}
|
|
35585
|
+
}
|
|
35443
35586
|
|
|
35444
35587
|
// src/controllers/data.ts
|
|
35445
35588
|
var DataController = class {
|
|
35446
35589
|
constructor(context) {
|
|
35447
35590
|
this.context = context;
|
|
35448
35591
|
}
|
|
35592
|
+
async upload(params) {
|
|
35593
|
+
const {
|
|
35594
|
+
content,
|
|
35595
|
+
filename,
|
|
35596
|
+
schemaId,
|
|
35597
|
+
permissions = [],
|
|
35598
|
+
encrypt: encrypt2 = true,
|
|
35599
|
+
providerName,
|
|
35600
|
+
owner
|
|
35601
|
+
} = params;
|
|
35602
|
+
try {
|
|
35603
|
+
let blob;
|
|
35604
|
+
if (content instanceof Blob) {
|
|
35605
|
+
blob = content;
|
|
35606
|
+
} else if (typeof content === "string") {
|
|
35607
|
+
blob = new Blob([content], { type: "text/plain" });
|
|
35608
|
+
} else if (content instanceof Buffer) {
|
|
35609
|
+
blob = new Blob([content], { type: "application/octet-stream" });
|
|
35610
|
+
} else {
|
|
35611
|
+
blob = new Blob([JSON.stringify(content)], {
|
|
35612
|
+
type: "application/json"
|
|
35613
|
+
});
|
|
35614
|
+
}
|
|
35615
|
+
let isValid = true;
|
|
35616
|
+
let validationErrors = [];
|
|
35617
|
+
if (schemaId !== void 0) {
|
|
35618
|
+
try {
|
|
35619
|
+
const schema = await this.getSchema(schemaId);
|
|
35620
|
+
const response = await fetch(schema.definitionUrl);
|
|
35621
|
+
if (!response.ok) {
|
|
35622
|
+
throw new Error(
|
|
35623
|
+
`Failed to fetch schema definition: ${response.status}`
|
|
35624
|
+
);
|
|
35625
|
+
}
|
|
35626
|
+
const schemaDefinition = await response.json();
|
|
35627
|
+
const dataSchema = {
|
|
35628
|
+
name: schema.name,
|
|
35629
|
+
version: "1.0.0",
|
|
35630
|
+
dialect: "json",
|
|
35631
|
+
schema: schemaDefinition
|
|
35632
|
+
};
|
|
35633
|
+
let parsedContent;
|
|
35634
|
+
if (typeof content === "string") {
|
|
35635
|
+
try {
|
|
35636
|
+
parsedContent = JSON.parse(content);
|
|
35637
|
+
} catch {
|
|
35638
|
+
parsedContent = content;
|
|
35639
|
+
}
|
|
35640
|
+
} else {
|
|
35641
|
+
parsedContent = content;
|
|
35642
|
+
}
|
|
35643
|
+
validateDataAgainstSchema(parsedContent, dataSchema);
|
|
35644
|
+
} catch (error) {
|
|
35645
|
+
isValid = false;
|
|
35646
|
+
validationErrors = [
|
|
35647
|
+
error instanceof Error ? error.message : "Schema validation failed"
|
|
35648
|
+
];
|
|
35649
|
+
}
|
|
35650
|
+
}
|
|
35651
|
+
let finalBlob = blob;
|
|
35652
|
+
if (encrypt2) {
|
|
35653
|
+
const encryptionKey = await generateEncryptionKey(
|
|
35654
|
+
this.context.walletClient,
|
|
35655
|
+
this.context.platform,
|
|
35656
|
+
DEFAULT_ENCRYPTION_SEED
|
|
35657
|
+
);
|
|
35658
|
+
finalBlob = await encryptBlobWithSignedKey(
|
|
35659
|
+
blob,
|
|
35660
|
+
encryptionKey,
|
|
35661
|
+
this.context.platform
|
|
35662
|
+
);
|
|
35663
|
+
}
|
|
35664
|
+
if (!this.context.storageManager) {
|
|
35665
|
+
if (this.context.validateStorageRequired) {
|
|
35666
|
+
this.context.validateStorageRequired();
|
|
35667
|
+
throw new Error("Storage validation failed");
|
|
35668
|
+
} else {
|
|
35669
|
+
throw new Error(
|
|
35670
|
+
"Storage manager not configured. Please provide storage providers in VanaConfig."
|
|
35671
|
+
);
|
|
35672
|
+
}
|
|
35673
|
+
}
|
|
35674
|
+
const uploadResult = await this.context.storageManager.upload(
|
|
35675
|
+
finalBlob,
|
|
35676
|
+
filename,
|
|
35677
|
+
providerName
|
|
35678
|
+
);
|
|
35679
|
+
const userAddress = owner || await this.getUserAddress();
|
|
35680
|
+
let encryptedPermissions = [];
|
|
35681
|
+
if (permissions.length > 0) {
|
|
35682
|
+
const userEncryptionKey = await generateEncryptionKey(
|
|
35683
|
+
this.context.walletClient,
|
|
35684
|
+
this.context.platform,
|
|
35685
|
+
DEFAULT_ENCRYPTION_SEED
|
|
35686
|
+
);
|
|
35687
|
+
encryptedPermissions = await Promise.all(
|
|
35688
|
+
permissions.map(async (permission) => {
|
|
35689
|
+
const encryptedKey = await encryptWithWalletPublicKey(
|
|
35690
|
+
userEncryptionKey,
|
|
35691
|
+
permission.publicKey,
|
|
35692
|
+
this.context.platform
|
|
35693
|
+
);
|
|
35694
|
+
return {
|
|
35695
|
+
account: permission.account,
|
|
35696
|
+
key: encryptedKey
|
|
35697
|
+
};
|
|
35698
|
+
})
|
|
35699
|
+
);
|
|
35700
|
+
}
|
|
35701
|
+
let result;
|
|
35702
|
+
if (this.context.relayerCallbacks?.submitFileAdditionComplete) {
|
|
35703
|
+
result = await this.context.relayerCallbacks.submitFileAdditionComplete(
|
|
35704
|
+
{
|
|
35705
|
+
url: uploadResult.url,
|
|
35706
|
+
userAddress,
|
|
35707
|
+
permissions: encryptedPermissions,
|
|
35708
|
+
schemaId: schemaId || 0,
|
|
35709
|
+
ownerAddress: owner
|
|
35710
|
+
}
|
|
35711
|
+
);
|
|
35712
|
+
} else if (this.context.relayerCallbacks?.submitFileAddition) {
|
|
35713
|
+
const needsComplexRegistration = schemaId !== void 0 || encryptedPermissions.length > 0;
|
|
35714
|
+
if (needsComplexRegistration) {
|
|
35715
|
+
throw new Error(
|
|
35716
|
+
"The configured relay callback does not support schemas or permissions. Please update your relay server implementation to provide the `submitFileAdditionComplete` callback."
|
|
35717
|
+
);
|
|
35718
|
+
}
|
|
35719
|
+
result = await this.context.relayerCallbacks.submitFileAddition(
|
|
35720
|
+
uploadResult.url,
|
|
35721
|
+
userAddress
|
|
35722
|
+
);
|
|
35723
|
+
} else {
|
|
35724
|
+
result = await this.addFileWithPermissionsAndSchema(
|
|
35725
|
+
uploadResult.url,
|
|
35726
|
+
userAddress,
|
|
35727
|
+
encryptedPermissions,
|
|
35728
|
+
schemaId || 0
|
|
35729
|
+
);
|
|
35730
|
+
}
|
|
35731
|
+
return {
|
|
35732
|
+
fileId: result.fileId,
|
|
35733
|
+
url: uploadResult.url,
|
|
35734
|
+
transactionHash: result.transactionHash,
|
|
35735
|
+
size: uploadResult.size,
|
|
35736
|
+
isValid,
|
|
35737
|
+
validationErrors: validationErrors.length > 0 ? validationErrors : void 0
|
|
35738
|
+
};
|
|
35739
|
+
} catch (error) {
|
|
35740
|
+
throw new Error(
|
|
35741
|
+
`Upload failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
35742
|
+
);
|
|
35743
|
+
}
|
|
35744
|
+
}
|
|
35745
|
+
/**
|
|
35746
|
+
* Decrypts a file owned by the user using their wallet signature.
|
|
35747
|
+
*
|
|
35748
|
+
* @remarks
|
|
35749
|
+
* This is the high-level convenience method for decrypting user files, serving as the
|
|
35750
|
+
* symmetrical counterpart to the `upload` method. It handles the complete decryption
|
|
35751
|
+
* workflow including key generation, URL protocol detection, content fetching, and
|
|
35752
|
+
* decryption.
|
|
35753
|
+
*
|
|
35754
|
+
* The method automatically:
|
|
35755
|
+
* - Generates the decryption key from the user's wallet signature
|
|
35756
|
+
* - Determines the appropriate fetch method based on the file URL protocol
|
|
35757
|
+
* - Fetches the encrypted content from IPFS or standard HTTP URLs
|
|
35758
|
+
* - Decrypts the content using the generated key
|
|
35759
|
+
*
|
|
35760
|
+
* For IPFS URLs, the method uses gateway fallback for improved reliability. For
|
|
35761
|
+
* standard HTTP URLs, it uses a simple fetch. If you need custom authentication
|
|
35762
|
+
* headers or specific gateway configurations, use the low-level primitives directly.
|
|
35763
|
+
*
|
|
35764
|
+
* @param file - The user file to decrypt (typically from getUserFiles)
|
|
35765
|
+
* @param encryptionSeed - Optional custom encryption seed (defaults to Vana standard)
|
|
35766
|
+
* @returns Promise resolving to the decrypted file content as a Blob
|
|
35767
|
+
* @throws {Error} When the wallet is not connected
|
|
35768
|
+
* @throws {Error} When fetching the encrypted content fails
|
|
35769
|
+
* @throws {Error} When decryption fails (wrong key or corrupted data)
|
|
35770
|
+
* @example
|
|
35771
|
+
* ```typescript
|
|
35772
|
+
* // Basic file decryption
|
|
35773
|
+
* const files = await vana.data.getUserFiles({ owner: userAddress });
|
|
35774
|
+
* const decryptedBlob = await vana.data.decryptFile(files[0]);
|
|
35775
|
+
*
|
|
35776
|
+
* // Convert to text
|
|
35777
|
+
* const text = await decryptedBlob.text();
|
|
35778
|
+
* console.log('Decrypted content:', text);
|
|
35779
|
+
*
|
|
35780
|
+
* // Convert to JSON
|
|
35781
|
+
* const json = JSON.parse(await decryptedBlob.text());
|
|
35782
|
+
* console.log('Decrypted data:', json);
|
|
35783
|
+
*
|
|
35784
|
+
* // With custom encryption seed
|
|
35785
|
+
* const decryptedBlob = await vana.data.decryptFile(
|
|
35786
|
+
* files[0],
|
|
35787
|
+
* "My custom encryption seed"
|
|
35788
|
+
* );
|
|
35789
|
+
*
|
|
35790
|
+
* // Save to file (in Node.js)
|
|
35791
|
+
* const buffer = await decryptedBlob.arrayBuffer();
|
|
35792
|
+
* fs.writeFileSync('decrypted-file.txt', Buffer.from(buffer));
|
|
35793
|
+
* ```
|
|
35794
|
+
*/
|
|
35795
|
+
async decryptFile(file, encryptionSeed) {
|
|
35796
|
+
try {
|
|
35797
|
+
const encryptionKey = await generateEncryptionKey(
|
|
35798
|
+
this.context.walletClient,
|
|
35799
|
+
this.context.platform,
|
|
35800
|
+
encryptionSeed || DEFAULT_ENCRYPTION_SEED
|
|
35801
|
+
);
|
|
35802
|
+
let encryptedBlob;
|
|
35803
|
+
try {
|
|
35804
|
+
if (file.url.startsWith("ipfs://")) {
|
|
35805
|
+
encryptedBlob = await this.fetchFromIPFS(file.url);
|
|
35806
|
+
} else {
|
|
35807
|
+
encryptedBlob = await this.fetch(file.url);
|
|
35808
|
+
}
|
|
35809
|
+
} catch (fetchError) {
|
|
35810
|
+
const errorMessage = fetchError instanceof Error ? fetchError.message : "Unknown error";
|
|
35811
|
+
if (errorMessage.includes("Failed to fetch IPFS content") && errorMessage.includes("from all gateways")) {
|
|
35812
|
+
throw new Error(
|
|
35813
|
+
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
35814
|
+
);
|
|
35815
|
+
} else if (errorMessage.includes("Empty response")) {
|
|
35816
|
+
throw new Error("File is empty or could not be retrieved");
|
|
35817
|
+
} else if (errorMessage.includes("Network error:") || errorMessage.includes("Failed to fetch")) {
|
|
35818
|
+
throw new Error(
|
|
35819
|
+
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
35820
|
+
);
|
|
35821
|
+
} else if (errorMessage.includes("HTTP error!")) {
|
|
35822
|
+
const statusMatch = errorMessage.match(/status: (\d+)/);
|
|
35823
|
+
const status = statusMatch ? statusMatch[1] : "unknown";
|
|
35824
|
+
if (status === "500") {
|
|
35825
|
+
throw new Error(
|
|
35826
|
+
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
35827
|
+
);
|
|
35828
|
+
} else if (status === "403") {
|
|
35829
|
+
throw new Error(
|
|
35830
|
+
"Access denied. You may not have permission to access this file"
|
|
35831
|
+
);
|
|
35832
|
+
} else if (status === "404") {
|
|
35833
|
+
throw new Error(
|
|
35834
|
+
"File not found: The encrypted file is no longer available at the stored URL."
|
|
35835
|
+
);
|
|
35836
|
+
} else {
|
|
35837
|
+
throw new Error(
|
|
35838
|
+
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
35839
|
+
);
|
|
35840
|
+
}
|
|
35841
|
+
}
|
|
35842
|
+
throw fetchError;
|
|
35843
|
+
}
|
|
35844
|
+
if (encryptedBlob.size === 0) {
|
|
35845
|
+
throw new Error("File is empty or could not be retrieved");
|
|
35846
|
+
}
|
|
35847
|
+
let decryptedBlob;
|
|
35848
|
+
try {
|
|
35849
|
+
decryptedBlob = await decryptBlobWithSignedKey(
|
|
35850
|
+
encryptedBlob,
|
|
35851
|
+
encryptionKey,
|
|
35852
|
+
this.context.platform
|
|
35853
|
+
);
|
|
35854
|
+
} catch (decryptError) {
|
|
35855
|
+
const errorMessage = decryptError instanceof Error ? decryptError.message : "Unknown error";
|
|
35856
|
+
if (errorMessage.includes("not a valid OpenPGP message")) {
|
|
35857
|
+
throw new Error(
|
|
35858
|
+
"Invalid file format: This file doesn't appear to be encrypted with the Vana protocol"
|
|
35859
|
+
);
|
|
35860
|
+
} else if (errorMessage.includes("Session key decryption failed")) {
|
|
35861
|
+
throw new Error("Wrong encryption key");
|
|
35862
|
+
} else if (errorMessage.includes("Error decrypting message")) {
|
|
35863
|
+
throw new Error("Wrong encryption key");
|
|
35864
|
+
} else if (errorMessage.includes("File not found")) {
|
|
35865
|
+
throw new Error(
|
|
35866
|
+
"File not found: The encrypted file is no longer available"
|
|
35867
|
+
);
|
|
35868
|
+
} else {
|
|
35869
|
+
throw decryptError;
|
|
35870
|
+
}
|
|
35871
|
+
}
|
|
35872
|
+
return decryptedBlob;
|
|
35873
|
+
} catch (error) {
|
|
35874
|
+
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"))) {
|
|
35875
|
+
throw error;
|
|
35876
|
+
}
|
|
35877
|
+
throw new Error(
|
|
35878
|
+
`Failed to decrypt file: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
35879
|
+
);
|
|
35880
|
+
}
|
|
35881
|
+
}
|
|
35449
35882
|
/**
|
|
35450
35883
|
* Retrieves all data files owned by a specific user address.
|
|
35451
35884
|
*
|
|
@@ -36029,6 +36462,7 @@ var DataController = class {
|
|
|
36029
36462
|
/**
|
|
36030
36463
|
* Uploads an encrypted file to storage and registers it on the blockchain.
|
|
36031
36464
|
*
|
|
36465
|
+
* @deprecated Use vana.data.upload() instead for the high-level API with automatic encryption
|
|
36032
36466
|
* @param encryptedFile - The encrypted file blob to upload
|
|
36033
36467
|
* @param filename - Optional filename for the upload
|
|
36034
36468
|
* @param providerName - Optional storage provider to use
|
|
@@ -36116,6 +36550,7 @@ var DataController = class {
|
|
|
36116
36550
|
/**
|
|
36117
36551
|
* Uploads an encrypted file to storage and registers it on the blockchain with a schema.
|
|
36118
36552
|
*
|
|
36553
|
+
* @deprecated Use vana.data.upload() instead for the high-level API with automatic encryption and schema validation
|
|
36119
36554
|
* @param encryptedFile - The encrypted file blob to upload
|
|
36120
36555
|
* @param schemaId - The schema ID to associate with the file
|
|
36121
36556
|
* @param filename - Optional filename for the upload
|
|
@@ -36194,81 +36629,6 @@ var DataController = class {
|
|
|
36194
36629
|
);
|
|
36195
36630
|
}
|
|
36196
36631
|
}
|
|
36197
|
-
/**
|
|
36198
|
-
* Decrypts a file that was encrypted using the Vana protocol.
|
|
36199
|
-
*
|
|
36200
|
-
* @param file - The UserFile object containing the file URL and metadata
|
|
36201
|
-
* @param encryptionSeed - Optional custom encryption seed (defaults to Vana standard)
|
|
36202
|
-
* @returns Promise resolving to the decrypted file as a Blob
|
|
36203
|
-
*
|
|
36204
|
-
* This method handles the complete flow of:
|
|
36205
|
-
* 1. Generating the encryption key from the user's wallet signature
|
|
36206
|
-
* 2. Fetching the encrypted file from the stored URL
|
|
36207
|
-
* 3. Decrypting the file using the canonical Vana decryption method
|
|
36208
|
-
*/
|
|
36209
|
-
async decryptFile(file, encryptionSeed = DEFAULT_ENCRYPTION_SEED) {
|
|
36210
|
-
try {
|
|
36211
|
-
const encryptionKey = await generateEncryptionKey(
|
|
36212
|
-
this.context.walletClient,
|
|
36213
|
-
encryptionSeed
|
|
36214
|
-
);
|
|
36215
|
-
const fetchUrl = this.convertToDownloadUrl(file.url);
|
|
36216
|
-
console.debug(
|
|
36217
|
-
`Fetching encrypted file from URL: ${fetchUrl} (original: ${file.url})`
|
|
36218
|
-
);
|
|
36219
|
-
const response = await fetch(fetchUrl);
|
|
36220
|
-
if (!response.ok) {
|
|
36221
|
-
if (response.status === 404) {
|
|
36222
|
-
throw new Error(
|
|
36223
|
-
"File not found. The encrypted file may have been moved or deleted."
|
|
36224
|
-
);
|
|
36225
|
-
} else if (response.status === 403) {
|
|
36226
|
-
throw new Error(
|
|
36227
|
-
"Access denied. You may not have permission to access this file."
|
|
36228
|
-
);
|
|
36229
|
-
} else {
|
|
36230
|
-
throw new Error(
|
|
36231
|
-
`Network error: ${response.status} ${response.statusText}`
|
|
36232
|
-
);
|
|
36233
|
-
}
|
|
36234
|
-
}
|
|
36235
|
-
const encryptedBlob = await response.blob();
|
|
36236
|
-
console.debug(
|
|
36237
|
-
`Retrieved blob of size: ${encryptedBlob.size} bytes, type: ${encryptedBlob.type}`
|
|
36238
|
-
);
|
|
36239
|
-
if (encryptedBlob.size === 0) {
|
|
36240
|
-
throw new Error("File is empty or could not be retrieved.");
|
|
36241
|
-
}
|
|
36242
|
-
const decryptedBlob = await decryptUserData(
|
|
36243
|
-
encryptedBlob,
|
|
36244
|
-
encryptionKey,
|
|
36245
|
-
this.context.platform
|
|
36246
|
-
);
|
|
36247
|
-
return decryptedBlob;
|
|
36248
|
-
} catch (error) {
|
|
36249
|
-
console.error("Failed to decrypt file:", error);
|
|
36250
|
-
if (error instanceof Error) {
|
|
36251
|
-
if (error.message.includes("Session key decryption failed") || error.message.includes("Error decrypting message")) {
|
|
36252
|
-
throw new Error(
|
|
36253
|
-
"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."
|
|
36254
|
-
);
|
|
36255
|
-
} else if (error.message.includes("Failed to fetch") || error.message.includes("Network error")) {
|
|
36256
|
-
throw new Error(
|
|
36257
|
-
"Network error: Cannot access the file URL. The file may be stored on a server that's not accessible or has CORS restrictions."
|
|
36258
|
-
);
|
|
36259
|
-
} else if (error.message.includes("File not found")) {
|
|
36260
|
-
throw new Error(
|
|
36261
|
-
"File not found: The encrypted file is no longer available at the stored URL."
|
|
36262
|
-
);
|
|
36263
|
-
} else if (error.message.includes("not a valid OpenPGP message") || error.message.includes("does not conform to a valid OpenPGP format")) {
|
|
36264
|
-
throw new Error(
|
|
36265
|
-
"Invalid file format: This file doesn't appear to be encrypted with the Vana protocol."
|
|
36266
|
-
);
|
|
36267
|
-
}
|
|
36268
|
-
}
|
|
36269
|
-
throw error;
|
|
36270
|
-
}
|
|
36271
|
-
}
|
|
36272
36632
|
/**
|
|
36273
36633
|
* Registers a file URL directly on the blockchain with a schema ID.
|
|
36274
36634
|
*
|
|
@@ -36329,26 +36689,6 @@ var DataController = class {
|
|
|
36329
36689
|
);
|
|
36330
36690
|
}
|
|
36331
36691
|
}
|
|
36332
|
-
/**
|
|
36333
|
-
* Converts IPFS and Google Drive URLs to direct download URLs for fetching.
|
|
36334
|
-
*
|
|
36335
|
-
* @param url - The URL to convert to a direct download URL
|
|
36336
|
-
* @returns The converted direct download URL or the original URL if not a special URL
|
|
36337
|
-
*/
|
|
36338
|
-
convertToDownloadUrl(url) {
|
|
36339
|
-
if (url.startsWith("ipfs://")) {
|
|
36340
|
-
const hash = url.replace("ipfs://", "");
|
|
36341
|
-
return `https://ipfs.io/ipfs/${hash}`;
|
|
36342
|
-
}
|
|
36343
|
-
if (url.includes("drive.google.com/file/d/")) {
|
|
36344
|
-
const fileIdMatch = url.match(/\/file\/d\/([a-zA-Z0-9-_]+)/);
|
|
36345
|
-
if (fileIdMatch) {
|
|
36346
|
-
const fileId = fileIdMatch[1];
|
|
36347
|
-
return `https://drive.google.com/uc?id=${fileId}&export=download`;
|
|
36348
|
-
}
|
|
36349
|
-
}
|
|
36350
|
-
return url;
|
|
36351
|
-
}
|
|
36352
36692
|
/**
|
|
36353
36693
|
* Gets the user's address from the wallet client.
|
|
36354
36694
|
*
|
|
@@ -36423,9 +36763,70 @@ var DataController = class {
|
|
|
36423
36763
|
);
|
|
36424
36764
|
}
|
|
36425
36765
|
}
|
|
36766
|
+
/**
|
|
36767
|
+
* Adds a file to the registry with permissions and schema.
|
|
36768
|
+
* This combines the functionality of addFileWithPermissions and schema validation.
|
|
36769
|
+
*
|
|
36770
|
+
* @param url - The URL of the file to register
|
|
36771
|
+
* @param ownerAddress - The address of the file owner
|
|
36772
|
+
* @param permissions - Array of permissions to grant (account and encrypted key)
|
|
36773
|
+
* @param schemaId - The schema ID to associate with the file (0 for no schema)
|
|
36774
|
+
* @returns Promise resolving to object with fileId and transactionHash
|
|
36775
|
+
*/
|
|
36776
|
+
async addFileWithPermissionsAndSchema(url, ownerAddress, permissions = [], schemaId = 0) {
|
|
36777
|
+
try {
|
|
36778
|
+
const chainId = this.context.walletClient.chain?.id;
|
|
36779
|
+
if (!chainId) {
|
|
36780
|
+
throw new Error("Chain ID not available");
|
|
36781
|
+
}
|
|
36782
|
+
const dataRegistryAddress = getContractAddress(chainId, "DataRegistry");
|
|
36783
|
+
const dataRegistryAbi = getAbi("DataRegistry");
|
|
36784
|
+
const txHash = await this.context.walletClient.writeContract({
|
|
36785
|
+
address: dataRegistryAddress,
|
|
36786
|
+
abi: dataRegistryAbi,
|
|
36787
|
+
functionName: "addFileWithPermissionsAndSchema",
|
|
36788
|
+
args: [url, ownerAddress, permissions, BigInt(schemaId)],
|
|
36789
|
+
account: this.context.walletClient.account || ownerAddress,
|
|
36790
|
+
chain: this.context.walletClient.chain || null
|
|
36791
|
+
});
|
|
36792
|
+
const receipt = await this.context.publicClient.waitForTransactionReceipt(
|
|
36793
|
+
{
|
|
36794
|
+
hash: txHash,
|
|
36795
|
+
timeout: 3e4
|
|
36796
|
+
// 30 seconds timeout
|
|
36797
|
+
}
|
|
36798
|
+
);
|
|
36799
|
+
let fileId = 0;
|
|
36800
|
+
for (const log of receipt.logs) {
|
|
36801
|
+
try {
|
|
36802
|
+
const decoded = decodeEventLog({
|
|
36803
|
+
abi: dataRegistryAbi,
|
|
36804
|
+
data: log.data,
|
|
36805
|
+
topics: log.topics
|
|
36806
|
+
});
|
|
36807
|
+
if (decoded.eventName === "FileAdded") {
|
|
36808
|
+
fileId = Number(decoded.args.fileId);
|
|
36809
|
+
break;
|
|
36810
|
+
}
|
|
36811
|
+
} catch {
|
|
36812
|
+
continue;
|
|
36813
|
+
}
|
|
36814
|
+
}
|
|
36815
|
+
return {
|
|
36816
|
+
fileId,
|
|
36817
|
+
transactionHash: txHash
|
|
36818
|
+
};
|
|
36819
|
+
} catch (error) {
|
|
36820
|
+
console.error("Failed to add file with permissions and schema:", error);
|
|
36821
|
+
throw new Error(
|
|
36822
|
+
`Failed to add file with permissions and schema: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
36823
|
+
);
|
|
36824
|
+
}
|
|
36825
|
+
}
|
|
36426
36826
|
/**
|
|
36427
36827
|
* Adds a new schema to the DataRefinerRegistry.
|
|
36428
36828
|
*
|
|
36829
|
+
* @deprecated Use vana.schemas.create() instead for the high-level API with automatic IPFS upload
|
|
36429
36830
|
* @param params - Schema parameters including name, type, and definition URL
|
|
36430
36831
|
* @returns Promise resolving to the new schema ID and transaction hash
|
|
36431
36832
|
*/
|
|
@@ -36484,6 +36885,7 @@ var DataController = class {
|
|
|
36484
36885
|
/**
|
|
36485
36886
|
* Retrieves a schema by its ID.
|
|
36486
36887
|
*
|
|
36888
|
+
* @deprecated Use vana.schemas.get() instead
|
|
36487
36889
|
* @param schemaId - The schema ID to retrieve
|
|
36488
36890
|
* @returns Promise resolving to the schema information
|
|
36489
36891
|
*/
|
|
@@ -36509,11 +36911,15 @@ var DataController = class {
|
|
|
36509
36911
|
if (!schemaData) {
|
|
36510
36912
|
throw new Error("Schema not found");
|
|
36511
36913
|
}
|
|
36914
|
+
const schemaObj = schemaData;
|
|
36915
|
+
if (!schemaObj.name || !schemaObj.typ || !schemaObj.definitionUrl) {
|
|
36916
|
+
throw new Error("Incomplete schema data");
|
|
36917
|
+
}
|
|
36512
36918
|
return {
|
|
36513
36919
|
id: schemaId,
|
|
36514
|
-
name:
|
|
36515
|
-
type:
|
|
36516
|
-
definitionUrl:
|
|
36920
|
+
name: schemaObj.name,
|
|
36921
|
+
type: schemaObj.typ,
|
|
36922
|
+
definitionUrl: schemaObj.definitionUrl
|
|
36517
36923
|
};
|
|
36518
36924
|
} catch (error) {
|
|
36519
36925
|
console.error("Failed to get schema:", error);
|
|
@@ -36525,6 +36931,7 @@ var DataController = class {
|
|
|
36525
36931
|
/**
|
|
36526
36932
|
* Gets the total number of schemas in the registry.
|
|
36527
36933
|
*
|
|
36934
|
+
* @deprecated Use vana.schemas.count() instead
|
|
36528
36935
|
* @returns Promise resolving to the total schema count
|
|
36529
36936
|
*/
|
|
36530
36937
|
async getSchemasCount() {
|
|
@@ -36570,7 +36977,7 @@ var DataController = class {
|
|
|
36570
36977
|
const txHash = await this.context.walletClient.writeContract({
|
|
36571
36978
|
address: dataRefinerRegistryAddress,
|
|
36572
36979
|
abi: dataRefinerRegistryAbi,
|
|
36573
|
-
functionName: "
|
|
36980
|
+
functionName: "addRefinerWithSchemaId",
|
|
36574
36981
|
args: [
|
|
36575
36982
|
BigInt(params.dlpId),
|
|
36576
36983
|
params.name,
|
|
@@ -36773,9 +37180,10 @@ var DataController = class {
|
|
|
36773
37180
|
try {
|
|
36774
37181
|
const userEncryptionKey = await generateEncryptionKey(
|
|
36775
37182
|
this.context.walletClient,
|
|
37183
|
+
this.context.platform,
|
|
36776
37184
|
DEFAULT_ENCRYPTION_SEED
|
|
36777
37185
|
);
|
|
36778
|
-
const encryptedData = await
|
|
37186
|
+
const encryptedData = await encryptBlobWithSignedKey(
|
|
36779
37187
|
data,
|
|
36780
37188
|
userEncryptionKey,
|
|
36781
37189
|
this.context.platform
|
|
@@ -36838,16 +37246,47 @@ var DataController = class {
|
|
|
36838
37246
|
* 1. Gets the user's encryption key
|
|
36839
37247
|
* 2. Encrypts the user's encryption key with the provided public key
|
|
36840
37248
|
* 3. Adds the permission to the file
|
|
37249
|
+
* 4. Returns the permission data from the blockchain event
|
|
37250
|
+
*
|
|
37251
|
+
* For advanced users who need more control over transaction timing,
|
|
37252
|
+
* use `submitFilePermission()` instead.
|
|
36841
37253
|
*
|
|
36842
37254
|
* @param fileId - The ID of the file to add permissions for
|
|
36843
37255
|
* @param account - The address of the account to grant permission to
|
|
36844
37256
|
* @param publicKey - The public key to encrypt the user's encryption key with
|
|
36845
|
-
* @returns Promise resolving to
|
|
37257
|
+
* @returns Promise resolving to permission data from PermissionGranted event
|
|
37258
|
+
* @example
|
|
37259
|
+
* ```typescript
|
|
37260
|
+
* const result = await vana.data.addPermissionToFile(fileId, account, publicKey);
|
|
37261
|
+
* console.log(`Permission granted to ${result.account} for file ${result.fileId}`);
|
|
37262
|
+
* console.log(`Transaction: ${result.transactionHash}`);
|
|
37263
|
+
* ```
|
|
36846
37264
|
*/
|
|
36847
37265
|
async addPermissionToFile(fileId, account, publicKey) {
|
|
37266
|
+
const txHash = await this.submitFilePermission(fileId, account, publicKey);
|
|
37267
|
+
return parseTransactionResult(this.context, txHash, "addFilePermission");
|
|
37268
|
+
}
|
|
37269
|
+
/**
|
|
37270
|
+
* Submits a file permission transaction and returns the transaction hash immediately.
|
|
37271
|
+
*
|
|
37272
|
+
* This is the lower-level method that provides maximum control over transaction timing.
|
|
37273
|
+
* Use this when you want to handle transaction confirmation and event parsing separately.
|
|
37274
|
+
*
|
|
37275
|
+
* @param fileId - The ID of the file to add permissions for
|
|
37276
|
+
* @param account - The address of the account to grant permission to
|
|
37277
|
+
* @param publicKey - The public key to encrypt the user's encryption key with
|
|
37278
|
+
* @returns Promise resolving to the transaction hash
|
|
37279
|
+
* @example
|
|
37280
|
+
* ```typescript
|
|
37281
|
+
* const txHash = await vana.data.submitFilePermission(fileId, account, publicKey);
|
|
37282
|
+
* console.log(`Transaction submitted: ${txHash}`);
|
|
37283
|
+
* ```
|
|
37284
|
+
*/
|
|
37285
|
+
async submitFilePermission(fileId, account, publicKey) {
|
|
36848
37286
|
try {
|
|
36849
37287
|
const userEncryptionKey = await generateEncryptionKey(
|
|
36850
37288
|
this.context.walletClient,
|
|
37289
|
+
this.context.platform,
|
|
36851
37290
|
DEFAULT_ENCRYPTION_SEED
|
|
36852
37291
|
);
|
|
36853
37292
|
const encryptedKey = await encryptWithWalletPublicKey(
|
|
@@ -36939,12 +37378,13 @@ var DataController = class {
|
|
|
36939
37378
|
privateKey,
|
|
36940
37379
|
this.context.platform
|
|
36941
37380
|
);
|
|
36942
|
-
|
|
36943
|
-
if (
|
|
36944
|
-
|
|
37381
|
+
let encryptedData;
|
|
37382
|
+
if (file.url.startsWith("ipfs://")) {
|
|
37383
|
+
encryptedData = await this.fetchFromIPFS(file.url);
|
|
37384
|
+
} else {
|
|
37385
|
+
encryptedData = await this.fetch(file.url);
|
|
36945
37386
|
}
|
|
36946
|
-
const
|
|
36947
|
-
const decryptedData = await decryptUserData(
|
|
37387
|
+
const decryptedData = await decryptBlobWithSignedKey(
|
|
36948
37388
|
encryptedData,
|
|
36949
37389
|
userEncryptionKey,
|
|
36950
37390
|
this.context.platform
|
|
@@ -36957,6 +37397,162 @@ var DataController = class {
|
|
|
36957
37397
|
);
|
|
36958
37398
|
}
|
|
36959
37399
|
}
|
|
37400
|
+
/**
|
|
37401
|
+
* Simple network-agnostic fetch utility for retrieving file content.
|
|
37402
|
+
*
|
|
37403
|
+
* @remarks
|
|
37404
|
+
* This is a thin wrapper around the global fetch API that returns the response as a Blob.
|
|
37405
|
+
* It provides a consistent interface for fetching encrypted content before decryption.
|
|
37406
|
+
* For IPFS URLs, consider using fetchFromIPFS for better reliability.
|
|
37407
|
+
*
|
|
37408
|
+
* @param url - The URL to fetch content from
|
|
37409
|
+
* @returns Promise resolving to the fetched content as a Blob
|
|
37410
|
+
* @throws {Error} When the fetch fails or returns a non-ok response
|
|
37411
|
+
*
|
|
37412
|
+
* @example
|
|
37413
|
+
* ```typescript
|
|
37414
|
+
* // Fetch and decrypt a file
|
|
37415
|
+
* const encryptionKey = await generateEncryptionKey(walletClient);
|
|
37416
|
+
* const encryptedBlob = await vana.data.fetch(file.url);
|
|
37417
|
+
* const decryptedBlob = await decryptBlob(encryptedBlob, encryptionKey, platform);
|
|
37418
|
+
*
|
|
37419
|
+
* // With custom headers for authentication
|
|
37420
|
+
* const response = await fetch(file.url, {
|
|
37421
|
+
* headers: { 'Authorization': 'Bearer token' }
|
|
37422
|
+
* });
|
|
37423
|
+
* const encryptedBlob = await response.blob();
|
|
37424
|
+
* ```
|
|
37425
|
+
*/
|
|
37426
|
+
async fetch(url) {
|
|
37427
|
+
try {
|
|
37428
|
+
const response = await fetch(url);
|
|
37429
|
+
if (!response.ok) {
|
|
37430
|
+
throw new Error(
|
|
37431
|
+
`HTTP error! status: ${response.status} ${response.statusText}`
|
|
37432
|
+
);
|
|
37433
|
+
}
|
|
37434
|
+
const blob = await response.blob();
|
|
37435
|
+
if (blob.size === 0) {
|
|
37436
|
+
throw new Error("Empty response");
|
|
37437
|
+
}
|
|
37438
|
+
return blob;
|
|
37439
|
+
} catch (error) {
|
|
37440
|
+
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
37441
|
+
throw new Error(
|
|
37442
|
+
`Network error: Failed to fetch from ${url}. The URL may be invalid or the server may not be accessible.`
|
|
37443
|
+
);
|
|
37444
|
+
}
|
|
37445
|
+
throw error;
|
|
37446
|
+
}
|
|
37447
|
+
}
|
|
37448
|
+
/**
|
|
37449
|
+
* Specialized IPFS fetcher with gateway fallback mechanism.
|
|
37450
|
+
*
|
|
37451
|
+
* @remarks
|
|
37452
|
+
* This method provides robust IPFS content fetching by trying multiple gateways
|
|
37453
|
+
* in sequence until one succeeds. It supports both ipfs:// URLs and raw CIDs.
|
|
37454
|
+
*
|
|
37455
|
+
* The default gateway list includes public gateways, but you should provide
|
|
37456
|
+
* your own gateways for production use to ensure reliability and privacy.
|
|
37457
|
+
*
|
|
37458
|
+
* @param url - The IPFS URL (ipfs://...) or CID to fetch
|
|
37459
|
+
* @param options - Optional configuration
|
|
37460
|
+
* @param options.gateways - Array of IPFS gateway URLs to try (must end with /)
|
|
37461
|
+
* @returns Promise resolving to the fetched content as a Blob
|
|
37462
|
+
* @throws {Error} When all gateways fail to fetch the content
|
|
37463
|
+
*
|
|
37464
|
+
* @example
|
|
37465
|
+
* ```typescript
|
|
37466
|
+
* // Fetch from IPFS with custom gateways
|
|
37467
|
+
* const encryptedBlob = await vana.data.fetchFromIPFS(file.url, {
|
|
37468
|
+
* gateways: [
|
|
37469
|
+
* 'https://my-private-gateway.com/ipfs/',
|
|
37470
|
+
* 'https://dweb.link/ipfs/',
|
|
37471
|
+
* 'https://ipfs.io/ipfs/'
|
|
37472
|
+
* ]
|
|
37473
|
+
* });
|
|
37474
|
+
*
|
|
37475
|
+
* // Decrypt the fetched content
|
|
37476
|
+
* const encryptionKey = await generateEncryptionKey(walletClient);
|
|
37477
|
+
* const decryptedBlob = await decryptBlob(encryptedBlob, encryptionKey, platform);
|
|
37478
|
+
*
|
|
37479
|
+
* // With raw CID
|
|
37480
|
+
* const blob = await vana.data.fetchFromIPFS('QmXxx...', {
|
|
37481
|
+
* gateways: ['https://ipfs.io/ipfs/']
|
|
37482
|
+
* });
|
|
37483
|
+
* ```
|
|
37484
|
+
*/
|
|
37485
|
+
async fetchFromIPFS(url, options) {
|
|
37486
|
+
const defaultGateways = [
|
|
37487
|
+
"https://dweb.link/ipfs/",
|
|
37488
|
+
"https://ipfs.io/ipfs/"
|
|
37489
|
+
];
|
|
37490
|
+
const gateways = options?.gateways || this.context.ipfsGateways || defaultGateways;
|
|
37491
|
+
let cid;
|
|
37492
|
+
if (url.startsWith("ipfs://")) {
|
|
37493
|
+
cid = url.replace("ipfs://", "");
|
|
37494
|
+
} else if (url.startsWith("Qm") || url.startsWith("bafy")) {
|
|
37495
|
+
cid = url;
|
|
37496
|
+
} else {
|
|
37497
|
+
throw new Error(
|
|
37498
|
+
`Invalid IPFS URL format. Expected ipfs://... or a raw CID, got: ${url}`
|
|
37499
|
+
);
|
|
37500
|
+
}
|
|
37501
|
+
const errors = [];
|
|
37502
|
+
for (let i = 0; i < gateways.length; i++) {
|
|
37503
|
+
const gateway = gateways[i];
|
|
37504
|
+
const isLastGateway = i === gateways.length - 1;
|
|
37505
|
+
const gatewayUrl = gateway.endsWith("/") ? `${gateway}${cid}` : `${gateway}/${cid}`;
|
|
37506
|
+
try {
|
|
37507
|
+
console.debug(`Trying IPFS gateway: ${gatewayUrl}`);
|
|
37508
|
+
const response = await fetch(gatewayUrl);
|
|
37509
|
+
if (response.ok) {
|
|
37510
|
+
const blob = await response.blob();
|
|
37511
|
+
if (blob.size > 0) {
|
|
37512
|
+
console.debug(`Successfully fetched from gateway: ${gateway}`);
|
|
37513
|
+
return blob;
|
|
37514
|
+
} else {
|
|
37515
|
+
if (isLastGateway) {
|
|
37516
|
+
throw new Error("Empty response");
|
|
37517
|
+
}
|
|
37518
|
+
errors.push({
|
|
37519
|
+
gateway,
|
|
37520
|
+
error: "Empty response"
|
|
37521
|
+
});
|
|
37522
|
+
}
|
|
37523
|
+
} else {
|
|
37524
|
+
if (isLastGateway) {
|
|
37525
|
+
if (response.status === 403) {
|
|
37526
|
+
throw new Error(`HTTP error! status: 403 ${response.statusText}`);
|
|
37527
|
+
} else if (response.status === 404) {
|
|
37528
|
+
throw new Error(`HTTP error! status: 404 ${response.statusText}`);
|
|
37529
|
+
} else {
|
|
37530
|
+
throw new Error(
|
|
37531
|
+
`HTTP error! status: ${response.status} ${response.statusText}`
|
|
37532
|
+
);
|
|
37533
|
+
}
|
|
37534
|
+
}
|
|
37535
|
+
errors.push({
|
|
37536
|
+
gateway,
|
|
37537
|
+
error: `HTTP ${response.status} ${response.statusText}`
|
|
37538
|
+
});
|
|
37539
|
+
}
|
|
37540
|
+
} catch (error) {
|
|
37541
|
+
if (isLastGateway && error instanceof Error && (error.message.includes("Empty response") || error.message.includes("HTTP error!"))) {
|
|
37542
|
+
throw error;
|
|
37543
|
+
}
|
|
37544
|
+
errors.push({
|
|
37545
|
+
gateway,
|
|
37546
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
37547
|
+
});
|
|
37548
|
+
}
|
|
37549
|
+
}
|
|
37550
|
+
const errorDetails = errors.map((e) => `${e.gateway}: ${e.error}`).join("\n ");
|
|
37551
|
+
throw new Error(
|
|
37552
|
+
`Failed to fetch IPFS content ${cid} from all gateways:
|
|
37553
|
+
${errorDetails}`
|
|
37554
|
+
);
|
|
37555
|
+
}
|
|
36960
37556
|
/**
|
|
36961
37557
|
* Validates a data schema against the Vana meta-schema.
|
|
36962
37558
|
*
|
|
@@ -37078,12 +37674,365 @@ var DataController = class {
|
|
|
37078
37674
|
}
|
|
37079
37675
|
};
|
|
37080
37676
|
|
|
37677
|
+
// src/controllers/schemas.ts
|
|
37678
|
+
import { getContract as getContract2, decodeEventLog as decodeEventLog2 } from "viem";
|
|
37679
|
+
var SchemaController = class {
|
|
37680
|
+
constructor(context) {
|
|
37681
|
+
this.context = context;
|
|
37682
|
+
}
|
|
37683
|
+
/**
|
|
37684
|
+
* Creates a new schema with automatic validation and IPFS upload.
|
|
37685
|
+
*
|
|
37686
|
+
* @remarks
|
|
37687
|
+
* This is the primary method for creating schemas on the Vana network. It handles
|
|
37688
|
+
* the complete workflow including schema validation, IPFS upload, and blockchain
|
|
37689
|
+
* registration. The schema definition is stored unencrypted on IPFS to enable
|
|
37690
|
+
* public access and reusability.
|
|
37691
|
+
*
|
|
37692
|
+
* The method automatically:
|
|
37693
|
+
* - Validates the schema definition against the Vana metaschema
|
|
37694
|
+
* - Uploads the definition to IPFS to generate a permanent URL
|
|
37695
|
+
* - Registers the schema on the blockchain with the generated URL
|
|
37696
|
+
*
|
|
37697
|
+
* @param params - Schema creation parameters including name, type, and definition
|
|
37698
|
+
* @returns Promise resolving to creation results with schema ID and transaction hash
|
|
37699
|
+
* @throws {SchemaValidationError} When the schema definition is invalid
|
|
37700
|
+
* @throws {Error} When IPFS upload or blockchain registration fails
|
|
37701
|
+
* @example
|
|
37702
|
+
* ```typescript
|
|
37703
|
+
* // Create a JSON schema for user profiles
|
|
37704
|
+
* const result = await vana.schemas.create({
|
|
37705
|
+
* name: "User Profile",
|
|
37706
|
+
* type: "personal",
|
|
37707
|
+
* definition: {
|
|
37708
|
+
* type: "object",
|
|
37709
|
+
* properties: {
|
|
37710
|
+
* name: { type: "string" },
|
|
37711
|
+
* age: { type: "number", minimum: 0 }
|
|
37712
|
+
* },
|
|
37713
|
+
* required: ["name"]
|
|
37714
|
+
* }
|
|
37715
|
+
* });
|
|
37716
|
+
*
|
|
37717
|
+
* console.log(`Schema created with ID: ${result.schemaId}`);
|
|
37718
|
+
* ```
|
|
37719
|
+
*/
|
|
37720
|
+
async create(params) {
|
|
37721
|
+
const { name, type, definition } = params;
|
|
37722
|
+
try {
|
|
37723
|
+
let schemaDefinition;
|
|
37724
|
+
if (typeof definition === "string") {
|
|
37725
|
+
try {
|
|
37726
|
+
schemaDefinition = JSON.parse(definition);
|
|
37727
|
+
} catch {
|
|
37728
|
+
throw new SchemaValidationError(
|
|
37729
|
+
"Invalid JSON in schema definition",
|
|
37730
|
+
[]
|
|
37731
|
+
);
|
|
37732
|
+
}
|
|
37733
|
+
} else {
|
|
37734
|
+
schemaDefinition = definition;
|
|
37735
|
+
}
|
|
37736
|
+
const dataSchema = {
|
|
37737
|
+
name,
|
|
37738
|
+
version: "1.0.0",
|
|
37739
|
+
dialect: "json",
|
|
37740
|
+
schema: schemaDefinition
|
|
37741
|
+
};
|
|
37742
|
+
validateDataSchema(dataSchema);
|
|
37743
|
+
if (!this.context.storageManager) {
|
|
37744
|
+
if (this.context.validateStorageRequired) {
|
|
37745
|
+
this.context.validateStorageRequired();
|
|
37746
|
+
throw new Error("Storage validation failed");
|
|
37747
|
+
} else {
|
|
37748
|
+
throw new Error(
|
|
37749
|
+
"Storage manager not configured. Please provide storage providers in VanaConfig."
|
|
37750
|
+
);
|
|
37751
|
+
}
|
|
37752
|
+
}
|
|
37753
|
+
const schemaBlob = new Blob([JSON.stringify(schemaDefinition)], {
|
|
37754
|
+
type: "application/json"
|
|
37755
|
+
});
|
|
37756
|
+
const uploadResult = await this.context.storageManager.upload(
|
|
37757
|
+
schemaBlob,
|
|
37758
|
+
`${name.replace(/[^a-zA-Z0-9]/g, "_")}.json`,
|
|
37759
|
+
"ipfs"
|
|
37760
|
+
// Use IPFS for public schema storage
|
|
37761
|
+
);
|
|
37762
|
+
const chainId = this.context.walletClient.chain?.id;
|
|
37763
|
+
if (!chainId) {
|
|
37764
|
+
throw new Error("Chain ID not available");
|
|
37765
|
+
}
|
|
37766
|
+
const dataRefinerRegistryAddress = getContractAddress(
|
|
37767
|
+
chainId,
|
|
37768
|
+
"DataRefinerRegistry"
|
|
37769
|
+
);
|
|
37770
|
+
const dataRefinerRegistryAbi = getAbi("DataRefinerRegistry");
|
|
37771
|
+
const userAddress = await this.getUserAddress();
|
|
37772
|
+
const txHash = await this.context.walletClient.writeContract({
|
|
37773
|
+
address: dataRefinerRegistryAddress,
|
|
37774
|
+
abi: dataRefinerRegistryAbi,
|
|
37775
|
+
functionName: "addSchema",
|
|
37776
|
+
args: [name, type, uploadResult.url],
|
|
37777
|
+
account: this.context.walletClient.account || userAddress,
|
|
37778
|
+
chain: this.context.walletClient.chain || null
|
|
37779
|
+
});
|
|
37780
|
+
const receipt = await this.context.publicClient.waitForTransactionReceipt(
|
|
37781
|
+
{
|
|
37782
|
+
hash: txHash,
|
|
37783
|
+
timeout: 3e4
|
|
37784
|
+
// 30 seconds timeout
|
|
37785
|
+
}
|
|
37786
|
+
);
|
|
37787
|
+
let schemaId = 0;
|
|
37788
|
+
for (const log of receipt.logs) {
|
|
37789
|
+
try {
|
|
37790
|
+
const decoded = decodeEventLog2({
|
|
37791
|
+
abi: dataRefinerRegistryAbi,
|
|
37792
|
+
data: log.data,
|
|
37793
|
+
topics: log.topics
|
|
37794
|
+
});
|
|
37795
|
+
if (decoded.eventName === "SchemaAdded") {
|
|
37796
|
+
schemaId = Number(decoded.args.schemaId);
|
|
37797
|
+
break;
|
|
37798
|
+
}
|
|
37799
|
+
} catch {
|
|
37800
|
+
}
|
|
37801
|
+
}
|
|
37802
|
+
return {
|
|
37803
|
+
schemaId,
|
|
37804
|
+
definitionUrl: uploadResult.url,
|
|
37805
|
+
transactionHash: txHash
|
|
37806
|
+
};
|
|
37807
|
+
} catch (error) {
|
|
37808
|
+
if (error instanceof SchemaValidationError) {
|
|
37809
|
+
throw error;
|
|
37810
|
+
}
|
|
37811
|
+
throw new Error(
|
|
37812
|
+
`Schema creation failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
37813
|
+
);
|
|
37814
|
+
}
|
|
37815
|
+
}
|
|
37816
|
+
/**
|
|
37817
|
+
* Retrieves a schema by its ID.
|
|
37818
|
+
*
|
|
37819
|
+
* @param schemaId - The ID of the schema to retrieve
|
|
37820
|
+
* @returns Promise resolving to the schema object
|
|
37821
|
+
* @throws {Error} When the schema is not found or chain is unavailable
|
|
37822
|
+
* @example
|
|
37823
|
+
* ```typescript
|
|
37824
|
+
* const schema = await vana.schemas.get(1);
|
|
37825
|
+
* console.log(`Schema: ${schema.name} (${schema.type})`);
|
|
37826
|
+
* ```
|
|
37827
|
+
*/
|
|
37828
|
+
async get(schemaId) {
|
|
37829
|
+
try {
|
|
37830
|
+
const chainId = this.context.walletClient.chain?.id;
|
|
37831
|
+
if (!chainId) {
|
|
37832
|
+
throw new Error("Chain ID not available");
|
|
37833
|
+
}
|
|
37834
|
+
const dataRefinerRegistryAddress = getContractAddress(
|
|
37835
|
+
chainId,
|
|
37836
|
+
"DataRefinerRegistry"
|
|
37837
|
+
);
|
|
37838
|
+
const dataRefinerRegistryAbi = getAbi("DataRefinerRegistry");
|
|
37839
|
+
const dataRefinerRegistry = getContract2({
|
|
37840
|
+
address: dataRefinerRegistryAddress,
|
|
37841
|
+
abi: dataRefinerRegistryAbi,
|
|
37842
|
+
client: this.context.publicClient
|
|
37843
|
+
});
|
|
37844
|
+
const schemaData = await dataRefinerRegistry.read.schemas([
|
|
37845
|
+
BigInt(schemaId)
|
|
37846
|
+
]);
|
|
37847
|
+
if (!schemaData) {
|
|
37848
|
+
throw new Error(`Schema with ID ${schemaId} not found`);
|
|
37849
|
+
}
|
|
37850
|
+
const schemaObj = schemaData;
|
|
37851
|
+
if (!schemaObj.name || !schemaObj.typ || !schemaObj.definitionUrl) {
|
|
37852
|
+
throw new Error("Incomplete schema data");
|
|
37853
|
+
}
|
|
37854
|
+
return {
|
|
37855
|
+
id: schemaId,
|
|
37856
|
+
name: schemaObj.name,
|
|
37857
|
+
type: schemaObj.typ,
|
|
37858
|
+
definitionUrl: schemaObj.definitionUrl
|
|
37859
|
+
};
|
|
37860
|
+
} catch (error) {
|
|
37861
|
+
throw new Error(
|
|
37862
|
+
`Failed to get schema: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
37863
|
+
);
|
|
37864
|
+
}
|
|
37865
|
+
}
|
|
37866
|
+
/**
|
|
37867
|
+
* Gets the total number of schemas registered on the network.
|
|
37868
|
+
*
|
|
37869
|
+
* @returns Promise resolving to the total schema count
|
|
37870
|
+
* @throws {Error} When the count cannot be retrieved
|
|
37871
|
+
* @example
|
|
37872
|
+
* ```typescript
|
|
37873
|
+
* const count = await vana.schemas.count();
|
|
37874
|
+
* console.log(`Total schemas: ${count}`);
|
|
37875
|
+
* ```
|
|
37876
|
+
*/
|
|
37877
|
+
async count() {
|
|
37878
|
+
try {
|
|
37879
|
+
const chainId = this.context.walletClient.chain?.id;
|
|
37880
|
+
if (!chainId) {
|
|
37881
|
+
throw new Error("Chain ID not available");
|
|
37882
|
+
}
|
|
37883
|
+
const dataRefinerRegistryAddress = getContractAddress(
|
|
37884
|
+
chainId,
|
|
37885
|
+
"DataRefinerRegistry"
|
|
37886
|
+
);
|
|
37887
|
+
const dataRefinerRegistryAbi = getAbi("DataRefinerRegistry");
|
|
37888
|
+
const dataRefinerRegistry = getContract2({
|
|
37889
|
+
address: dataRefinerRegistryAddress,
|
|
37890
|
+
abi: dataRefinerRegistryAbi,
|
|
37891
|
+
client: this.context.publicClient
|
|
37892
|
+
});
|
|
37893
|
+
const count = await dataRefinerRegistry.read.schemasCount();
|
|
37894
|
+
return Number(count);
|
|
37895
|
+
} catch (error) {
|
|
37896
|
+
throw new Error(
|
|
37897
|
+
`Failed to get schemas count: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
37898
|
+
);
|
|
37899
|
+
}
|
|
37900
|
+
}
|
|
37901
|
+
/**
|
|
37902
|
+
* Lists all schemas with pagination.
|
|
37903
|
+
*
|
|
37904
|
+
* @param options - Optional parameters for listing schemas
|
|
37905
|
+
* @param options.limit - Maximum number of schemas to return
|
|
37906
|
+
* @param options.offset - Number of schemas to skip
|
|
37907
|
+
* @returns Promise resolving to an array of schemas
|
|
37908
|
+
* @example
|
|
37909
|
+
* ```typescript
|
|
37910
|
+
* // Get all schemas
|
|
37911
|
+
* const schemas = await vana.schemas.list();
|
|
37912
|
+
*
|
|
37913
|
+
* // Get schemas with pagination
|
|
37914
|
+
* const schemas = await vana.schemas.list({ limit: 10, offset: 0 });
|
|
37915
|
+
* ```
|
|
37916
|
+
*/
|
|
37917
|
+
async list(options = {}) {
|
|
37918
|
+
const { limit = 100, offset = 0 } = options;
|
|
37919
|
+
try {
|
|
37920
|
+
const totalCount = await this.count();
|
|
37921
|
+
const schemas = [];
|
|
37922
|
+
const start = offset;
|
|
37923
|
+
const end = Math.min(start + limit, totalCount);
|
|
37924
|
+
for (let i = start; i < end; i++) {
|
|
37925
|
+
try {
|
|
37926
|
+
const schema = await this.get(i + 1);
|
|
37927
|
+
schemas.push(schema);
|
|
37928
|
+
} catch (error) {
|
|
37929
|
+
console.warn(`Failed to retrieve schema ${i + 1}:`, error);
|
|
37930
|
+
}
|
|
37931
|
+
}
|
|
37932
|
+
return schemas;
|
|
37933
|
+
} catch (error) {
|
|
37934
|
+
throw new Error(
|
|
37935
|
+
`Failed to list schemas: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
37936
|
+
);
|
|
37937
|
+
}
|
|
37938
|
+
}
|
|
37939
|
+
/**
|
|
37940
|
+
* Adds a schema using the legacy method (low-level API).
|
|
37941
|
+
*
|
|
37942
|
+
* @deprecated Use create() instead for the high-level API with automatic IPFS upload
|
|
37943
|
+
* @param params - Schema parameters including pre-generated definition URL
|
|
37944
|
+
* @returns Promise resolving to the add schema result
|
|
37945
|
+
*/
|
|
37946
|
+
async addSchema(params) {
|
|
37947
|
+
try {
|
|
37948
|
+
const chainId = this.context.walletClient.chain?.id;
|
|
37949
|
+
if (!chainId) {
|
|
37950
|
+
throw new Error("Chain ID not available");
|
|
37951
|
+
}
|
|
37952
|
+
const dataRefinerRegistryAddress = getContractAddress(
|
|
37953
|
+
chainId,
|
|
37954
|
+
"DataRefinerRegistry"
|
|
37955
|
+
);
|
|
37956
|
+
const dataRefinerRegistryAbi = getAbi("DataRefinerRegistry");
|
|
37957
|
+
const userAddress = await this.getUserAddress();
|
|
37958
|
+
const txHash = await this.context.walletClient.writeContract({
|
|
37959
|
+
address: dataRefinerRegistryAddress,
|
|
37960
|
+
abi: dataRefinerRegistryAbi,
|
|
37961
|
+
functionName: "addSchema",
|
|
37962
|
+
args: [params.name, params.type, params.definitionUrl],
|
|
37963
|
+
account: this.context.walletClient.account || userAddress,
|
|
37964
|
+
chain: this.context.walletClient.chain || null
|
|
37965
|
+
});
|
|
37966
|
+
return {
|
|
37967
|
+
schemaId: 0,
|
|
37968
|
+
// TODO: Parse from transaction receipt
|
|
37969
|
+
transactionHash: txHash
|
|
37970
|
+
};
|
|
37971
|
+
} catch (error) {
|
|
37972
|
+
throw new Error(
|
|
37973
|
+
`Failed to add schema: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
37974
|
+
);
|
|
37975
|
+
}
|
|
37976
|
+
}
|
|
37977
|
+
/**
|
|
37978
|
+
* Gets the user's wallet address.
|
|
37979
|
+
*
|
|
37980
|
+
* @private
|
|
37981
|
+
* @returns Promise resolving to the user's address
|
|
37982
|
+
*/
|
|
37983
|
+
async getUserAddress() {
|
|
37984
|
+
if (!this.context.walletClient.account) {
|
|
37985
|
+
throw new Error("No wallet account connected");
|
|
37986
|
+
}
|
|
37987
|
+
if (typeof this.context.walletClient.account === "string") {
|
|
37988
|
+
return this.context.walletClient.account;
|
|
37989
|
+
}
|
|
37990
|
+
if (typeof this.context.walletClient.account === "object" && this.context.walletClient.account.address) {
|
|
37991
|
+
return this.context.walletClient.account.address;
|
|
37992
|
+
}
|
|
37993
|
+
throw new Error("Unable to determine wallet address");
|
|
37994
|
+
}
|
|
37995
|
+
};
|
|
37996
|
+
|
|
37081
37997
|
// src/controllers/server.ts
|
|
37082
37998
|
var ServerController = class {
|
|
37083
37999
|
constructor(context) {
|
|
37084
38000
|
this.context = context;
|
|
37085
38001
|
__publicField(this, "PERSONAL_SERVER_BASE_URL", process.env.NEXT_PUBLIC_PERSONAL_SERVER_BASE_URL);
|
|
37086
38002
|
}
|
|
38003
|
+
/**
|
|
38004
|
+
* Retrieves the cryptographic identity of a personal server.
|
|
38005
|
+
*
|
|
38006
|
+
* @remarks
|
|
38007
|
+
* This method fetches the public key and metadata for a personal server,
|
|
38008
|
+
* which is required for encrypting data before sharing with the server.
|
|
38009
|
+
* The identity includes the server's public key, address, and operational
|
|
38010
|
+
* details needed for secure communication. This information is cached
|
|
38011
|
+
* by identity servers to enable offline key retrieval.
|
|
38012
|
+
*
|
|
38013
|
+
* @param request - Parameters containing the user address
|
|
38014
|
+
* @param request.userAddress - The wallet address associated with the personal server
|
|
38015
|
+
* @returns Promise resolving to the server's identity information
|
|
38016
|
+
* @throws {NetworkError} When the identity service is unavailable or returns invalid data
|
|
38017
|
+
* @throws {PersonalServerError} When server identity cannot be retrieved
|
|
38018
|
+
* @example
|
|
38019
|
+
* ```typescript
|
|
38020
|
+
* // Get server identity for data encryption
|
|
38021
|
+
* const identity = await vana.server.getIdentity({
|
|
38022
|
+
* userAddress: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36"
|
|
38023
|
+
* });
|
|
38024
|
+
*
|
|
38025
|
+
* console.log(`Server: ${identity.name}`);
|
|
38026
|
+
* console.log(`Address: ${identity.address}`);
|
|
38027
|
+
* console.log(`Public Key: ${identity.public_key}`);
|
|
38028
|
+
*
|
|
38029
|
+
* // Use the public key for encrypting data to share with this server
|
|
38030
|
+
* const encryptedData = await encryptWithWalletPublicKey(
|
|
38031
|
+
* userData,
|
|
38032
|
+
* identity.public_key
|
|
38033
|
+
* );
|
|
38034
|
+
* ```
|
|
38035
|
+
*/
|
|
37087
38036
|
async getIdentity(request) {
|
|
37088
38037
|
try {
|
|
37089
38038
|
const response = await fetch(
|
|
@@ -37104,6 +38053,7 @@ var ServerController = class {
|
|
|
37104
38053
|
}
|
|
37105
38054
|
const serverResponse = await response.json();
|
|
37106
38055
|
return {
|
|
38056
|
+
kind: serverResponse.personal_server.kind,
|
|
37107
38057
|
address: serverResponse.personal_server.address,
|
|
37108
38058
|
public_key: serverResponse.personal_server.public_key,
|
|
37109
38059
|
base_url: this.PERSONAL_SERVER_BASE_URL || "",
|
|
@@ -37125,10 +38075,13 @@ var ServerController = class {
|
|
|
37125
38075
|
* This method submits a computation request to the personal server API.
|
|
37126
38076
|
* The response includes the operation ID.
|
|
37127
38077
|
* @param params - The request parameters object
|
|
37128
|
-
* @param params.permissionId - The permission ID authorizing this operation
|
|
38078
|
+
* @param params.permissionId - The permission ID authorizing this operation.
|
|
38079
|
+
* Obtain from granted permissions via `vana.permissions.getUserPermissionGrantsOnChain()`.
|
|
37129
38080
|
* @returns A Promise that resolves to an operation response with status and control URLs
|
|
37130
|
-
* @throws {PersonalServerError} When server request fails or parameters are invalid
|
|
37131
|
-
*
|
|
38081
|
+
* @throws {PersonalServerError} When server request fails or parameters are invalid.
|
|
38082
|
+
* Verify permissionId exists and is active for the target server.
|
|
38083
|
+
* @throws {NetworkError} When personal server API communication fails.
|
|
38084
|
+
* Check server URL configuration and network connectivity.
|
|
37132
38085
|
* @example
|
|
37133
38086
|
* ```typescript
|
|
37134
38087
|
* const response = await vana.server.createOperation({
|
|
@@ -37230,6 +38183,50 @@ var ServerController = class {
|
|
|
37230
38183
|
);
|
|
37231
38184
|
}
|
|
37232
38185
|
}
|
|
38186
|
+
/**
|
|
38187
|
+
* Cancels a running operation on the personal server.
|
|
38188
|
+
*
|
|
38189
|
+
* @remarks
|
|
38190
|
+
* This method attempts to cancel an operation that is currently processing
|
|
38191
|
+
* on the personal server. The operation must be in a cancellable state
|
|
38192
|
+
* (typically `starting` or `processing`). Not all operations support
|
|
38193
|
+
* cancellation, and cancellation may not be immediate. The server will
|
|
38194
|
+
* attempt to stop the operation and update its status to `canceled`.
|
|
38195
|
+
*
|
|
38196
|
+
* **Cancellation Behavior:**
|
|
38197
|
+
* - Operations in `succeeded` or `failed` states cannot be canceled
|
|
38198
|
+
* - Some long-running operations may take time to respond to cancellation
|
|
38199
|
+
* - Always verify cancellation by polling the operation status afterward
|
|
38200
|
+
*
|
|
38201
|
+
* @param operationId - The unique identifier of the operation to cancel,
|
|
38202
|
+
* obtained from `createOperation()` response
|
|
38203
|
+
* @returns Promise that resolves when the cancellation request is accepted
|
|
38204
|
+
* @throws {PersonalServerError} When the operation cannot be canceled or doesn't exist.
|
|
38205
|
+
* Check operation status - it may already be completed or failed.
|
|
38206
|
+
* @throws {NetworkError} When unable to reach the personal server API.
|
|
38207
|
+
* Verify server URL and network connectivity.
|
|
38208
|
+
* @example
|
|
38209
|
+
* ```typescript
|
|
38210
|
+
* // Start a long-running operation
|
|
38211
|
+
* const operation = await vana.server.createOperation({
|
|
38212
|
+
* permissionId: 123
|
|
38213
|
+
* });
|
|
38214
|
+
*
|
|
38215
|
+
* // Cancel if needed
|
|
38216
|
+
* try {
|
|
38217
|
+
* await vana.server.cancelOperation(operation.id);
|
|
38218
|
+
* console.log("Cancellation requested");
|
|
38219
|
+
*
|
|
38220
|
+
* // Verify cancellation
|
|
38221
|
+
* const status = await vana.server.getOperation(operation.id);
|
|
38222
|
+
* if (status.status === "canceled") {
|
|
38223
|
+
* console.log("Operation successfully canceled");
|
|
38224
|
+
* }
|
|
38225
|
+
* } catch (error) {
|
|
38226
|
+
* console.error("Failed to cancel:", error);
|
|
38227
|
+
* }
|
|
38228
|
+
* ```
|
|
38229
|
+
*/
|
|
37233
38230
|
async cancelOperation(operationId) {
|
|
37234
38231
|
try {
|
|
37235
38232
|
const response = await fetch(
|
|
@@ -37256,7 +38253,7 @@ var ServerController = class {
|
|
|
37256
38253
|
/**
|
|
37257
38254
|
* Makes the request to the personal server API.
|
|
37258
38255
|
*
|
|
37259
|
-
* @param
|
|
38256
|
+
* @param requestBody - The post request parameters to serialize
|
|
37260
38257
|
* @returns JSON string representation of the request data
|
|
37261
38258
|
*/
|
|
37262
38259
|
async makeRequest(requestBody) {
|
|
@@ -37339,7 +38336,7 @@ var ServerController = class {
|
|
|
37339
38336
|
|
|
37340
38337
|
// src/contracts/contractController.ts
|
|
37341
38338
|
import {
|
|
37342
|
-
getContract as
|
|
38339
|
+
getContract as getContract3
|
|
37343
38340
|
} from "viem";
|
|
37344
38341
|
|
|
37345
38342
|
// src/core/client.ts
|
|
@@ -37440,7 +38437,7 @@ function getContractController(contract, client = createClient()) {
|
|
|
37440
38437
|
const cacheKey = createCacheKey(contract, chainId);
|
|
37441
38438
|
let controller = contractCache.get(cacheKey);
|
|
37442
38439
|
if (!controller) {
|
|
37443
|
-
controller =
|
|
38440
|
+
controller = getContract3({
|
|
37444
38441
|
address: getContractAddress(chainId, contract),
|
|
37445
38442
|
abi: getAbi(contract),
|
|
37446
38443
|
client
|
|
@@ -37533,7 +38530,8 @@ var ProtocolController = class {
|
|
|
37533
38530
|
* are actually deployed on the current network.
|
|
37534
38531
|
* @param contractName - The name of the Vana contract to retrieve (use const assertion for full typing)
|
|
37535
38532
|
* @returns An object containing the contract's address and fully typed ABI
|
|
37536
|
-
* @throws {ContractNotFoundError} When the contract is not deployed on the current chain
|
|
38533
|
+
* @throws {ContractNotFoundError} When the contract is not deployed on the current chain.
|
|
38534
|
+
* Verify contract name spelling and check current network with `getChainId()`.
|
|
37537
38535
|
* @example
|
|
37538
38536
|
* ```typescript
|
|
37539
38537
|
* // Get contract info with full type inference
|
|
@@ -38154,6 +39152,7 @@ var GoogleDriveStorage = class {
|
|
|
38154
39152
|
};
|
|
38155
39153
|
|
|
38156
39154
|
// src/storage/providers/ipfs.ts
|
|
39155
|
+
init_crypto_utils();
|
|
38157
39156
|
var IpfsStorage = class _IpfsStorage {
|
|
38158
39157
|
constructor(config) {
|
|
38159
39158
|
this.config = config;
|
|
@@ -38193,7 +39192,7 @@ var IpfsStorage = class _IpfsStorage {
|
|
|
38193
39192
|
* ```
|
|
38194
39193
|
*/
|
|
38195
39194
|
static forInfura(credentials) {
|
|
38196
|
-
const auth =
|
|
39195
|
+
const auth = toBase64(`${credentials.projectId}:${credentials.projectSecret}`);
|
|
38197
39196
|
return new _IpfsStorage({
|
|
38198
39197
|
apiEndpoint: "https://ipfs.infura.io:5001/api/v0/add",
|
|
38199
39198
|
gatewayUrl: "https://ipfs.infura.io/ipfs",
|
|
@@ -38717,175 +39716,151 @@ var PinataStorage = class {
|
|
|
38717
39716
|
}
|
|
38718
39717
|
};
|
|
38719
39718
|
|
|
38720
|
-
// src/storage/providers/
|
|
38721
|
-
var
|
|
38722
|
-
constructor(
|
|
38723
|
-
this.
|
|
38724
|
-
if (!
|
|
38725
|
-
throw new
|
|
38726
|
-
"
|
|
38727
|
-
"MISSING_UPLOAD_URL",
|
|
38728
|
-
"server-proxy"
|
|
38729
|
-
);
|
|
38730
|
-
}
|
|
38731
|
-
if (!config.downloadUrl) {
|
|
38732
|
-
throw new StorageError(
|
|
38733
|
-
"Download URL is required",
|
|
38734
|
-
"MISSING_DOWNLOAD_URL",
|
|
38735
|
-
"server-proxy"
|
|
39719
|
+
// src/storage/providers/callback-storage.ts
|
|
39720
|
+
var CallbackStorage = class {
|
|
39721
|
+
constructor(callbacks) {
|
|
39722
|
+
this.callbacks = callbacks;
|
|
39723
|
+
if (!callbacks.upload || !callbacks.download) {
|
|
39724
|
+
throw new Error(
|
|
39725
|
+
"CallbackStorage requires both upload and download callbacks"
|
|
38736
39726
|
);
|
|
38737
39727
|
}
|
|
38738
39728
|
}
|
|
38739
39729
|
/**
|
|
38740
|
-
*
|
|
39730
|
+
* Upload a file using the provided callback
|
|
38741
39731
|
*
|
|
38742
|
-
* @
|
|
38743
|
-
*
|
|
38744
|
-
*
|
|
38745
|
-
* and must return a JSON response with `success: true` and an `identifier` field.
|
|
38746
|
-
*
|
|
38747
|
-
* @param file - The file to upload
|
|
38748
|
-
* @param filename - Optional custom filename
|
|
38749
|
-
* @returns Promise that resolves to the server-provided identifier
|
|
38750
|
-
* @throws {StorageError} When the upload fails or server returns an error
|
|
38751
|
-
*
|
|
38752
|
-
* @example
|
|
38753
|
-
* ```typescript
|
|
38754
|
-
* const identifier = await serverStorage.upload(fileBlob, { name: "report.pdf" });
|
|
38755
|
-
* console.log("File uploaded with identifier:", identifier);
|
|
38756
|
-
* ```
|
|
39732
|
+
* @param file - The blob to upload
|
|
39733
|
+
* @param filename - Optional filename for the upload
|
|
39734
|
+
* @returns The upload result with URL and metadata
|
|
38757
39735
|
*/
|
|
38758
39736
|
async upload(file, filename) {
|
|
38759
39737
|
try {
|
|
38760
|
-
const
|
|
38761
|
-
|
|
38762
|
-
if (filename) {
|
|
38763
|
-
formData.append("name", filename);
|
|
38764
|
-
}
|
|
38765
|
-
const response = await fetch(this.config.uploadUrl, {
|
|
38766
|
-
method: "POST",
|
|
38767
|
-
body: formData
|
|
38768
|
-
});
|
|
38769
|
-
if (!response.ok) {
|
|
38770
|
-
const _errorText = await response.text();
|
|
38771
|
-
throw new StorageError(
|
|
38772
|
-
`Server upload failed: ${response.status} ${response.statusText}`,
|
|
38773
|
-
"UPLOAD_FAILED",
|
|
38774
|
-
"server-proxy"
|
|
38775
|
-
);
|
|
38776
|
-
}
|
|
38777
|
-
const result = await response.json();
|
|
38778
|
-
if (!result.success) {
|
|
39738
|
+
const result = await this.callbacks.upload(file, filename);
|
|
39739
|
+
if (!result.url || result.url.trim() === "") {
|
|
38779
39740
|
throw new StorageError(
|
|
38780
|
-
|
|
38781
|
-
"
|
|
38782
|
-
"
|
|
39741
|
+
"Upload callback returned invalid result: missing or empty url",
|
|
39742
|
+
"INVALID_UPLOAD_RESULT",
|
|
39743
|
+
"callback-storage"
|
|
38783
39744
|
);
|
|
38784
39745
|
}
|
|
38785
|
-
|
|
38786
|
-
throw new StorageError(
|
|
38787
|
-
"Server upload succeeded but no identifier returned",
|
|
38788
|
-
"NO_IDENTIFIER_RETURNED",
|
|
38789
|
-
"server-proxy"
|
|
38790
|
-
);
|
|
38791
|
-
}
|
|
38792
|
-
return {
|
|
38793
|
-
url: result.url || result.identifier,
|
|
38794
|
-
size: file.size,
|
|
38795
|
-
contentType: file.type || "application/octet-stream"
|
|
38796
|
-
};
|
|
39746
|
+
return result;
|
|
38797
39747
|
} catch (error) {
|
|
38798
39748
|
if (error instanceof StorageError) {
|
|
38799
39749
|
throw error;
|
|
38800
39750
|
}
|
|
38801
39751
|
throw new StorageError(
|
|
38802
|
-
`
|
|
39752
|
+
`Upload failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
38803
39753
|
"UPLOAD_ERROR",
|
|
38804
|
-
"
|
|
39754
|
+
"callback-storage",
|
|
39755
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
38805
39756
|
);
|
|
38806
39757
|
}
|
|
38807
39758
|
}
|
|
38808
39759
|
/**
|
|
38809
|
-
*
|
|
38810
|
-
*
|
|
38811
|
-
* @remarks
|
|
38812
|
-
* This method sends the identifier to your configured download endpoint via POST request.
|
|
38813
|
-
* Your server is responsible for retrieving the file from your storage backend
|
|
38814
|
-
* and returning the file content as a blob response.
|
|
38815
|
-
*
|
|
38816
|
-
* @param url - The server-provided URL or identifier from upload
|
|
38817
|
-
* @returns Promise that resolves to the downloaded file content
|
|
38818
|
-
* @throws {StorageError} When the download fails or file is not found
|
|
39760
|
+
* Download a file using the provided callback
|
|
38819
39761
|
*
|
|
38820
|
-
* @
|
|
38821
|
-
*
|
|
38822
|
-
* const fileBlob = await serverStorage.download("file-123");
|
|
38823
|
-
* const url = URL.createObjectURL(fileBlob);
|
|
38824
|
-
* ```
|
|
39762
|
+
* @param url - The URL or identifier to download
|
|
39763
|
+
* @returns The downloaded blob
|
|
38825
39764
|
*/
|
|
38826
39765
|
async download(url) {
|
|
38827
39766
|
try {
|
|
38828
|
-
const identifier = this.
|
|
38829
|
-
const
|
|
38830
|
-
|
|
38831
|
-
headers: {
|
|
38832
|
-
"Content-Type": "application/json"
|
|
38833
|
-
},
|
|
38834
|
-
body: JSON.stringify({ identifier })
|
|
38835
|
-
});
|
|
38836
|
-
if (!response.ok) {
|
|
38837
|
-
const _errorText = await response.text();
|
|
39767
|
+
const identifier = this.callbacks.extractIdentifier ? this.callbacks.extractIdentifier(url) : url;
|
|
39768
|
+
const blob = await this.callbacks.download(identifier);
|
|
39769
|
+
if (!(blob instanceof Blob)) {
|
|
38838
39770
|
throw new StorageError(
|
|
38839
|
-
|
|
38840
|
-
"
|
|
38841
|
-
"
|
|
39771
|
+
"Download callback returned invalid result: expected Blob",
|
|
39772
|
+
"INVALID_DOWNLOAD_RESULT",
|
|
39773
|
+
"callback-storage"
|
|
38842
39774
|
);
|
|
38843
39775
|
}
|
|
38844
|
-
return
|
|
39776
|
+
return blob;
|
|
38845
39777
|
} catch (error) {
|
|
38846
39778
|
if (error instanceof StorageError) {
|
|
38847
39779
|
throw error;
|
|
38848
39780
|
}
|
|
38849
39781
|
throw new StorageError(
|
|
38850
|
-
`
|
|
39782
|
+
`Download failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
38851
39783
|
"DOWNLOAD_ERROR",
|
|
38852
|
-
"
|
|
39784
|
+
"callback-storage",
|
|
39785
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
38853
39786
|
);
|
|
38854
39787
|
}
|
|
38855
39788
|
}
|
|
38856
|
-
|
|
38857
|
-
|
|
38858
|
-
|
|
38859
|
-
|
|
38860
|
-
|
|
38861
|
-
|
|
38862
|
-
|
|
38863
|
-
|
|
38864
|
-
|
|
38865
|
-
|
|
38866
|
-
|
|
38867
|
-
|
|
38868
|
-
|
|
39789
|
+
/**
|
|
39790
|
+
* List files using the provided callback (if available)
|
|
39791
|
+
*
|
|
39792
|
+
* @param options - Optional list options including filters and pagination
|
|
39793
|
+
* @returns Array of storage files
|
|
39794
|
+
*/
|
|
39795
|
+
async list(options) {
|
|
39796
|
+
if (!this.callbacks.list) {
|
|
39797
|
+
throw new StorageError(
|
|
39798
|
+
"List operation not supported - no list callback provided",
|
|
39799
|
+
"NOT_SUPPORTED",
|
|
39800
|
+
"callback-storage"
|
|
39801
|
+
);
|
|
39802
|
+
}
|
|
39803
|
+
try {
|
|
39804
|
+
const result = await this.callbacks.list(options?.namePattern, options);
|
|
39805
|
+
return result.items.map((item, index) => ({
|
|
39806
|
+
id: item.identifier,
|
|
39807
|
+
name: item.identifier.split("/").pop() || `file-${index}`,
|
|
39808
|
+
url: item.identifier,
|
|
39809
|
+
size: item.size || 0,
|
|
39810
|
+
contentType: "application/octet-stream",
|
|
39811
|
+
createdAt: item.lastModified || /* @__PURE__ */ new Date(),
|
|
39812
|
+
metadata: item.metadata
|
|
39813
|
+
}));
|
|
39814
|
+
} catch (error) {
|
|
39815
|
+
throw new StorageError(
|
|
39816
|
+
`List failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39817
|
+
"LIST_ERROR",
|
|
39818
|
+
"callback-storage",
|
|
39819
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
39820
|
+
);
|
|
39821
|
+
}
|
|
38869
39822
|
}
|
|
38870
39823
|
/**
|
|
38871
|
-
*
|
|
39824
|
+
* Delete a file using the provided callback (if available)
|
|
38872
39825
|
*
|
|
38873
|
-
* @param url - URL or identifier
|
|
38874
|
-
* @returns
|
|
39826
|
+
* @param url - The URL or identifier to delete
|
|
39827
|
+
* @returns True if deletion succeeded
|
|
38875
39828
|
*/
|
|
38876
|
-
|
|
38877
|
-
|
|
39829
|
+
async delete(url) {
|
|
39830
|
+
if (!this.callbacks.delete) {
|
|
39831
|
+
throw new StorageError(
|
|
39832
|
+
"Delete operation not supported - no delete callback provided",
|
|
39833
|
+
"NOT_SUPPORTED",
|
|
39834
|
+
"callback-storage"
|
|
39835
|
+
);
|
|
39836
|
+
}
|
|
39837
|
+
try {
|
|
39838
|
+
const identifier = this.callbacks.extractIdentifier ? this.callbacks.extractIdentifier(url) : url;
|
|
39839
|
+
return await this.callbacks.delete(identifier);
|
|
39840
|
+
} catch (error) {
|
|
39841
|
+
throw new StorageError(
|
|
39842
|
+
`Delete failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39843
|
+
"DELETE_ERROR",
|
|
39844
|
+
"callback-storage",
|
|
39845
|
+
{ cause: error instanceof Error ? error : void 0 }
|
|
39846
|
+
);
|
|
39847
|
+
}
|
|
38878
39848
|
}
|
|
39849
|
+
/**
|
|
39850
|
+
* Get provider configuration
|
|
39851
|
+
*
|
|
39852
|
+
* @returns Provider configuration metadata
|
|
39853
|
+
*/
|
|
38879
39854
|
getConfig() {
|
|
38880
39855
|
return {
|
|
38881
|
-
name: "
|
|
38882
|
-
type: "
|
|
39856
|
+
name: "callback-storage",
|
|
39857
|
+
type: "callback",
|
|
38883
39858
|
requiresAuth: false,
|
|
38884
39859
|
features: {
|
|
38885
39860
|
upload: true,
|
|
38886
39861
|
download: true,
|
|
38887
|
-
list:
|
|
38888
|
-
delete:
|
|
39862
|
+
list: !!this.callbacks.list,
|
|
39863
|
+
delete: !!this.callbacks.delete
|
|
38889
39864
|
}
|
|
38890
39865
|
};
|
|
38891
39866
|
}
|
|
@@ -39099,7 +40074,7 @@ var moksha = {
|
|
|
39099
40074
|
url: "https://moksha.vanascan.io"
|
|
39100
40075
|
}
|
|
39101
40076
|
},
|
|
39102
|
-
subgraphUrl: "https://api.goldsky.com/api/public/project_cm168cz887zva010j39il7a6p/subgraphs/moksha/7.0.
|
|
40077
|
+
subgraphUrl: "https://api.goldsky.com/api/public/project_cm168cz887zva010j39il7a6p/subgraphs/moksha/7.0.3/gn"
|
|
39103
40078
|
};
|
|
39104
40079
|
function getChainConfig(chainId) {
|
|
39105
40080
|
switch (chainId) {
|
|
@@ -39111,11 +40086,53 @@ function getChainConfig(chainId) {
|
|
|
39111
40086
|
return void 0;
|
|
39112
40087
|
}
|
|
39113
40088
|
}
|
|
40089
|
+
var mokshaTestnet2 = moksha;
|
|
39114
40090
|
function getAllChains() {
|
|
39115
40091
|
return [vanaMainnet2, moksha];
|
|
39116
40092
|
}
|
|
39117
40093
|
|
|
39118
40094
|
// src/core.ts
|
|
40095
|
+
var VanaCoreFactory = class {
|
|
40096
|
+
/**
|
|
40097
|
+
* Creates a VanaCore instance that enforces storage requirements at compile time.
|
|
40098
|
+
* Use this factory when you know you'll need storage-dependent operations.
|
|
40099
|
+
*
|
|
40100
|
+
* @param platform - The platform adapter for environment-specific operations
|
|
40101
|
+
* @param config - Configuration that includes required storage providers
|
|
40102
|
+
* @returns VanaCore instance with storage validation
|
|
40103
|
+
* @example
|
|
40104
|
+
* ```typescript
|
|
40105
|
+
* const vanaCore = VanaCoreFactory.createWithStorage(platformAdapter, {
|
|
40106
|
+
* walletClient: myWalletClient,
|
|
40107
|
+
* storage: {
|
|
40108
|
+
* providers: { ipfs: new IPFSStorage() },
|
|
40109
|
+
* defaultProvider: 'ipfs'
|
|
40110
|
+
* }
|
|
40111
|
+
* });
|
|
40112
|
+
* ```
|
|
40113
|
+
*/
|
|
40114
|
+
static createWithStorage(platform, config) {
|
|
40115
|
+
const core = new VanaCore(platform, config);
|
|
40116
|
+
return core;
|
|
40117
|
+
}
|
|
40118
|
+
/**
|
|
40119
|
+
* Creates a VanaCore instance without storage requirements.
|
|
40120
|
+
* Storage-dependent operations will fail at runtime if not configured.
|
|
40121
|
+
*
|
|
40122
|
+
* @param platform - The platform adapter for environment-specific operations
|
|
40123
|
+
* @param config - Basic configuration without required storage
|
|
40124
|
+
* @returns VanaCore instance
|
|
40125
|
+
* @example
|
|
40126
|
+
* ```typescript
|
|
40127
|
+
* const vanaCore = VanaCoreFactory.create(platformAdapter, {
|
|
40128
|
+
* walletClient: myWalletClient
|
|
40129
|
+
* });
|
|
40130
|
+
* ```
|
|
40131
|
+
*/
|
|
40132
|
+
static create(platform, config) {
|
|
40133
|
+
return new VanaCore(platform, config);
|
|
40134
|
+
}
|
|
40135
|
+
};
|
|
39119
40136
|
var VanaCore = class {
|
|
39120
40137
|
/**
|
|
39121
40138
|
* Initializes a new VanaCore client instance with the provided configuration.
|
|
@@ -39123,6 +40140,10 @@ var VanaCore = class {
|
|
|
39123
40140
|
* @remarks
|
|
39124
40141
|
* The constructor validates the configuration, initializes storage providers if configured,
|
|
39125
40142
|
* creates wallet and public clients, and sets up all SDK controllers with shared context.
|
|
40143
|
+
*
|
|
40144
|
+
* IMPORTANT: This constructor will validate storage requirements at runtime to fail fast.
|
|
40145
|
+
* Methods that require storage will throw runtime errors if storage is not configured.
|
|
40146
|
+
*
|
|
39126
40147
|
* @param platform - The platform adapter for environment-specific operations
|
|
39127
40148
|
* @param config - The configuration object specifying wallet or chain settings
|
|
39128
40149
|
* @throws {InvalidConfigurationError} When the configuration is invalid or incomplete
|
|
@@ -39137,8 +40158,10 @@ var VanaCore = class {
|
|
|
39137
40158
|
constructor(platform, config) {
|
|
39138
40159
|
/** Manages gasless data access permissions and trusted server registry. */
|
|
39139
40160
|
__publicField(this, "permissions");
|
|
39140
|
-
/** Handles user data file operations
|
|
40161
|
+
/** Handles user data file operations. */
|
|
39141
40162
|
__publicField(this, "data");
|
|
40163
|
+
/** Manages data schemas and refiners. */
|
|
40164
|
+
__publicField(this, "schemas");
|
|
39142
40165
|
/** Provides personal server setup and trusted server interactions. */
|
|
39143
40166
|
__publicField(this, "server");
|
|
39144
40167
|
/** Offers low-level access to Vana protocol smart contracts. */
|
|
@@ -39147,9 +40170,13 @@ var VanaCore = class {
|
|
|
39147
40170
|
__publicField(this, "platform");
|
|
39148
40171
|
__publicField(this, "relayerCallbacks");
|
|
39149
40172
|
__publicField(this, "storageManager");
|
|
40173
|
+
__publicField(this, "hasRequiredStorage");
|
|
40174
|
+
__publicField(this, "ipfsGateways");
|
|
39150
40175
|
this.platform = platform;
|
|
39151
40176
|
this.validateConfig(config);
|
|
39152
40177
|
this.relayerCallbacks = config.relayerCallbacks;
|
|
40178
|
+
this.ipfsGateways = config.ipfsGateways;
|
|
40179
|
+
this.hasRequiredStorage = hasStorageConfig(config);
|
|
39153
40180
|
if (config.storage?.providers) {
|
|
39154
40181
|
this.storageManager = new StorageManager();
|
|
39155
40182
|
for (const [name, provider] of Object.entries(config.storage.providers)) {
|
|
@@ -39204,14 +40231,70 @@ var VanaCore = class {
|
|
|
39204
40231
|
relayerCallbacks: this.relayerCallbacks,
|
|
39205
40232
|
storageManager: this.storageManager,
|
|
39206
40233
|
subgraphUrl,
|
|
39207
|
-
platform: this.platform
|
|
40234
|
+
platform: this.platform,
|
|
39208
40235
|
// Pass the platform adapter to controllers
|
|
40236
|
+
validateStorageRequired: this.validateStorageRequired.bind(this),
|
|
40237
|
+
hasStorage: this.hasStorage.bind(this),
|
|
40238
|
+
ipfsGateways: this.ipfsGateways
|
|
39209
40239
|
};
|
|
39210
40240
|
this.permissions = new PermissionsController(sharedContext);
|
|
39211
40241
|
this.data = new DataController(sharedContext);
|
|
40242
|
+
this.schemas = new SchemaController(sharedContext);
|
|
39212
40243
|
this.server = new ServerController(sharedContext);
|
|
39213
40244
|
this.protocol = new ProtocolController(sharedContext);
|
|
39214
40245
|
}
|
|
40246
|
+
/**
|
|
40247
|
+
* Validates that storage is available for storage-dependent operations.
|
|
40248
|
+
* This method enforces the fail-fast principle by checking storage availability
|
|
40249
|
+
* at method call time rather than during expensive operations.
|
|
40250
|
+
*
|
|
40251
|
+
* @throws {InvalidConfigurationError} When storage is required but not configured
|
|
40252
|
+
* @example
|
|
40253
|
+
* ```typescript
|
|
40254
|
+
* // This will throw if storage is not configured
|
|
40255
|
+
* vana.validateStorageRequired();
|
|
40256
|
+
* await vana.data.uploadFile(file); // Safe to proceed
|
|
40257
|
+
* ```
|
|
40258
|
+
*/
|
|
40259
|
+
validateStorageRequired() {
|
|
40260
|
+
if (!this.hasRequiredStorage) {
|
|
40261
|
+
throw new InvalidConfigurationError(
|
|
40262
|
+
"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."
|
|
40263
|
+
);
|
|
40264
|
+
}
|
|
40265
|
+
}
|
|
40266
|
+
/**
|
|
40267
|
+
* Checks whether storage is configured without throwing an error.
|
|
40268
|
+
*
|
|
40269
|
+
* @returns True if storage is properly configured
|
|
40270
|
+
* @example
|
|
40271
|
+
* ```typescript
|
|
40272
|
+
* if (vana.hasStorage()) {
|
|
40273
|
+
* await vana.data.uploadFile(file);
|
|
40274
|
+
* } else {
|
|
40275
|
+
* console.warn('Storage not configured - using pre-stored URLs only');
|
|
40276
|
+
* }
|
|
40277
|
+
* ```
|
|
40278
|
+
*/
|
|
40279
|
+
hasStorage() {
|
|
40280
|
+
return this.hasRequiredStorage;
|
|
40281
|
+
}
|
|
40282
|
+
/**
|
|
40283
|
+
* Type guard to check if this instance has storage enabled at compile time.
|
|
40284
|
+
* Use this when you need TypeScript to understand that storage is available.
|
|
40285
|
+
*
|
|
40286
|
+
* @returns True if storage is configured, with type narrowing
|
|
40287
|
+
* @example
|
|
40288
|
+
* ```typescript
|
|
40289
|
+
* if (vana.isStorageEnabled()) {
|
|
40290
|
+
* // TypeScript knows storage is available here
|
|
40291
|
+
* await vana.data.uploadFile(file);
|
|
40292
|
+
* }
|
|
40293
|
+
* ```
|
|
40294
|
+
*/
|
|
40295
|
+
isStorageEnabled() {
|
|
40296
|
+
return this.hasRequiredStorage;
|
|
40297
|
+
}
|
|
39215
40298
|
/**
|
|
39216
40299
|
* Validates the provided configuration object against all requirements.
|
|
39217
40300
|
*
|
|
@@ -39400,37 +40483,97 @@ var VanaCore = class {
|
|
|
39400
40483
|
return this.platform;
|
|
39401
40484
|
}
|
|
39402
40485
|
/**
|
|
39403
|
-
* Encrypts
|
|
39404
|
-
*
|
|
40486
|
+
* Encrypts data using the Vana protocol standard encryption.
|
|
40487
|
+
*
|
|
40488
|
+
* @remarks
|
|
40489
|
+
* This method implements the Vana network's standard encryption protocol using
|
|
40490
|
+
* platform-appropriate cryptographic libraries. It automatically handles different
|
|
40491
|
+
* input types (string or Blob) and produces encrypted output suitable for secure
|
|
40492
|
+
* storage or transmission. The encryption is compatible with the network's
|
|
40493
|
+
* decryption protocols and can be decrypted by authorized parties.
|
|
39405
40494
|
*
|
|
39406
|
-
* @param data The data to encrypt (string or Blob)
|
|
39407
|
-
* @param
|
|
39408
|
-
* @returns The encrypted data as Blob
|
|
40495
|
+
* @param data - The data to encrypt (string or Blob)
|
|
40496
|
+
* @param key - The encryption key (typically generated via `generateEncryptionKey`)
|
|
40497
|
+
* @returns The encrypted data as a Blob
|
|
40498
|
+
* @throws {Error} When encryption fails due to invalid key or data format
|
|
39409
40499
|
* @example
|
|
39410
40500
|
* ```typescript
|
|
39411
|
-
*
|
|
39412
|
-
*
|
|
40501
|
+
* import { generateEncryptionKey } from '@opendatalabs/vana-sdk/node';
|
|
40502
|
+
*
|
|
40503
|
+
* // Generate encryption key from wallet signature
|
|
40504
|
+
* const encryptionKey = await generateEncryptionKey(vana.walletClient);
|
|
40505
|
+
*
|
|
40506
|
+
* // Encrypt string data
|
|
40507
|
+
* const sensitiveData = "User's private information";
|
|
40508
|
+
* const encrypted = await vana.encryptBlob(sensitiveData, encryptionKey);
|
|
40509
|
+
*
|
|
40510
|
+
* // Encrypt file data
|
|
40511
|
+
* const fileBlob = new Blob([fileContent], { type: 'application/json' });
|
|
40512
|
+
* const encryptedFile = await vana.encryptBlob(fileBlob, encryptionKey);
|
|
40513
|
+
*
|
|
40514
|
+
* // Store encrypted data safely
|
|
40515
|
+
* await storageProvider.upload(encrypted, 'encrypted-data.bin');
|
|
39413
40516
|
* ```
|
|
39414
40517
|
*/
|
|
39415
|
-
async
|
|
39416
|
-
return
|
|
40518
|
+
async encryptBlob(data, key) {
|
|
40519
|
+
return encryptBlobWithSignedKey(data, key, this.platform);
|
|
39417
40520
|
}
|
|
39418
40521
|
/**
|
|
39419
|
-
* Decrypts
|
|
39420
|
-
*
|
|
40522
|
+
* Decrypts data that was encrypted using the Vana protocol.
|
|
40523
|
+
*
|
|
40524
|
+
* @remarks
|
|
40525
|
+
* This method decrypts data that was previously encrypted using the Vana network's
|
|
40526
|
+
* standard encryption protocol. It requires the same wallet signature that was used
|
|
40527
|
+
* for encryption and automatically uses the appropriate platform adapter for
|
|
40528
|
+
* cryptographic operations. The decrypted output maintains the original data format.
|
|
39421
40529
|
*
|
|
39422
|
-
* @param encryptedData The encrypted data (string or Blob)
|
|
39423
|
-
* @param walletSignature The wallet signature
|
|
39424
|
-
* @returns The decrypted data as Blob
|
|
40530
|
+
* @param encryptedData - The encrypted data (string or Blob)
|
|
40531
|
+
* @param walletSignature - The wallet signature used as decryption key
|
|
40532
|
+
* @returns The decrypted data as a Blob
|
|
40533
|
+
* @throws {Error} When decryption fails due to invalid signature or corrupted data
|
|
39425
40534
|
* @example
|
|
39426
40535
|
* ```typescript
|
|
39427
|
-
*
|
|
39428
|
-
*
|
|
39429
|
-
*
|
|
40536
|
+
* import { generateEncryptionKey } from '@opendatalabs/vana-sdk/node';
|
|
40537
|
+
*
|
|
40538
|
+
* // Retrieve encrypted data from storage
|
|
40539
|
+
* const encryptedBlob = await storageProvider.download('encrypted-data.bin');
|
|
40540
|
+
*
|
|
40541
|
+
* // Generate the same key used for encryption
|
|
40542
|
+
* const decryptionKey = await generateEncryptionKey(vana.walletClient);
|
|
40543
|
+
*
|
|
40544
|
+
* // Decrypt the data
|
|
40545
|
+
* const decrypted = await vana.decryptBlob(encryptedBlob, decryptionKey);
|
|
40546
|
+
*
|
|
40547
|
+
* // Convert back to original format
|
|
40548
|
+
* const originalText = await decrypted.text();
|
|
40549
|
+
* const originalJson = JSON.parse(originalText);
|
|
40550
|
+
*
|
|
40551
|
+
* console.log('Decrypted data:', originalJson);
|
|
40552
|
+
* ```
|
|
40553
|
+
*
|
|
40554
|
+
* @example
|
|
40555
|
+
* ```typescript
|
|
40556
|
+
* // Decrypt file downloaded from Vana network
|
|
40557
|
+
* const userFiles = await vana.data.getUserFiles();
|
|
40558
|
+
* const file = userFiles[0];
|
|
40559
|
+
*
|
|
40560
|
+
* // Download encrypted content
|
|
40561
|
+
* const encrypted = await fetch(file.url).then(r => r.blob());
|
|
40562
|
+
*
|
|
40563
|
+
* // Decrypt with user's key
|
|
40564
|
+
* const decryptionKey = await generateEncryptionKey(vana.walletClient);
|
|
40565
|
+
* const decrypted = await vana.decryptBlob(encrypted, decryptionKey);
|
|
40566
|
+
*
|
|
40567
|
+
* // Process original data
|
|
40568
|
+
* const fileContent = await decrypted.arrayBuffer();
|
|
39430
40569
|
* ```
|
|
39431
40570
|
*/
|
|
39432
|
-
async
|
|
39433
|
-
return
|
|
40571
|
+
async decryptBlob(encryptedData, walletSignature) {
|
|
40572
|
+
return decryptBlobWithSignedKey(
|
|
40573
|
+
encryptedData,
|
|
40574
|
+
walletSignature,
|
|
40575
|
+
this.platform
|
|
40576
|
+
);
|
|
39434
40577
|
}
|
|
39435
40578
|
};
|
|
39436
40579
|
|
|
@@ -39461,7 +40604,7 @@ function createValidatedGrant(params) {
|
|
|
39461
40604
|
try {
|
|
39462
40605
|
validateGrant(grantFile, {
|
|
39463
40606
|
schema: true,
|
|
39464
|
-
grantee: params.
|
|
40607
|
+
grantee: params.grantee,
|
|
39465
40608
|
operation: params.operation
|
|
39466
40609
|
});
|
|
39467
40610
|
} catch (error) {
|
|
@@ -40218,31 +41361,22 @@ var ApiClient = class {
|
|
|
40218
41361
|
};
|
|
40219
41362
|
|
|
40220
41363
|
// src/index.browser.ts
|
|
40221
|
-
var
|
|
40222
|
-
/**
|
|
40223
|
-
* Creates a Vana SDK instance configured for browser environments.
|
|
40224
|
-
*
|
|
40225
|
-
* @param config - SDK configuration object (wallet client or chain config)
|
|
40226
|
-
* @example
|
|
40227
|
-
* ```typescript
|
|
40228
|
-
* // With wallet client
|
|
40229
|
-
* const vana = new Vana({ walletClient });
|
|
40230
|
-
*
|
|
40231
|
-
* // With chain configuration
|
|
40232
|
-
* const vana = new Vana({ chainId: 14800, account });
|
|
40233
|
-
* ```
|
|
40234
|
-
*/
|
|
41364
|
+
var VanaBrowserImpl = class extends VanaCore {
|
|
40235
41365
|
constructor(config) {
|
|
40236
41366
|
super(new BrowserPlatformAdapter(), config);
|
|
40237
41367
|
}
|
|
40238
41368
|
};
|
|
40239
|
-
|
|
41369
|
+
function Vana(config) {
|
|
41370
|
+
return new VanaBrowserImpl(config);
|
|
41371
|
+
}
|
|
41372
|
+
var index_browser_default = Vana;
|
|
40240
41373
|
export {
|
|
40241
41374
|
ApiClient,
|
|
40242
41375
|
AsyncQueue,
|
|
40243
41376
|
BaseController,
|
|
40244
41377
|
BlockchainError,
|
|
40245
41378
|
BrowserPlatformAdapter,
|
|
41379
|
+
CallbackStorage,
|
|
40246
41380
|
CircuitBreaker,
|
|
40247
41381
|
ContractFactory,
|
|
40248
41382
|
ContractNotFoundError,
|
|
@@ -40275,14 +41409,16 @@ export {
|
|
|
40275
41409
|
SchemaValidator,
|
|
40276
41410
|
SerializationError,
|
|
40277
41411
|
ServerController,
|
|
40278
|
-
ServerProxyStorage,
|
|
40279
41412
|
ServerUrlMismatchError,
|
|
41413
|
+
SignatureCache,
|
|
40280
41414
|
SignatureError,
|
|
40281
41415
|
StorageError,
|
|
40282
41416
|
StorageManager,
|
|
40283
41417
|
UserRejectedRequestError,
|
|
40284
|
-
|
|
40285
|
-
|
|
41418
|
+
Vana,
|
|
41419
|
+
VanaBrowserImpl,
|
|
41420
|
+
VanaCore,
|
|
41421
|
+
VanaCoreFactory,
|
|
40286
41422
|
VanaError,
|
|
40287
41423
|
__contractCache,
|
|
40288
41424
|
chains,
|
|
@@ -40295,13 +41431,13 @@ export {
|
|
|
40295
41431
|
createGrantFile,
|
|
40296
41432
|
createPlatformAdapterSafe,
|
|
40297
41433
|
createValidatedGrant,
|
|
40298
|
-
|
|
41434
|
+
decryptBlobWithSignedKey,
|
|
40299
41435
|
decryptWithPrivateKey,
|
|
40300
41436
|
decryptWithWalletPrivateKey,
|
|
40301
41437
|
index_browser_default as default,
|
|
40302
41438
|
detectPlatform,
|
|
41439
|
+
encryptBlobWithSignedKey,
|
|
40303
41440
|
encryptFileKey,
|
|
40304
|
-
encryptUserData,
|
|
40305
41441
|
encryptWithWalletPublicKey,
|
|
40306
41442
|
extractIpfsHash,
|
|
40307
41443
|
fetchAndValidateSchema,
|
|
@@ -40325,13 +41461,11 @@ export {
|
|
|
40325
41461
|
getPlatformCapabilities,
|
|
40326
41462
|
isAPIResponse,
|
|
40327
41463
|
isGrantExpired,
|
|
40328
|
-
isIdentityServerOutput,
|
|
40329
41464
|
isIpfsUrl,
|
|
40330
|
-
isPersonalServerOutput,
|
|
40331
41465
|
isPlatformSupported,
|
|
40332
41466
|
isReplicateAPIResponse,
|
|
40333
41467
|
moksha,
|
|
40334
|
-
mokshaTestnet,
|
|
41468
|
+
mokshaTestnet2 as mokshaTestnet,
|
|
40335
41469
|
parseReplicateOutput,
|
|
40336
41470
|
retrieveAndValidateGrant,
|
|
40337
41471
|
retrieveGrantFile,
|
|
@@ -40347,6 +41481,7 @@ export {
|
|
|
40347
41481
|
validateGrantFile,
|
|
40348
41482
|
validateGranteeAccess,
|
|
40349
41483
|
validateOperationAccess,
|
|
40350
|
-
vanaMainnet
|
|
41484
|
+
vanaMainnet2 as vanaMainnet,
|
|
41485
|
+
withSignatureCache
|
|
40351
41486
|
};
|
|
40352
41487
|
//# sourceMappingURL=index.browser.js.map
|