@opendatalabs/vana-sdk 0.1.0-alpha.5869423

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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2025, Vana
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,600 @@
1
+ # Vana SDK
2
+
3
+ The Vana SDK is a comprehensive TypeScript library for building applications on the Vana Network. It provides simple, powerful APIs for gasless data permissions, file management, and secure data portability.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/vana-sdk)](https://www.npmjs.com/package/vana-sdk)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)](https://www.typescriptlang.org/)
7
+ [![License: ISC](https://img.shields.io/badge/License-ISC-green.svg)](https://opensource.org/licenses/ISC)
8
+
9
+ [Documentation](https://vana-com.github.io/vana-sdk) • [Examples](#examples) • [API Reference](https://vana-com.github.io/vana-sdk)
10
+
11
+ ## Why Vana SDK?
12
+
13
+ - **🔐 Gasless Permissions**: EIP-712 based permission system with zero gas fees for users
14
+ - **📁 Data Management**: Query, upload, and manage encrypted user data files
15
+ - **🔄 Flexible Relaying**: Callback-based relay system supporting any gasless transaction infrastructure
16
+ - **📊 Schema Validation**: Built-in JSON Schema and SQLite schema validation with AJV
17
+ - **🔧 Type-Safe**: Full TypeScript support with comprehensive type definitions
18
+ - **🎯 Production Ready**: Battle-tested with comprehensive error handling and retry mechanisms
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ # npm
24
+ npm install vana-sdk
25
+
26
+ # yarn
27
+ yarn add vana-sdk
28
+
29
+ # pnpm
30
+ pnpm add vana-sdk
31
+ ```
32
+
33
+ **Peer Dependencies:**
34
+
35
+ ```bash
36
+ npm install viem@^2.31.7
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ### Basic Setup
42
+
43
+ ```typescript
44
+ import { Vana } from "vana-sdk";
45
+ import { createWalletClient, http } from "viem";
46
+ import { privateKeyToAccount } from "viem/accounts";
47
+ import { mokshaTestnet } from "vana-sdk";
48
+
49
+ // Create wallet client
50
+ const account = privateKeyToAccount("0x...");
51
+ const walletClient = createWalletClient({
52
+ account,
53
+ chain: mokshaTestnet,
54
+ transport: http("https://rpc.moksha.vana.org"),
55
+ });
56
+
57
+ // Initialize Vana SDK
58
+ const vana = new Vana({
59
+ walletClient,
60
+ // Optional: configure gasless relayer
61
+ relayerUrl: "https://relayer.moksha.vana.org",
62
+ });
63
+ ```
64
+
65
+ ### Grant Data Permission (Gasless)
66
+
67
+ ```typescript
68
+ // Grant permission for an AI application to access user data
69
+ const txHash = await vana.permissions.grant({
70
+ to: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36", // Application address
71
+ operation: "llm_inference",
72
+ parameters: {
73
+ prompt: "Analyze my browsing data for insights",
74
+ maxTokens: 1000,
75
+ files: [12, 15, 28], // Specific file IDs
76
+ model: "gpt-4",
77
+ },
78
+ expiresAt: Math.floor(Date.now() / 1000) + 24 * 60 * 60, // 24 hours
79
+ });
80
+
81
+ console.log("Permission granted:", txHash);
82
+ ```
83
+
84
+ ### Query User Data Files
85
+
86
+ ```typescript
87
+ // Get all files owned by a user
88
+ const files = await vana.data.getUserFiles({
89
+ user: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
90
+ });
91
+
92
+ files.forEach((file) => {
93
+ console.log(`File ${file.id}: ${file.url}`);
94
+ console.log(`Schema: ${file.schemaId}, Added: ${file.addedAtBlock}`);
95
+ });
96
+ ```
97
+
98
+ ### Upload Encrypted File
99
+
100
+ ```typescript
101
+ // Generate encryption key from wallet
102
+ const encryptionKey = await generateEncryptionKey(walletClient);
103
+
104
+ // Encrypt user data
105
+ const userData = new Blob([
106
+ JSON.stringify({
107
+ browsing_history: [{ url: "https://example.com", timestamp: Date.now() }],
108
+ }),
109
+ ]);
110
+
111
+ const encryptedData = await encryptUserData(userData, encryptionKey);
112
+
113
+ // Upload to IPFS and register on-chain
114
+ const result = await vana.data.uploadEncryptedFile({
115
+ data: encryptedData,
116
+ schemaId: 123, // JSON schema for browsing data
117
+ filename: "browsing-data.json",
118
+ });
119
+
120
+ console.log("File uploaded:", result.fileId, result.url);
121
+ ```
122
+
123
+ ## Architecture
124
+
125
+ The Vana SDK follows a resource-oriented architecture with five main controllers:
126
+
127
+ ### Core Controllers
128
+
129
+ | Controller | Purpose | Key Methods |
130
+ | ---------------------- | --------------------------------------- | ----------------------------------------------------------------- |
131
+ | **`vana.permissions`** | Gasless permission grants & revocations | `grant()`, `revoke()`, `getUserPermissions()` |
132
+ | **`vana.data`** | Data file management & encryption | `getUserFiles()`, `uploadEncryptedFile()`, `validateDataSchema()` |
133
+ | **`vana.server`** | Trusted server management | `trustServer()`, `untrustServer()`, `processWithTrustedServer()` |
134
+ | **`vana.protocol`** | Low-level contract access | `getContract()`, `getAvailableContracts()` |
135
+
136
+ ### Configuration Options
137
+
138
+ ```typescript
139
+ const vana = new Vana({
140
+ // Required: Wallet client for signing
141
+ walletClient,
142
+
143
+ // Optional: Gasless transaction relay
144
+ relayerUrl: "https://custom-relayer.com",
145
+
146
+ // Optional: Custom callback-based relaying
147
+ relayerCallbacks: {
148
+ submitPermissionGrant: async (typedData, signature) => {
149
+ // Custom relay implementation
150
+ return await customRelayer.submit(typedData, signature);
151
+ },
152
+ },
153
+
154
+ // Optional: Storage configuration
155
+ storageManager: new StorageManager({
156
+ defaultProvider: "ipfs",
157
+ providers: {
158
+ ipfs: new PinataStorage({ apiKey: "...", secretKey: "..." }),
159
+ },
160
+ }),
161
+
162
+ // Optional: Subgraph for efficient data queries
163
+ subgraphUrl: "https://api.thegraph.com/subgraphs/name/vana/moksha",
164
+ });
165
+ ```
166
+
167
+ ## Core Concepts
168
+
169
+ ### Gasless Permissions
170
+
171
+ The Vana SDK enables applications to request data access permissions without users paying gas fees:
172
+
173
+ ```typescript
174
+ // Complete gasless permission flow
175
+ const permission = await vana.permissions.grant({
176
+ to: applicationAddress,
177
+ operation: "data_analysis",
178
+ parameters: {
179
+ // Structured parameters for the operation
180
+ analysisType: "sentiment",
181
+ outputFormat: "json",
182
+ maxDataPoints: 1000,
183
+ },
184
+ });
185
+
186
+ // The SDK handles:
187
+ // 1. Parameter serialization & IPFS storage
188
+ // 2. EIP-712 typed data creation
189
+ // 3. User signature via wallet
190
+ // 4. Relayer submission & gas payment
191
+ // 5. On-chain permission registration
192
+ ```
193
+
194
+ ### Data File Management
195
+
196
+ Query and manage encrypted user data files using the subgraph for efficiency:
197
+
198
+ ```typescript
199
+ // Efficiently query user files (no contract scanning)
200
+ const files = await vana.data.getUserFiles({
201
+ user: userAddress,
202
+ // Optional: override subgraph URL
203
+ subgraphUrl: "https://custom-subgraph.com/graphql",
204
+ });
205
+
206
+ // Files are automatically deduplicated by ID
207
+ // Latest timestamp wins for duplicate file IDs
208
+ console.log(`Found ${files.length} unique files`);
209
+ ```
210
+
211
+ ### Schema Validation
212
+
213
+ Built-in support for validating data schemas and user data:
214
+
215
+ ```typescript
216
+ // Validate a data schema against Vana meta-schema
217
+ const schema = {
218
+ name: "Instagram Export",
219
+ version: "1.0.0",
220
+ dialect: "json",
221
+ schema: {
222
+ type: "object",
223
+ properties: {
224
+ posts: { type: "array" },
225
+ profile: { type: "object" },
226
+ },
227
+ },
228
+ };
229
+
230
+ vana.data.validateDataSchema(schema);
231
+
232
+ // Validate user data against the schema
233
+ const userData = { posts: [], profile: { username: "alice" } };
234
+ vana.data.validateDataAgainstSchema(userData, schema);
235
+ ```
236
+
237
+ ### Flexible Relay System
238
+
239
+ Configure gasless transactions using callbacks instead of fixed HTTP APIs:
240
+
241
+ ```typescript
242
+ const vana = new Vana({
243
+ walletClient,
244
+ relayerCallbacks: {
245
+ // Custom permission grant relaying
246
+ submitPermissionGrant: async (typedData, signature) => {
247
+ const response = await fetch("/api/relay/grant", {
248
+ method: "POST",
249
+ body: JSON.stringify({ typedData, signature }),
250
+ });
251
+ const result = await response.json();
252
+ return result.transactionHash;
253
+ },
254
+
255
+ // Custom revocation relaying
256
+ submitPermissionRevoke: async (typedData, signature) => {
257
+ return await myCustomRelayer.revoke(typedData, signature);
258
+ },
259
+ },
260
+ });
261
+ ```
262
+
263
+ ## API Reference
264
+
265
+ ### Permissions Controller
266
+
267
+ ```typescript
268
+ // Grant permission (gasless)
269
+ await vana.permissions.grant({
270
+ to: Address, // Application address
271
+ operation: string, // Operation type
272
+ parameters: object, // Operation parameters
273
+ expiresAt?: number // Optional expiration timestamp
274
+ }): Promise<Hash>
275
+
276
+ // Revoke permission (gasless)
277
+ await vana.permissions.revoke({
278
+ grantId: string, // Grant ID to revoke
279
+ nonce?: bigint // Optional nonce override
280
+ }): Promise<Hash>
281
+
282
+ // Query user permissions
283
+ await vana.permissions.getUserPermissions({
284
+ user: Address, // User address
285
+ subgraphUrl?: string // Optional subgraph override
286
+ }): Promise<GrantedPermission[]>
287
+
288
+ // Trust a server
289
+ await vana.permissions.trustServer({
290
+ serverAddress: Address, // Server's address
291
+ serverUrl: string // Server's URL
292
+ }): Promise<Hash>
293
+ ```
294
+
295
+ ### Data Controller
296
+
297
+ ```typescript
298
+ // Get user files
299
+ await vana.data.getUserFiles({
300
+ user: Address, // File owner address
301
+ subgraphUrl?: string // Optional subgraph override
302
+ }): Promise<UserFile[]>
303
+
304
+ // Upload encrypted file
305
+ await vana.data.uploadEncryptedFile({
306
+ data: Blob, // Encrypted file data
307
+ schemaId?: number, // Optional schema ID
308
+ filename?: string // Optional filename
309
+ }): Promise<UploadEncryptedFileResult>
310
+
311
+ // Validate data schema
312
+ vana.data.validateDataSchema(
313
+ schema: unknown // Schema to validate
314
+ ): asserts schema is DataSchema
315
+
316
+ // Validate data against schema
317
+ vana.data.validateDataAgainstSchema(
318
+ data: unknown, // Data to validate
319
+ schema: DataSchema // Data schema
320
+ ): void
321
+
322
+ // Fetch and validate remote schema
323
+ await vana.data.fetchAndValidateSchema(
324
+ url: string // Schema URL
325
+ ): Promise<DataSchema>
326
+ ```
327
+
328
+ ### Server Controller
329
+
330
+ ```typescript
331
+ // Process data with trusted server
332
+ await vana.server.processWithTrustedServer({
333
+ serverUrl: string, // Trusted server URL
334
+ operation: string, // Operation to perform
335
+ parameters: object // Operation parameters
336
+ }): Promise<any>
337
+
338
+ // Check server trust status
339
+ await vana.server.isServerTrusted({
340
+ user: Address, // User address
341
+ serverAddress: Address // Server address
342
+ }): Promise<boolean>
343
+ ```
344
+
345
+ ### Protocol Controller
346
+
347
+ ```typescript
348
+ // Get contract information
349
+ vana.protocol.getContract(
350
+ contractName: VanaContract // Contract name
351
+ ): ContractInfo
352
+
353
+ // List available contracts
354
+ vana.protocol.getAvailableContracts(): VanaContract[]
355
+
356
+ // Get contract addresses for chain
357
+ vana.protocol.getChainContracts(
358
+ chainId: number // Chain ID
359
+ ): Record<VanaContract, Address>
360
+ ```
361
+
362
+ ## Storage Integration
363
+
364
+ The SDK includes a powerful storage abstraction supporting multiple providers:
365
+
366
+ ### IPFS Storage
367
+
368
+ ```typescript
369
+ import { StorageManager, PinataStorage } from "vana-sdk";
370
+
371
+ const storageManager = new StorageManager();
372
+
373
+ // Configure Pinata IPFS
374
+ const pinataStorage = new PinataStorage({
375
+ apiKey: process.env.PINATA_API_KEY,
376
+ secretKey: process.env.PINATA_SECRET_KEY,
377
+ gatewayUrl: "https://gateway.pinata.cloud/ipfs",
378
+ });
379
+
380
+ storageManager.register("ipfs", pinataStorage, true); // Default provider
381
+
382
+ // Upload file
383
+ const result = await storageManager.upload(encryptedBlob, "encrypted-data.bin");
384
+ ```
385
+
386
+ ### Google Drive Storage
387
+
388
+ ```typescript
389
+ import { StorageManager, GoogleDriveStorage } from "vana-sdk";
390
+
391
+ const googleDriveStorage = new GoogleDriveStorage({
392
+ accessToken: process.env.GOOGLE_DRIVE_ACCESS_TOKEN,
393
+ refreshToken: process.env.GOOGLE_DRIVE_REFRESH_TOKEN,
394
+ clientId: process.env.GOOGLE_DRIVE_CLIENT_ID,
395
+ clientSecret: process.env.GOOGLE_DRIVE_CLIENT_SECRET,
396
+ });
397
+
398
+ storageManager.register("google-drive", googleDriveStorage);
399
+ ```
400
+
401
+ ### Custom Storage Provider
402
+
403
+ ```typescript
404
+ class CustomStorage implements StorageProvider {
405
+ async upload(file: Blob, filename?: string): Promise<StorageUploadResult> {
406
+ // Custom upload logic
407
+ return { url: "custom://uploaded-file", size: file.size };
408
+ }
409
+
410
+ async download(url: string): Promise<Blob> {
411
+ // Custom download logic
412
+ }
413
+
414
+ // ... other required methods
415
+ }
416
+
417
+ storageManager.register("custom", new CustomStorage());
418
+ ```
419
+
420
+ ## Error Handling
421
+
422
+ The SDK provides comprehensive error handling with specific error types:
423
+
424
+ ```typescript
425
+ import {
426
+ RelayerError,
427
+ UserRejectedRequestError,
428
+ SchemaValidationError,
429
+ InvalidConfigurationError,
430
+ NetworkError,
431
+ } from "vana-sdk";
432
+
433
+ try {
434
+ await vana.permissions.grant(params);
435
+ } catch (error) {
436
+ if (error instanceof UserRejectedRequestError) {
437
+ // User rejected the signature request
438
+ console.log("User cancelled transaction");
439
+ } else if (error instanceof RelayerError) {
440
+ // Relayer service error
441
+ console.log(`Relayer error (${error.statusCode}): ${error.message}`);
442
+ } else if (error instanceof SchemaValidationError) {
443
+ // Schema validation failed
444
+ console.log(`Schema error: ${error.message}`);
445
+ } else if (error instanceof NetworkError) {
446
+ // Network connectivity issue
447
+ console.log(`Network error: ${error.message}`);
448
+ } else {
449
+ // Unexpected error
450
+ console.error("Unexpected error:", error);
451
+ }
452
+ }
453
+ ```
454
+
455
+ ## Supported Networks
456
+
457
+ | Network | Chain ID | RPC URL | Explorer |
458
+ | ------------------ | -------- | ----------------------------- | ------------------------------------------------ |
459
+ | **Vana Mainnet** | `1480` | `https://rpc.vana.org` | [vanascan.io](https://vanascan.io) |
460
+ | **Moksha Testnet** | `14800` | `https://rpc.moksha.vana.org` | [moksha.vanascan.io](https://moksha.vanascan.io) |
461
+
462
+ ### Adding Networks to Wallet
463
+
464
+ **Moksha Testnet:**
465
+
466
+ ```
467
+ Network Name: Vana Moksha Testnet
468
+ RPC URL: https://rpc.moksha.vana.org
469
+ Chain ID: 14800
470
+ Currency Symbol: VANA
471
+ Block Explorer: https://moksha.vanascan.io
472
+ ```
473
+
474
+ ## Examples
475
+
476
+ ### Complete Permission Flow
477
+
478
+ ```typescript
479
+ import { Vana, generateEncryptionKey, encryptUserData } from "vana-sdk";
480
+
481
+ async function completePermissionFlow() {
482
+ // 1. Initialize SDK
483
+ const vana = new Vana({ walletClient });
484
+
485
+ // 2. Encrypt user data
486
+ const encryptionKey = await generateEncryptionKey(walletClient);
487
+ const userData = new Blob([JSON.stringify({ data: "sensitive info" })]);
488
+ const encryptedData = await encryptUserData(userData, encryptionKey);
489
+
490
+ // 3. Upload encrypted file
491
+ const uploadResult = await vana.data.uploadEncryptedFile({
492
+ data: encryptedData,
493
+ schemaId: 123,
494
+ filename: "user-data.json",
495
+ });
496
+
497
+ // 4. Grant permission to access the file
498
+ const permissionTx = await vana.permissions.grant({
499
+ to: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
500
+ operation: "ai_training",
501
+ parameters: {
502
+ files: [uploadResult.fileId],
503
+ model: "llm-v1",
504
+ maxTokens: 500,
505
+ },
506
+ });
507
+
508
+ console.log("Permission granted:", permissionTx);
509
+ }
510
+ ```
511
+
512
+ ### Schema Validation Example
513
+
514
+ ```typescript
515
+ // Define a data schema
516
+ const instagramSchema = {
517
+ name: "Instagram Export",
518
+ version: "1.0.0",
519
+ description: "User's Instagram profile and posts data",
520
+ dialect: "json",
521
+ schema: {
522
+ type: "object",
523
+ properties: {
524
+ profile: {
525
+ type: "object",
526
+ properties: {
527
+ username: { type: "string" },
528
+ followers: { type: "number" },
529
+ verified: { type: "boolean" },
530
+ },
531
+ required: ["username"],
532
+ },
533
+ posts: {
534
+ type: "array",
535
+ items: {
536
+ type: "object",
537
+ properties: {
538
+ id: { type: "string" },
539
+ likes: { type: "number" },
540
+ caption: { type: "string" },
541
+ },
542
+ },
543
+ },
544
+ },
545
+ required: ["profile"],
546
+ },
547
+ };
548
+
549
+ // Validate the schema
550
+ vana.data.validateDataSchema(instagramSchema);
551
+
552
+ // Validate user data against the schema
553
+ const userData = {
554
+ profile: { username: "alice_smith", followers: 1500, verified: false },
555
+ posts: [{ id: "post_123", likes: 42, caption: "Beautiful sunset! 🌅" }],
556
+ };
557
+
558
+ vana.data.validateDataAgainstSchema(userData, instagramSchema);
559
+ ```
560
+
561
+ ## Contributing
562
+
563
+ We welcome contributions to the Vana SDK! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
564
+
565
+ ### Development Setup
566
+
567
+ ```bash
568
+ git clone https://github.com/vana-com/vana-sdk.git
569
+ cd vana-sdk
570
+ npm install
571
+ npm run build
572
+ npm test
573
+ ```
574
+
575
+ ### Running Examples
576
+
577
+ ```bash
578
+ cd examples/vana-sdk-demo
579
+ npm install
580
+ npm run dev
581
+ ```
582
+
583
+ ## Documentation
584
+
585
+ - [📚 API Documentation](https://vana-com.github.io/vana-sdk) - Complete TypeDoc API reference
586
+ - [🚀 Getting Started Guide](https://docs.vana.org/vana-sdk) - Step-by-step setup
587
+ - [🏗️ Architecture Guide](https://docs.vana.org/vana-sdk/architecture) - SDK design and patterns
588
+ - [🔧 Configuration Guide](https://docs.vana.org/vana-sdk/configuration) - All configuration options
589
+ - [🔒 Security Guide](https://docs.vana.org/vana-sdk/security) - Best practices and security
590
+
591
+ ## Support
592
+
593
+ - **📖 Documentation**: [API Reference](https://vana-com.github.io/vana-sdk)
594
+ - **💬 Discord**: [Join our community](https://discord.gg/vanabuilders)
595
+ - **🐛 Issues**: [GitHub Issues](https://github.com/vana-com/vana-sdk/issues)
596
+ - **📧 Email**: [support@vana.org](mailto:support@vana.org)
597
+
598
+ ## License
599
+
600
+ [ISC License](LICENSE) © Vana Foundation