@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/README.md
CHANGED
|
@@ -1,33 +1,23 @@
|
|
|
1
1
|
# Vana SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **⚠️ ALPHA SOFTWARE - EXPERIMENTAL USE ONLY**
|
|
4
|
+
>
|
|
5
|
+
> This SDK is in early alpha development and is **NOT SUITABLE FOR PRODUCTION USE**.
|
|
6
|
+
> Features may change without notice, and data loss or unexpected behavior may occur.
|
|
7
|
+
> Use at your own risk and avoid using with mainnet assets or critical operations.
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
A TypeScript SDK for building data-driven applications on the Vana Network. Enable users to grant gasless permissions, manage encrypted data, and interact with privacy-preserving infrastructure.
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/@opendatalabs/vana-sdk)
|
|
6
12
|
[](https://www.typescriptlang.org/)
|
|
7
13
|
[](https://opensource.org/licenses/ISC)
|
|
8
14
|
|
|
9
|
-
[Documentation](https://vana-com.github.io/vana-sdk) • [Examples](#examples) • [
|
|
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
|
|
15
|
+
[API Documentation](https://vana-com.github.io/vana-sdk) • [Examples](#examples) • [Configuration](#configuration)
|
|
19
16
|
|
|
20
17
|
## Installation
|
|
21
18
|
|
|
22
19
|
```bash
|
|
23
|
-
|
|
24
|
-
npm install vana-sdk
|
|
25
|
-
|
|
26
|
-
# yarn
|
|
27
|
-
yarn add vana-sdk
|
|
28
|
-
|
|
29
|
-
# pnpm
|
|
30
|
-
pnpm add vana-sdk
|
|
20
|
+
npm install @opendatalabs/vana-sdk
|
|
31
21
|
```
|
|
32
22
|
|
|
33
23
|
**Peer Dependencies:**
|
|
@@ -38,13 +28,15 @@ npm install viem@^2.31.7
|
|
|
38
28
|
|
|
39
29
|
## Quick Start
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
The Vana SDK supports both browser and Node.js environments with explicit entry points:
|
|
32
|
+
|
|
33
|
+
### Browser Applications (React, Vue, etc.)
|
|
42
34
|
|
|
43
35
|
```typescript
|
|
44
|
-
|
|
36
|
+
// For browser-based applications (React, Vue, etc.)
|
|
37
|
+
import { Vana, mokshaTestnet } from "@opendatalabs/vana-sdk/browser";
|
|
45
38
|
import { createWalletClient, http } from "viem";
|
|
46
39
|
import { privateKeyToAccount } from "viem/accounts";
|
|
47
|
-
import { mokshaTestnet } from "vana-sdk";
|
|
48
40
|
|
|
49
41
|
// Create wallet client
|
|
50
42
|
const account = privateKeyToAccount("0x...");
|
|
@@ -54,104 +46,136 @@ const walletClient = createWalletClient({
|
|
|
54
46
|
transport: http("https://rpc.moksha.vana.org"),
|
|
55
47
|
});
|
|
56
48
|
|
|
57
|
-
// Initialize
|
|
58
|
-
const vana =
|
|
49
|
+
// Initialize SDK
|
|
50
|
+
const vana = Vana({
|
|
59
51
|
walletClient,
|
|
60
|
-
// Optional: configure gasless relayer
|
|
61
52
|
relayerUrl: "https://relayer.moksha.vana.org",
|
|
62
53
|
});
|
|
63
54
|
```
|
|
64
55
|
|
|
65
|
-
###
|
|
56
|
+
### Server-side Applications (Next.js API routes, Express)
|
|
66
57
|
|
|
67
58
|
```typescript
|
|
68
|
-
//
|
|
59
|
+
// For server-side applications (Next.js API routes, Express)
|
|
60
|
+
import { Vana, mokshaTestnet } from "@opendatalabs/vana-sdk/node";
|
|
61
|
+
import { createWalletClient, http } from "viem";
|
|
62
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
63
|
+
|
|
64
|
+
// Create wallet client
|
|
65
|
+
const account = privateKeyToAccount("0x...");
|
|
66
|
+
const walletClient = createWalletClient({
|
|
67
|
+
account,
|
|
68
|
+
chain: mokshaTestnet,
|
|
69
|
+
transport: http("https://rpc.moksha.vana.org"),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Initialize SDK
|
|
73
|
+
const vana = Vana({
|
|
74
|
+
walletClient,
|
|
75
|
+
relayerUrl: "https://relayer.moksha.vana.org",
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Grant gasless permission
|
|
69
79
|
const txHash = await vana.permissions.grant({
|
|
70
|
-
|
|
80
|
+
grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
71
81
|
operation: "llm_inference",
|
|
72
82
|
parameters: {
|
|
73
|
-
prompt: "Analyze my
|
|
83
|
+
prompt: "Analyze my data for insights",
|
|
74
84
|
maxTokens: 1000,
|
|
75
|
-
files: [12, 15, 28], // Specific file IDs
|
|
76
|
-
model: "gpt-4",
|
|
77
85
|
},
|
|
78
|
-
expiresAt: Math.floor(Date.now() / 1000) +
|
|
86
|
+
expiresAt: Math.floor(Date.now() / 1000) + 86400, // 24 hours
|
|
79
87
|
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Core Features
|
|
91
|
+
|
|
92
|
+
### Gasless Permissions
|
|
80
93
|
|
|
81
|
-
|
|
94
|
+
Users can grant data access permissions without paying gas fees through EIP-712 signatures and relay infrastructure.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Grant permission with custom parameters
|
|
98
|
+
await vana.permissions.grant({
|
|
99
|
+
grantee: applicationAddress,
|
|
100
|
+
operation: "data_analysis",
|
|
101
|
+
parameters: {
|
|
102
|
+
analysisType: "sentiment",
|
|
103
|
+
files: [12, 15, 28],
|
|
104
|
+
model: "gpt-4",
|
|
105
|
+
},
|
|
106
|
+
});
|
|
82
107
|
```
|
|
83
108
|
|
|
84
|
-
###
|
|
109
|
+
### Encrypted Data Management
|
|
110
|
+
|
|
111
|
+
Upload, query, and manage encrypted user data files with built-in schema validation.
|
|
85
112
|
|
|
86
113
|
```typescript
|
|
87
|
-
//
|
|
114
|
+
// Query user files
|
|
88
115
|
const files = await vana.data.getUserFiles({
|
|
89
|
-
|
|
116
|
+
owner: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
90
117
|
});
|
|
91
118
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
119
|
+
// Upload encrypted file with decryption permissions
|
|
120
|
+
const result = await vana.data.upload({
|
|
121
|
+
content: "Sensitive user data",
|
|
122
|
+
filename: "user-data.json",
|
|
123
|
+
schemaId: 123,
|
|
124
|
+
permissions: [{
|
|
125
|
+
account: "0xServerAddress...", // Who can decrypt
|
|
126
|
+
publicKey: "0x04ServerKey..." // Their public key
|
|
127
|
+
}]
|
|
95
128
|
});
|
|
96
129
|
```
|
|
97
130
|
|
|
98
|
-
###
|
|
131
|
+
### Flexible Storage
|
|
132
|
+
|
|
133
|
+
Abstract storage layer supporting IPFS, Google Drive, and custom providers.
|
|
99
134
|
|
|
100
135
|
```typescript
|
|
101
|
-
//
|
|
102
|
-
|
|
136
|
+
// For browser applications
|
|
137
|
+
import { StorageManager, PinataStorage } from "@opendatalabs/vana-sdk/browser";
|
|
138
|
+
// OR for server-side applications
|
|
139
|
+
// import { StorageManager, PinataStorage } from "@opendatalabs/vana-sdk/node";
|
|
103
140
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
141
|
+
const storageManager = new StorageManager();
|
|
142
|
+
storageManager.register(
|
|
143
|
+
"ipfs",
|
|
144
|
+
new PinataStorage({
|
|
145
|
+
apiKey: process.env.PINATA_API_KEY,
|
|
146
|
+
secretKey: process.env.PINATA_SECRET_KEY,
|
|
108
147
|
}),
|
|
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);
|
|
148
|
+
);
|
|
121
149
|
```
|
|
122
150
|
|
|
123
151
|
## Architecture
|
|
124
152
|
|
|
125
|
-
The
|
|
126
|
-
|
|
127
|
-
### Core Controllers
|
|
153
|
+
The SDK provides four main controllers:
|
|
128
154
|
|
|
129
|
-
| Controller
|
|
130
|
-
|
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
|
|
|
134
|
-
|
|
|
155
|
+
| Controller | Purpose | Key Methods |
|
|
156
|
+
| ------------- | ------------------------------ | ----------------------------------------------------------------- |
|
|
157
|
+
| `permissions` | Gasless permission management | `grant()`, `revoke()`, `getUserPermissions()` |
|
|
158
|
+
| `data` | File management and validation | `getUserFiles()`, `uploadEncryptedFile()`, `validateDataSchema()` |
|
|
159
|
+
| `server` | Trusted server operations | `trustServer()`, `processWithTrustedServer()` |
|
|
160
|
+
| `protocol` | Contract interaction | `getContract()`, `getAvailableContracts()` |
|
|
135
161
|
|
|
136
|
-
|
|
162
|
+
## Configuration
|
|
137
163
|
|
|
138
164
|
```typescript
|
|
139
|
-
const vana =
|
|
140
|
-
// Required: Wallet client for signing
|
|
165
|
+
const vana = Vana({
|
|
141
166
|
walletClient,
|
|
142
167
|
|
|
143
|
-
//
|
|
144
|
-
relayerUrl: "https://
|
|
168
|
+
// Gasless transaction relay
|
|
169
|
+
relayerUrl: "https://relayer.moksha.vana.org",
|
|
145
170
|
|
|
146
|
-
//
|
|
171
|
+
// Custom relay callbacks
|
|
147
172
|
relayerCallbacks: {
|
|
148
173
|
submitPermissionGrant: async (typedData, signature) => {
|
|
149
|
-
// Custom relay implementation
|
|
150
174
|
return await customRelayer.submit(typedData, signature);
|
|
151
175
|
},
|
|
152
176
|
},
|
|
153
177
|
|
|
154
|
-
//
|
|
178
|
+
// Storage configuration
|
|
155
179
|
storageManager: new StorageManager({
|
|
156
180
|
defaultProvider: "ipfs",
|
|
157
181
|
providers: {
|
|
@@ -159,441 +183,188 @@ const vana = new Vana({
|
|
|
159
183
|
},
|
|
160
184
|
}),
|
|
161
185
|
|
|
162
|
-
//
|
|
186
|
+
// Subgraph for efficient queries
|
|
163
187
|
subgraphUrl: "https://api.thegraph.com/subgraphs/name/vana/moksha",
|
|
164
188
|
});
|
|
165
189
|
```
|
|
166
190
|
|
|
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
191
|
## Error Handling
|
|
421
192
|
|
|
422
|
-
The SDK provides
|
|
193
|
+
The SDK provides specific error types for different failure scenarios:
|
|
423
194
|
|
|
424
195
|
```typescript
|
|
425
196
|
import {
|
|
426
197
|
RelayerError,
|
|
427
198
|
UserRejectedRequestError,
|
|
428
199
|
SchemaValidationError,
|
|
429
|
-
InvalidConfigurationError,
|
|
430
200
|
NetworkError,
|
|
431
|
-
} from "vana-sdk";
|
|
201
|
+
} from "@opendatalabs/vana-sdk/browser";
|
|
202
|
+
// OR for server-side applications
|
|
203
|
+
// } from "@opendatalabs/vana-sdk/node";
|
|
432
204
|
|
|
433
205
|
try {
|
|
434
206
|
await vana.permissions.grant(params);
|
|
435
207
|
} catch (error) {
|
|
436
208
|
if (error instanceof UserRejectedRequestError) {
|
|
437
|
-
// User
|
|
438
|
-
console.log("User cancelled transaction");
|
|
209
|
+
// User cancelled transaction
|
|
439
210
|
} else if (error instanceof RelayerError) {
|
|
440
211
|
// Relayer service error
|
|
441
|
-
console.log(`Relayer error (${error.statusCode}): ${error.message}`);
|
|
442
212
|
} else if (error instanceof SchemaValidationError) {
|
|
443
213
|
// 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
214
|
}
|
|
452
215
|
}
|
|
453
216
|
```
|
|
454
217
|
|
|
455
218
|
## Supported Networks
|
|
456
219
|
|
|
457
|
-
| Network | Chain ID | RPC URL |
|
|
458
|
-
| ------------------ | -------- | ----------------------------- |
|
|
459
|
-
| **Vana Mainnet** | `1480` | `https://rpc.vana.org` |
|
|
460
|
-
| **Moksha Testnet** | `14800` | `https://rpc.moksha.vana.org` |
|
|
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
|
-
```
|
|
220
|
+
| Network | Chain ID | RPC URL |
|
|
221
|
+
| ------------------ | -------- | ----------------------------- |
|
|
222
|
+
| **Vana Mainnet** | `1480` | `https://rpc.vana.org` |
|
|
223
|
+
| **Moksha Testnet** | `14800` | `https://rpc.moksha.vana.org` |
|
|
473
224
|
|
|
474
225
|
## Examples
|
|
475
226
|
|
|
476
|
-
### Complete
|
|
227
|
+
### Complete Data Sharing Flow
|
|
477
228
|
|
|
478
229
|
```typescript
|
|
479
|
-
import { Vana
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
// 1. Initialize SDK
|
|
483
|
-
const vana = new Vana({ walletClient });
|
|
230
|
+
import { Vana } from "@opendatalabs/vana-sdk/browser";
|
|
231
|
+
// OR for server-side applications
|
|
232
|
+
// } from "@opendatalabs/vana-sdk/node";
|
|
484
233
|
|
|
485
|
-
|
|
486
|
-
const
|
|
487
|
-
const userData = new Blob([JSON.stringify({ data: "sensitive info" })]);
|
|
488
|
-
const encryptedData = await encryptUserData(userData, encryptionKey);
|
|
234
|
+
async function shareDataWithServer() {
|
|
235
|
+
const vana = Vana({ walletClient });
|
|
489
236
|
|
|
490
|
-
//
|
|
491
|
-
const uploadResult = await vana.data.
|
|
492
|
-
data:
|
|
237
|
+
// Step 1: Upload encrypted file with decryption permissions
|
|
238
|
+
const uploadResult = await vana.data.upload({
|
|
239
|
+
content: { data: "sensitive medical records" },
|
|
240
|
+
filename: "health-data.json",
|
|
493
241
|
schemaId: 123,
|
|
494
|
-
|
|
242
|
+
permissions: [{
|
|
243
|
+
// Grant decryption access to the AI server
|
|
244
|
+
account: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
245
|
+
publicKey: "0x04abc..." // Server's public key for encryption
|
|
246
|
+
}]
|
|
495
247
|
});
|
|
496
248
|
|
|
497
|
-
//
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
|
|
249
|
+
// Step 2: Grant operation permissions for what the server can do
|
|
250
|
+
const permissionResult = await vana.permissions.grant({
|
|
251
|
+
grantee: "0x742d35Cc6558Fd4D9e9E0E888F0462ef6919Bd36",
|
|
252
|
+
fileIds: [BigInt(uploadResult.fileId)],
|
|
253
|
+
operation: "medical_analysis",
|
|
501
254
|
parameters: {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
maxTokens: 500,
|
|
255
|
+
model: "medical-ai-v2",
|
|
256
|
+
analysisType: "comprehensive",
|
|
505
257
|
},
|
|
506
258
|
});
|
|
507
259
|
|
|
508
|
-
|
|
260
|
+
return { uploadResult, permissionResult };
|
|
509
261
|
}
|
|
510
262
|
```
|
|
511
263
|
|
|
512
|
-
### Schema Validation
|
|
264
|
+
### Schema Validation
|
|
513
265
|
|
|
514
266
|
```typescript
|
|
515
|
-
// Define
|
|
516
|
-
const
|
|
517
|
-
name: "
|
|
267
|
+
// Define data schema
|
|
268
|
+
const schema = {
|
|
269
|
+
name: "Social Media Export",
|
|
518
270
|
version: "1.0.0",
|
|
519
|
-
description: "User's Instagram profile and posts data",
|
|
520
271
|
dialect: "json",
|
|
521
272
|
schema: {
|
|
522
273
|
type: "object",
|
|
523
274
|
properties: {
|
|
524
|
-
|
|
525
|
-
|
|
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
|
-
},
|
|
275
|
+
posts: { type: "array" },
|
|
276
|
+
profile: { type: "object" },
|
|
544
277
|
},
|
|
545
278
|
required: ["profile"],
|
|
546
279
|
},
|
|
547
280
|
};
|
|
548
281
|
|
|
549
|
-
// Validate
|
|
550
|
-
vana.data.validateDataSchema(
|
|
282
|
+
// Validate schema
|
|
283
|
+
vana.data.validateDataSchema(schema);
|
|
551
284
|
|
|
552
|
-
// Validate user data
|
|
285
|
+
// Validate user data
|
|
553
286
|
const userData = {
|
|
554
|
-
profile: { username: "
|
|
555
|
-
posts: [
|
|
287
|
+
profile: { username: "alice" },
|
|
288
|
+
posts: [],
|
|
556
289
|
};
|
|
557
|
-
|
|
558
|
-
vana.data.validateDataAgainstSchema(userData, instagramSchema);
|
|
290
|
+
vana.data.validateDataAgainstSchema(userData, schema);
|
|
559
291
|
```
|
|
560
292
|
|
|
561
|
-
##
|
|
293
|
+
## API Reference
|
|
562
294
|
|
|
563
|
-
|
|
295
|
+
### Permissions
|
|
564
296
|
|
|
565
|
-
|
|
297
|
+
```typescript
|
|
298
|
+
// Grant operation permission
|
|
299
|
+
await vana.permissions.grant({
|
|
300
|
+
grantee: Address,
|
|
301
|
+
fileIds: bigint[],
|
|
302
|
+
operation: string,
|
|
303
|
+
parameters: object,
|
|
304
|
+
expiresAt?: number
|
|
305
|
+
}): Promise<PermissionGrantResult>
|
|
306
|
+
|
|
307
|
+
// Revoke permission
|
|
308
|
+
await vana.permissions.revoke({
|
|
309
|
+
grantId: string
|
|
310
|
+
}): Promise<Hash>
|
|
566
311
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
npm run build
|
|
572
|
-
npm test
|
|
312
|
+
// Get user permissions
|
|
313
|
+
await vana.permissions.getUserPermissions({
|
|
314
|
+
owner: Address
|
|
315
|
+
}): Promise<GrantedPermission[]>
|
|
573
316
|
```
|
|
574
317
|
|
|
575
|
-
###
|
|
318
|
+
### Data
|
|
576
319
|
|
|
577
|
-
```
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
320
|
+
```typescript
|
|
321
|
+
// Get user files
|
|
322
|
+
await vana.data.getUserFiles({
|
|
323
|
+
owner: Address
|
|
324
|
+
}): Promise<UserFile[]>
|
|
325
|
+
|
|
326
|
+
// Upload data with automatic encryption
|
|
327
|
+
await vana.data.upload({
|
|
328
|
+
content: string | Blob | Buffer,
|
|
329
|
+
filename?: string,
|
|
330
|
+
schemaId?: number,
|
|
331
|
+
permissions?: Array<{
|
|
332
|
+
account: Address, // Who can decrypt
|
|
333
|
+
publicKey: string // Their public key
|
|
334
|
+
}>,
|
|
335
|
+
encrypt?: boolean // Default: true
|
|
336
|
+
}): Promise<UploadResult>
|
|
337
|
+
|
|
338
|
+
// Validate schema
|
|
339
|
+
vana.data.validateDataSchema(schema: unknown): void
|
|
340
|
+
|
|
341
|
+
// Validate data against schema
|
|
342
|
+
vana.data.validateDataAgainstSchema(data: unknown, schema: DataSchema): void
|
|
581
343
|
```
|
|
582
344
|
|
|
583
345
|
## Documentation
|
|
584
346
|
|
|
585
|
-
- [
|
|
586
|
-
- [
|
|
587
|
-
- [
|
|
588
|
-
- [
|
|
589
|
-
- [
|
|
347
|
+
- [API Documentation](https://vana-com.github.io/vana-sdk) - Complete TypeDoc API reference
|
|
348
|
+
- [Getting Started](https://vana-com.github.io/vana-sdk/getting-started) - Step-by-step setup guide
|
|
349
|
+
- [Architecture](https://vana-com.github.io/vana-sdk/architecture) - SDK design and patterns
|
|
350
|
+
- [Configuration](https://vana-com.github.io/vana-sdk/configuration) - All configuration options
|
|
351
|
+
- [Security](https://vana-com.github.io/vana-sdk/security) - Best practices and security
|
|
590
352
|
|
|
591
353
|
## Support
|
|
592
354
|
|
|
593
|
-
-
|
|
594
|
-
-
|
|
595
|
-
-
|
|
596
|
-
|
|
355
|
+
- **Documentation**: [vana-com.github.io/vana-sdk](https://vana-com.github.io/vana-sdk)
|
|
356
|
+
- **Issues**: [GitHub Issues](https://github.com/vana-com/vana-sdk/issues)
|
|
357
|
+
- **Discord**: [Join our community](https://discord.gg/vanabuilders)
|
|
358
|
+
|
|
359
|
+
## Development
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
git clone https://github.com/vana-com/vana-sdk.git
|
|
363
|
+
cd vana-sdk
|
|
364
|
+
npm install
|
|
365
|
+
npm run build
|
|
366
|
+
npm test
|
|
367
|
+
```
|
|
597
368
|
|
|
598
369
|
## License
|
|
599
370
|
|