shogun-relay-sdk 1.2.11 → 1.4.0
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 +408 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/modules/api-keys.d.ts +44 -0
- package/dist/modules/api-keys.js +36 -0
- package/dist/modules/deals.d.ts +1 -1
- package/dist/modules/deals.js +4 -2
- package/dist/modules/drive.d.ts +135 -0
- package/dist/modules/drive.js +125 -0
- package/dist/modules/ipfs.d.ts +26 -6
- package/dist/modules/ipfs.js +56 -16
- package/dist/utils/wallet.d.ts +56 -0
- package/dist/utils/wallet.js +112 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# Shogun Relay SDK
|
|
2
|
+
|
|
3
|
+
TypeScript/JavaScript SDK for interacting with Shogun Relay API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @shogun/relay-sdk
|
|
9
|
+
# or
|
|
10
|
+
yarn add @shogun/relay-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import ShogunRelaySDK from '@shogun/relay-sdk';
|
|
17
|
+
import { generateWalletSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
18
|
+
import { ethers } from 'ethers';
|
|
19
|
+
|
|
20
|
+
// Initialize SDK
|
|
21
|
+
const sdk = new ShogunRelaySDK({
|
|
22
|
+
baseURL: 'https://shogun-relay.scobrudot.dev',
|
|
23
|
+
token: 'your-admin-token' // Optional: for admin operations
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Or set token later
|
|
27
|
+
sdk.setToken('your-admin-token');
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Authentication
|
|
31
|
+
|
|
32
|
+
### Admin Authentication
|
|
33
|
+
|
|
34
|
+
For admin operations, use the admin token:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
const sdk = new ShogunRelaySDK({
|
|
38
|
+
baseURL: 'https://shogun-relay.scobrudot.dev',
|
|
39
|
+
token: 'your-admin-token'
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Admin upload (no signature required)
|
|
43
|
+
const result = await sdk.ipfs.uploadFile(
|
|
44
|
+
fileBuffer,
|
|
45
|
+
'example.txt',
|
|
46
|
+
'text/plain'
|
|
47
|
+
);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Wallet Signature Authentication
|
|
51
|
+
|
|
52
|
+
For user operations, you need to sign a message with your wallet:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { generateWalletSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
56
|
+
import { ethers } from 'ethers';
|
|
57
|
+
|
|
58
|
+
// Connect to wallet
|
|
59
|
+
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
60
|
+
const signer = await provider.getSigner();
|
|
61
|
+
const address = await signer.getAddress();
|
|
62
|
+
|
|
63
|
+
// Generate signature
|
|
64
|
+
const signature = await generateWalletSignature(signer);
|
|
65
|
+
|
|
66
|
+
// Upload with wallet signature
|
|
67
|
+
const result = await sdk.ipfs.uploadFile(
|
|
68
|
+
fileBuffer,
|
|
69
|
+
'example.txt',
|
|
70
|
+
'text/plain',
|
|
71
|
+
{
|
|
72
|
+
userAddress: address,
|
|
73
|
+
walletSignature: signature,
|
|
74
|
+
isDealUpload: true // For deal uploads (no subscription required)
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## API Keys
|
|
80
|
+
|
|
81
|
+
Manage API keys for programmatic access to all relay services:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// List all API keys
|
|
85
|
+
const keys = await sdk.apiKeys.list();
|
|
86
|
+
|
|
87
|
+
// Create a new API key
|
|
88
|
+
const newKey = await sdk.apiKeys.create('My App Key', 30); // 30 days expiration
|
|
89
|
+
console.log('API Key:', newKey.token); // Save this, it's only shown once!
|
|
90
|
+
|
|
91
|
+
// Use the API key for authentication
|
|
92
|
+
sdk.apiKeys.useApiKey(newKey.token);
|
|
93
|
+
|
|
94
|
+
// Or use it directly
|
|
95
|
+
sdk.setToken(newKey.token);
|
|
96
|
+
|
|
97
|
+
// Revoke an API key
|
|
98
|
+
await sdk.apiKeys.revoke(newKey.keyId);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Note**: API keys work across all relay services (Drive, IPFS, etc.) and use the prefix `shogun-api-`.
|
|
102
|
+
|
|
103
|
+
## Drive Operations
|
|
104
|
+
|
|
105
|
+
The Drive module provides file system operations for the admin drive:
|
|
106
|
+
|
|
107
|
+
### List Files
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// List root directory
|
|
111
|
+
const files = await sdk.drive.list();
|
|
112
|
+
|
|
113
|
+
// List specific directory
|
|
114
|
+
const files = await sdk.drive.list('folder/subfolder');
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Upload Files
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// Upload single file
|
|
121
|
+
const result = await sdk.drive.uploadFile(
|
|
122
|
+
fileBuffer,
|
|
123
|
+
'example.txt',
|
|
124
|
+
'folder' // optional path
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Upload multiple files
|
|
128
|
+
const result = await sdk.drive.uploadFiles([
|
|
129
|
+
{ file: fileBuffer1, filename: 'file1.txt' },
|
|
130
|
+
{ file: fileBuffer2, filename: 'file2.txt' }
|
|
131
|
+
], 'folder');
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Download Files
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const fileBuffer = await sdk.drive.download('path/to/file.txt');
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Directory Operations
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
// Create directory
|
|
144
|
+
await sdk.drive.createDirectory('new-folder', 'parent-folder');
|
|
145
|
+
|
|
146
|
+
// Rename file/directory
|
|
147
|
+
await sdk.drive.rename('old-name.txt', 'new-name.txt');
|
|
148
|
+
|
|
149
|
+
// Move file/directory
|
|
150
|
+
await sdk.drive.move('source.txt', 'destination/folder/source.txt');
|
|
151
|
+
|
|
152
|
+
// Delete file/directory
|
|
153
|
+
await sdk.drive.delete('path/to/item');
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Storage Statistics
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const stats = await sdk.drive.getStats();
|
|
160
|
+
console.log(`Total: ${stats.stats.totalSizeMB} MB`);
|
|
161
|
+
console.log(`Files: ${stats.stats.fileCount}`);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Public Links
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// Create a public sharing link
|
|
168
|
+
const link = await sdk.drive.createPublicLink('document.pdf', 7); // 7 days expiration
|
|
169
|
+
console.log('Public URL:', link.publicUrl);
|
|
170
|
+
|
|
171
|
+
// List all public links
|
|
172
|
+
const links = await sdk.drive.listPublicLinks();
|
|
173
|
+
|
|
174
|
+
// Revoke a link
|
|
175
|
+
await sdk.drive.revokePublicLink(link.linkId);
|
|
176
|
+
|
|
177
|
+
// Get public file URL (for direct access)
|
|
178
|
+
const publicUrl = sdk.drive.getPublicFileUrl(link.linkId, 'https://shogun-relay.scobrudot.dev');
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## IPFS Operations
|
|
182
|
+
|
|
183
|
+
### Upload Single File
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// Admin upload
|
|
187
|
+
const result = await sdk.ipfs.uploadFile(
|
|
188
|
+
fileBuffer,
|
|
189
|
+
'example.txt',
|
|
190
|
+
'text/plain'
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
// User upload with subscription
|
|
194
|
+
const result = await sdk.ipfs.uploadFile(
|
|
195
|
+
fileBuffer,
|
|
196
|
+
'example.txt',
|
|
197
|
+
'text/plain',
|
|
198
|
+
{
|
|
199
|
+
userAddress: address,
|
|
200
|
+
walletSignature: signature
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
// Deal upload (no subscription required)
|
|
205
|
+
const result = await sdk.ipfs.uploadFile(
|
|
206
|
+
fileBuffer,
|
|
207
|
+
'example.txt',
|
|
208
|
+
'text/plain',
|
|
209
|
+
{
|
|
210
|
+
userAddress: address,
|
|
211
|
+
walletSignature: signature,
|
|
212
|
+
isDealUpload: true
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
// Encrypted upload
|
|
217
|
+
const encryptedResult = await sdk.ipfs.uploadFile(
|
|
218
|
+
fileBuffer,
|
|
219
|
+
'example.txt',
|
|
220
|
+
'text/plain',
|
|
221
|
+
{
|
|
222
|
+
userAddress: address,
|
|
223
|
+
walletSignature: signature,
|
|
224
|
+
encrypted: true,
|
|
225
|
+
encryptionToken: signature // Use same signature for encryption
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Upload Directory
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const files = [
|
|
234
|
+
{
|
|
235
|
+
buffer: indexHtmlBuffer,
|
|
236
|
+
filename: 'index.html',
|
|
237
|
+
path: 'index.html',
|
|
238
|
+
contentType: 'text/html'
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
buffer: styleCssBuffer,
|
|
242
|
+
filename: 'style.css',
|
|
243
|
+
path: 'css/style.css',
|
|
244
|
+
contentType: 'text/css'
|
|
245
|
+
}
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
const result = await sdk.ipfs.uploadDirectory(files, {
|
|
249
|
+
userAddress: address,
|
|
250
|
+
walletSignature: signature,
|
|
251
|
+
isDealUpload: true
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Browser Upload
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// Single file
|
|
259
|
+
const fileInput = document.querySelector('input[type="file"]');
|
|
260
|
+
const file = fileInput.files[0];
|
|
261
|
+
|
|
262
|
+
const result = await sdk.ipfs.uploadFileBrowser(file, {
|
|
263
|
+
userAddress: address,
|
|
264
|
+
walletSignature: signature,
|
|
265
|
+
isDealUpload: true
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// Directory upload
|
|
269
|
+
const directoryInput = document.querySelector('input[type="file"][webkitdirectory]');
|
|
270
|
+
const files = Array.from(directoryInput.files);
|
|
271
|
+
|
|
272
|
+
const result = await sdk.ipfs.uploadDirectoryBrowser(files, {
|
|
273
|
+
userAddress: address,
|
|
274
|
+
walletSignature: signature
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Retrieve File
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
// Get file content
|
|
282
|
+
const content = await sdk.ipfs.cat('QmHash...');
|
|
283
|
+
|
|
284
|
+
// Get encrypted file (decrypted)
|
|
285
|
+
const decryptedContent = await sdk.ipfs.catDecrypt(
|
|
286
|
+
'QmHash...',
|
|
287
|
+
signature, // Encryption token
|
|
288
|
+
address // Optional: for signature verification
|
|
289
|
+
);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Storage Deals
|
|
293
|
+
|
|
294
|
+
### Upload for Deal
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
const signature = await generateWalletSignature(signer);
|
|
298
|
+
|
|
299
|
+
const result = await sdk.deals.uploadForDeal(
|
|
300
|
+
fileBuffer,
|
|
301
|
+
'example.txt',
|
|
302
|
+
'text/plain',
|
|
303
|
+
address,
|
|
304
|
+
signature // Required: wallet signature
|
|
305
|
+
);
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Create Deal
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const deal = await sdk.deals.createDeal({
|
|
312
|
+
cid: 'QmHash...',
|
|
313
|
+
clientAddress: address,
|
|
314
|
+
sizeMB: 10,
|
|
315
|
+
durationDays: 30,
|
|
316
|
+
tier: 'standard'
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Wallet Utilities
|
|
321
|
+
|
|
322
|
+
The SDK includes utility functions for wallet operations:
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import {
|
|
326
|
+
generateWalletSignature,
|
|
327
|
+
verifyWalletSignature,
|
|
328
|
+
getAddressFromSignature,
|
|
329
|
+
WALLET_AUTH_MESSAGE
|
|
330
|
+
} from '@shogun/relay-sdk/utils/wallet';
|
|
331
|
+
|
|
332
|
+
// Generate signature
|
|
333
|
+
const signature = await generateWalletSignature(signer);
|
|
334
|
+
|
|
335
|
+
// Verify signature
|
|
336
|
+
const isValid = await verifyWalletSignature(address, signature);
|
|
337
|
+
|
|
338
|
+
// Get address from signature
|
|
339
|
+
const recoveredAddress = await getAddressFromSignature(signature);
|
|
340
|
+
|
|
341
|
+
// The message that must be signed
|
|
342
|
+
console.log(WALLET_AUTH_MESSAGE); // "I Love Shogun"
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Complete Example
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
import ShogunRelaySDK from '@shogun/relay-sdk';
|
|
349
|
+
import { generateWalletSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
350
|
+
import { ethers } from 'ethers';
|
|
351
|
+
import fs from 'fs';
|
|
352
|
+
|
|
353
|
+
async function uploadFileExample() {
|
|
354
|
+
// Initialize SDK
|
|
355
|
+
const sdk = new ShogunRelaySDK({
|
|
356
|
+
baseURL: 'https://shogun-relay.scobrudot.dev'
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
// Connect wallet
|
|
360
|
+
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
361
|
+
const signer = await provider.getSigner();
|
|
362
|
+
const address = await signer.getAddress();
|
|
363
|
+
|
|
364
|
+
// Generate signature for authentication
|
|
365
|
+
const signature = await generateWalletSignature(signer);
|
|
366
|
+
|
|
367
|
+
// Read file
|
|
368
|
+
const fileBuffer = fs.readFileSync('example.txt');
|
|
369
|
+
|
|
370
|
+
// Upload as deal (no subscription required)
|
|
371
|
+
const result = await sdk.ipfs.uploadFile(
|
|
372
|
+
fileBuffer,
|
|
373
|
+
'example.txt',
|
|
374
|
+
'text/plain',
|
|
375
|
+
{
|
|
376
|
+
userAddress: address,
|
|
377
|
+
walletSignature: signature,
|
|
378
|
+
isDealUpload: true
|
|
379
|
+
}
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
console.log('Uploaded! CID:', result.cid);
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## API Reference
|
|
388
|
+
|
|
389
|
+
See the main [API Documentation](../docs/API.md) for complete endpoint reference.
|
|
390
|
+
|
|
391
|
+
## Modules
|
|
392
|
+
|
|
393
|
+
- **System**: Health checks, stats, system information
|
|
394
|
+
- **IPFS**: File uploads, directory uploads, content retrieval, pinning
|
|
395
|
+
- **Drive**: Admin drive file system operations, public link sharing
|
|
396
|
+
- **API Keys**: API key management for programmatic access
|
|
397
|
+
- **Deals**: Storage deal creation, activation, management
|
|
398
|
+
- **Registry**: On-chain relay registry operations
|
|
399
|
+
- **Network**: Network federation, reputation, relay discovery
|
|
400
|
+
- **X402**: Subscription management, storage limits
|
|
401
|
+
- **Bridge**: L2 bridge operations, deposits, withdrawals
|
|
402
|
+
- **Uploads**: User upload metadata management
|
|
403
|
+
- **AnnasArchive**: Torrent and archive management
|
|
404
|
+
|
|
405
|
+
## License
|
|
406
|
+
|
|
407
|
+
MIT
|
|
408
|
+
|
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,13 @@ import { RegistryModule } from "./modules/registry";
|
|
|
8
8
|
import { UploadsModule } from "./modules/uploads";
|
|
9
9
|
import { BridgeModule } from "./modules/bridge";
|
|
10
10
|
import { AnnasArchiveModule } from "./modules/annas-archive";
|
|
11
|
+
import { DriveModule } from "./modules/drive";
|
|
12
|
+
import { ApiKeysModule } from "./modules/api-keys";
|
|
11
13
|
export * from "./types";
|
|
12
14
|
export * from "./modules/annas-archive";
|
|
15
|
+
export * from "./modules/drive";
|
|
16
|
+
export * from "./modules/api-keys";
|
|
17
|
+
export * from "./utils/wallet";
|
|
13
18
|
export declare class ShogunRelaySDK {
|
|
14
19
|
private client;
|
|
15
20
|
system: SystemModule;
|
|
@@ -21,6 +26,8 @@ export declare class ShogunRelaySDK {
|
|
|
21
26
|
uploads: UploadsModule;
|
|
22
27
|
bridge: BridgeModule;
|
|
23
28
|
annasArchive: AnnasArchiveModule;
|
|
29
|
+
drive: DriveModule;
|
|
30
|
+
apiKeys: ApiKeysModule;
|
|
24
31
|
constructor(config: ApiClientConfig);
|
|
25
32
|
setToken(token: string): void;
|
|
26
33
|
}
|
package/dist/index.js
CHANGED
|
@@ -25,9 +25,15 @@ const registry_1 = require("./modules/registry");
|
|
|
25
25
|
const uploads_1 = require("./modules/uploads");
|
|
26
26
|
const bridge_1 = require("./modules/bridge");
|
|
27
27
|
const annas_archive_1 = require("./modules/annas-archive");
|
|
28
|
+
const drive_1 = require("./modules/drive");
|
|
29
|
+
const api_keys_1 = require("./modules/api-keys");
|
|
28
30
|
// Export types
|
|
29
31
|
__exportStar(require("./types"), exports);
|
|
30
32
|
__exportStar(require("./modules/annas-archive"), exports);
|
|
33
|
+
__exportStar(require("./modules/drive"), exports);
|
|
34
|
+
__exportStar(require("./modules/api-keys"), exports);
|
|
35
|
+
// Export wallet utilities
|
|
36
|
+
__exportStar(require("./utils/wallet"), exports);
|
|
31
37
|
class ShogunRelaySDK {
|
|
32
38
|
constructor(config) {
|
|
33
39
|
this.client = new client_1.ApiClient(config);
|
|
@@ -40,6 +46,8 @@ class ShogunRelaySDK {
|
|
|
40
46
|
this.uploads = new uploads_1.UploadsModule(this.client);
|
|
41
47
|
this.bridge = new bridge_1.BridgeModule(this.client);
|
|
42
48
|
this.annasArchive = new annas_archive_1.AnnasArchiveModule(this.client);
|
|
49
|
+
this.drive = new drive_1.DriveModule(this.client);
|
|
50
|
+
this.apiKeys = new api_keys_1.ApiKeysModule(this.client);
|
|
43
51
|
}
|
|
44
52
|
setToken(token) {
|
|
45
53
|
this.client.setToken(token);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ApiClient } from "../client";
|
|
2
|
+
export interface ApiKey {
|
|
3
|
+
keyId: string;
|
|
4
|
+
name: string;
|
|
5
|
+
createdAt: number;
|
|
6
|
+
lastUsedAt: number | null;
|
|
7
|
+
expiresAt: number | null;
|
|
8
|
+
}
|
|
9
|
+
export interface ApiKeyCreateResponse {
|
|
10
|
+
success: boolean;
|
|
11
|
+
keyId: string;
|
|
12
|
+
token: string;
|
|
13
|
+
name: string;
|
|
14
|
+
createdAt: number;
|
|
15
|
+
expiresAt: number | null;
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ApiKeysListResponse {
|
|
19
|
+
success: boolean;
|
|
20
|
+
keys: ApiKey[];
|
|
21
|
+
}
|
|
22
|
+
export declare class ApiKeysModule {
|
|
23
|
+
private client;
|
|
24
|
+
constructor(client: ApiClient);
|
|
25
|
+
/**
|
|
26
|
+
* List all API keys
|
|
27
|
+
*/
|
|
28
|
+
list(): Promise<ApiKeysListResponse>;
|
|
29
|
+
/**
|
|
30
|
+
* Create a new API key
|
|
31
|
+
*/
|
|
32
|
+
create(name: string, expiresInDays?: number): Promise<ApiKeyCreateResponse>;
|
|
33
|
+
/**
|
|
34
|
+
* Revoke an API key
|
|
35
|
+
*/
|
|
36
|
+
revoke(keyId: string): Promise<{
|
|
37
|
+
success: boolean;
|
|
38
|
+
message: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Set the API key as the authentication token for future requests
|
|
42
|
+
*/
|
|
43
|
+
useApiKey(apiKeyToken: string): void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiKeysModule = void 0;
|
|
4
|
+
class ApiKeysModule {
|
|
5
|
+
constructor(client) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* List all API keys
|
|
10
|
+
*/
|
|
11
|
+
async list() {
|
|
12
|
+
return this.client.get("/api/v1/api-keys");
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a new API key
|
|
16
|
+
*/
|
|
17
|
+
async create(name, expiresInDays) {
|
|
18
|
+
return this.client.post("/api/v1/api-keys", {
|
|
19
|
+
name,
|
|
20
|
+
expiresInDays,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Revoke an API key
|
|
25
|
+
*/
|
|
26
|
+
async revoke(keyId) {
|
|
27
|
+
return this.client.delete(`/api/v1/api-keys/${keyId}`);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Set the API key as the authentication token for future requests
|
|
31
|
+
*/
|
|
32
|
+
useApiKey(apiKeyToken) {
|
|
33
|
+
this.client.setToken(apiKeyToken);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.ApiKeysModule = ApiKeysModule;
|
package/dist/modules/deals.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export declare class DealsModule {
|
|
|
3
3
|
private client;
|
|
4
4
|
constructor(client: ApiClient);
|
|
5
5
|
getPricing(sizeMB?: number, durationDays?: number, tier?: string): Promise<any>;
|
|
6
|
-
uploadForDeal(fileBuffer: Buffer, filename: string, contentType: string, walletAddress: string): Promise<any>;
|
|
6
|
+
uploadForDeal(fileBuffer: Buffer, filename: string, contentType: string, walletAddress: string, walletSignature: string): Promise<any>;
|
|
7
7
|
createDeal(dealParams: {
|
|
8
8
|
cid: string;
|
|
9
9
|
clientAddress: string;
|
package/dist/modules/deals.js
CHANGED
|
@@ -19,7 +19,7 @@ class DealsModule {
|
|
|
19
19
|
params.tier = tier;
|
|
20
20
|
return this.client.get("/api/v1/deals/pricing", { params });
|
|
21
21
|
}
|
|
22
|
-
async uploadForDeal(fileBuffer, filename, contentType, walletAddress) {
|
|
22
|
+
async uploadForDeal(fileBuffer, filename, contentType, walletAddress, walletSignature) {
|
|
23
23
|
const form = new form_data_1.default();
|
|
24
24
|
form.append("file", fileBuffer, {
|
|
25
25
|
filename: filename,
|
|
@@ -28,7 +28,9 @@ class DealsModule {
|
|
|
28
28
|
return this.client.post("/api/v1/deals/upload", form, {
|
|
29
29
|
headers: {
|
|
30
30
|
...form.getHeaders(),
|
|
31
|
-
"x-
|
|
31
|
+
"x-user-address": walletAddress,
|
|
32
|
+
"x-wallet-signature": walletSignature,
|
|
33
|
+
"x-deal-upload": "true",
|
|
32
34
|
},
|
|
33
35
|
});
|
|
34
36
|
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { ApiClient } from "../client";
|
|
2
|
+
export interface DriveFileItem {
|
|
3
|
+
name: string;
|
|
4
|
+
path: string;
|
|
5
|
+
type: "file" | "directory";
|
|
6
|
+
size: number;
|
|
7
|
+
modified: number;
|
|
8
|
+
}
|
|
9
|
+
export interface DriveListResponse {
|
|
10
|
+
success: boolean;
|
|
11
|
+
items: DriveFileItem[];
|
|
12
|
+
path: string;
|
|
13
|
+
}
|
|
14
|
+
export interface DriveStatsResponse {
|
|
15
|
+
success: boolean;
|
|
16
|
+
stats: {
|
|
17
|
+
totalBytes: number;
|
|
18
|
+
totalSizeMB: string;
|
|
19
|
+
totalSizeGB: string;
|
|
20
|
+
fileCount: number;
|
|
21
|
+
dirCount: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface PublicLink {
|
|
25
|
+
linkId: string;
|
|
26
|
+
filePath: string;
|
|
27
|
+
createdAt: number;
|
|
28
|
+
expiresAt: number | null;
|
|
29
|
+
accessCount: number;
|
|
30
|
+
lastAccessedAt: number | null;
|
|
31
|
+
}
|
|
32
|
+
export interface PublicLinkResponse {
|
|
33
|
+
success: boolean;
|
|
34
|
+
linkId: string;
|
|
35
|
+
filePath: string;
|
|
36
|
+
publicUrl: string;
|
|
37
|
+
createdAt: number;
|
|
38
|
+
expiresAt: number | null;
|
|
39
|
+
}
|
|
40
|
+
export interface PublicLinksListResponse {
|
|
41
|
+
success: boolean;
|
|
42
|
+
links: PublicLink[];
|
|
43
|
+
}
|
|
44
|
+
export declare class DriveModule {
|
|
45
|
+
private client;
|
|
46
|
+
constructor(client: ApiClient);
|
|
47
|
+
/**
|
|
48
|
+
* List files and folders in the specified directory
|
|
49
|
+
*/
|
|
50
|
+
list(path?: string): Promise<DriveListResponse>;
|
|
51
|
+
/**
|
|
52
|
+
* Upload a single file
|
|
53
|
+
*/
|
|
54
|
+
uploadFile(file: Buffer | Blob, filename: string, path?: string): Promise<{
|
|
55
|
+
success: boolean;
|
|
56
|
+
message: string;
|
|
57
|
+
files: Array<{
|
|
58
|
+
name: string;
|
|
59
|
+
path: string;
|
|
60
|
+
size: number;
|
|
61
|
+
}>;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Upload multiple files
|
|
65
|
+
*/
|
|
66
|
+
uploadFiles(files: Array<{
|
|
67
|
+
file: Buffer | Blob;
|
|
68
|
+
filename: string;
|
|
69
|
+
}>, path?: string): Promise<{
|
|
70
|
+
success: boolean;
|
|
71
|
+
message: string;
|
|
72
|
+
files: Array<{
|
|
73
|
+
name: string;
|
|
74
|
+
path: string;
|
|
75
|
+
size: number;
|
|
76
|
+
}>;
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Download a file
|
|
80
|
+
*/
|
|
81
|
+
download(path: string): Promise<Buffer>;
|
|
82
|
+
/**
|
|
83
|
+
* Delete a file or directory
|
|
84
|
+
*/
|
|
85
|
+
delete(path: string): Promise<{
|
|
86
|
+
success: boolean;
|
|
87
|
+
message: string;
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* Create a directory
|
|
91
|
+
*/
|
|
92
|
+
createDirectory(name: string, path?: string): Promise<{
|
|
93
|
+
success: boolean;
|
|
94
|
+
message: string;
|
|
95
|
+
path: string;
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Rename a file or directory
|
|
99
|
+
*/
|
|
100
|
+
rename(oldPath: string, newName: string): Promise<{
|
|
101
|
+
success: boolean;
|
|
102
|
+
message: string;
|
|
103
|
+
}>;
|
|
104
|
+
/**
|
|
105
|
+
* Move a file or directory
|
|
106
|
+
*/
|
|
107
|
+
move(sourcePath: string, destPath: string): Promise<{
|
|
108
|
+
success: boolean;
|
|
109
|
+
message: string;
|
|
110
|
+
}>;
|
|
111
|
+
/**
|
|
112
|
+
* Get storage statistics
|
|
113
|
+
*/
|
|
114
|
+
getStats(): Promise<DriveStatsResponse>;
|
|
115
|
+
/**
|
|
116
|
+
* Create a public sharing link for a file
|
|
117
|
+
*/
|
|
118
|
+
createPublicLink(filePath: string, expiresInDays?: number): Promise<PublicLinkResponse>;
|
|
119
|
+
/**
|
|
120
|
+
* List all public links
|
|
121
|
+
*/
|
|
122
|
+
listPublicLinks(): Promise<PublicLinksListResponse>;
|
|
123
|
+
/**
|
|
124
|
+
* Revoke a public link
|
|
125
|
+
*/
|
|
126
|
+
revokePublicLink(linkId: string): Promise<{
|
|
127
|
+
success: boolean;
|
|
128
|
+
message: string;
|
|
129
|
+
}>;
|
|
130
|
+
/**
|
|
131
|
+
* Get public file URL (for direct access without authentication)
|
|
132
|
+
* Note: This requires the baseURL from the SDK configuration to construct the full URL
|
|
133
|
+
*/
|
|
134
|
+
getPublicFileUrl(linkId: string, baseURL?: string): string;
|
|
135
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DriveModule = void 0;
|
|
7
|
+
const form_data_1 = __importDefault(require("form-data"));
|
|
8
|
+
class DriveModule {
|
|
9
|
+
constructor(client) {
|
|
10
|
+
this.client = client;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* List files and folders in the specified directory
|
|
14
|
+
*/
|
|
15
|
+
async list(path) {
|
|
16
|
+
const url = path ? `/api/v1/drive/list/${encodeURIComponent(path)}` : "/api/v1/drive/list";
|
|
17
|
+
return this.client.get(url);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Upload a single file
|
|
21
|
+
*/
|
|
22
|
+
async uploadFile(file, filename, path) {
|
|
23
|
+
const formData = new form_data_1.default();
|
|
24
|
+
formData.append("file", file, filename);
|
|
25
|
+
const url = path ? `/api/v1/drive/upload/${encodeURIComponent(path)}` : "/api/v1/drive/upload";
|
|
26
|
+
return this.client.post(url, formData, {
|
|
27
|
+
headers: formData.getHeaders(),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Upload multiple files
|
|
32
|
+
*/
|
|
33
|
+
async uploadFiles(files, path) {
|
|
34
|
+
const formData = new form_data_1.default();
|
|
35
|
+
files.forEach(({ file, filename }) => {
|
|
36
|
+
formData.append("files", file, filename);
|
|
37
|
+
});
|
|
38
|
+
const url = path ? `/api/v1/drive/upload/${encodeURIComponent(path)}` : "/api/v1/drive/upload";
|
|
39
|
+
return this.client.post(url, formData, {
|
|
40
|
+
headers: formData.getHeaders(),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Download a file
|
|
45
|
+
*/
|
|
46
|
+
async download(path) {
|
|
47
|
+
const url = `/api/v1/drive/download/${encodeURIComponent(path)}`;
|
|
48
|
+
// Use the internal axios client to handle arraybuffer response
|
|
49
|
+
const response = await this.client.client.get(url, {
|
|
50
|
+
responseType: "arraybuffer",
|
|
51
|
+
});
|
|
52
|
+
return Buffer.from(response.data);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Delete a file or directory
|
|
56
|
+
*/
|
|
57
|
+
async delete(path) {
|
|
58
|
+
const url = `/api/v1/drive/delete/${encodeURIComponent(path)}`;
|
|
59
|
+
return this.client.delete(url);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a directory
|
|
63
|
+
*/
|
|
64
|
+
async createDirectory(name, path) {
|
|
65
|
+
const url = path ? `/api/v1/drive/mkdir/${encodeURIComponent(path)}` : "/api/v1/drive/mkdir";
|
|
66
|
+
return this.client.post(url, { name });
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Rename a file or directory
|
|
70
|
+
*/
|
|
71
|
+
async rename(oldPath, newName) {
|
|
72
|
+
return this.client.post("/api/v1/drive/rename", {
|
|
73
|
+
oldPath,
|
|
74
|
+
newName,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Move a file or directory
|
|
79
|
+
*/
|
|
80
|
+
async move(sourcePath, destPath) {
|
|
81
|
+
return this.client.post("/api/v1/drive/move", {
|
|
82
|
+
sourcePath,
|
|
83
|
+
destPath,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get storage statistics
|
|
88
|
+
*/
|
|
89
|
+
async getStats() {
|
|
90
|
+
return this.client.get("/api/v1/drive/stats");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create a public sharing link for a file
|
|
94
|
+
*/
|
|
95
|
+
async createPublicLink(filePath, expiresInDays) {
|
|
96
|
+
return this.client.post("/api/v1/drive/links", {
|
|
97
|
+
filePath,
|
|
98
|
+
expiresInDays,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* List all public links
|
|
103
|
+
*/
|
|
104
|
+
async listPublicLinks() {
|
|
105
|
+
return this.client.get("/api/v1/drive/links");
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Revoke a public link
|
|
109
|
+
*/
|
|
110
|
+
async revokePublicLink(linkId) {
|
|
111
|
+
return this.client.delete(`/api/v1/drive/links/${linkId}`);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get public file URL (for direct access without authentication)
|
|
115
|
+
* Note: This requires the baseURL from the SDK configuration to construct the full URL
|
|
116
|
+
*/
|
|
117
|
+
getPublicFileUrl(linkId, baseURL) {
|
|
118
|
+
if (baseURL) {
|
|
119
|
+
return `${baseURL}/api/v1/drive/public/${linkId}`;
|
|
120
|
+
}
|
|
121
|
+
// If baseURL is not provided, return relative path
|
|
122
|
+
return `/api/v1/drive/public/${linkId}`;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.DriveModule = DriveModule;
|
package/dist/modules/ipfs.d.ts
CHANGED
|
@@ -3,7 +3,13 @@ export declare class IpfsModule {
|
|
|
3
3
|
private readonly client;
|
|
4
4
|
constructor(client: ApiClient);
|
|
5
5
|
getStatus(): Promise<any>;
|
|
6
|
-
uploadFile(fileBuffer: Buffer, filename: string, contentType: string,
|
|
6
|
+
uploadFile(fileBuffer: Buffer, filename: string, contentType: string, options?: {
|
|
7
|
+
userAddress?: string;
|
|
8
|
+
walletSignature?: string;
|
|
9
|
+
isDealUpload?: boolean;
|
|
10
|
+
encrypted?: boolean;
|
|
11
|
+
encryptionToken?: string;
|
|
12
|
+
}): Promise<any>;
|
|
7
13
|
/**
|
|
8
14
|
* Upload multiple files as a directory to IPFS
|
|
9
15
|
* Maintains directory structure using relative paths
|
|
@@ -17,7 +23,11 @@ export declare class IpfsModule {
|
|
|
17
23
|
filename: string;
|
|
18
24
|
path: string;
|
|
19
25
|
contentType?: string;
|
|
20
|
-
}>,
|
|
26
|
+
}>, options?: {
|
|
27
|
+
userAddress?: string;
|
|
28
|
+
walletSignature?: string;
|
|
29
|
+
isDealUpload?: boolean;
|
|
30
|
+
}): Promise<any>;
|
|
21
31
|
cat(cid: string): Promise<Buffer>;
|
|
22
32
|
/**
|
|
23
33
|
* Cat a file from an IPFS directory using a relative path
|
|
@@ -37,19 +47,29 @@ export declare class IpfsModule {
|
|
|
37
47
|
/**
|
|
38
48
|
* Upload a file using browser FormData (for browser environments)
|
|
39
49
|
* @param file File object from browser File API
|
|
40
|
-
* @param
|
|
50
|
+
* @param options Upload options including authentication
|
|
41
51
|
* @returns Promise with upload result
|
|
42
52
|
*/
|
|
43
|
-
uploadFileBrowser(file: File,
|
|
53
|
+
uploadFileBrowser(file: File, options?: {
|
|
54
|
+
userAddress?: string;
|
|
55
|
+
walletSignature?: string;
|
|
56
|
+
isDealUpload?: boolean;
|
|
57
|
+
encrypted?: boolean;
|
|
58
|
+
encryptionToken?: string;
|
|
59
|
+
}): Promise<any>;
|
|
44
60
|
/**
|
|
45
61
|
* Upload multiple files as a directory using browser FormData (for browser environments)
|
|
46
62
|
* Maintains directory structure using relative paths from File.webkitRelativePath or file.name
|
|
47
63
|
*
|
|
48
64
|
* @param files Array of File objects from browser File API
|
|
49
|
-
* @param
|
|
65
|
+
* @param options Upload options including authentication
|
|
50
66
|
* @returns Promise with directory CID and file information
|
|
51
67
|
*/
|
|
52
|
-
uploadDirectoryBrowser(files: File[],
|
|
68
|
+
uploadDirectoryBrowser(files: File[], options?: {
|
|
69
|
+
userAddress?: string;
|
|
70
|
+
walletSignature?: string;
|
|
71
|
+
isDealUpload?: boolean;
|
|
72
|
+
}): Promise<any>;
|
|
53
73
|
/**
|
|
54
74
|
* Cat a file and return as Blob (for browser environments)
|
|
55
75
|
* @param cid The CID of the file
|
package/dist/modules/ipfs.js
CHANGED
|
@@ -12,17 +12,31 @@ class IpfsModule {
|
|
|
12
12
|
async getStatus() {
|
|
13
13
|
return this.client.get("/api/v1/ipfs/status");
|
|
14
14
|
}
|
|
15
|
-
async uploadFile(fileBuffer, filename, contentType,
|
|
15
|
+
async uploadFile(fileBuffer, filename, contentType, options) {
|
|
16
16
|
const form = new form_data_1.default();
|
|
17
17
|
form.append("file", fileBuffer, {
|
|
18
18
|
filename: filename,
|
|
19
19
|
contentType: contentType,
|
|
20
20
|
});
|
|
21
21
|
const headers = form.getHeaders();
|
|
22
|
-
if (userAddress) {
|
|
23
|
-
headers["x-user-address"] = userAddress;
|
|
22
|
+
if (options?.userAddress) {
|
|
23
|
+
headers["x-user-address"] = options.userAddress;
|
|
24
|
+
}
|
|
25
|
+
if (options?.walletSignature) {
|
|
26
|
+
headers["x-wallet-signature"] = options.walletSignature;
|
|
27
|
+
}
|
|
28
|
+
if (options?.isDealUpload) {
|
|
29
|
+
headers["x-deal-upload"] = "true";
|
|
30
|
+
}
|
|
31
|
+
if (options?.encrypted) {
|
|
32
|
+
form.append("encrypted", "true");
|
|
33
|
+
form.append("encryptionMethod", "SEA");
|
|
34
|
+
if (options.encryptionToken) {
|
|
35
|
+
form.append("encryptionToken", options.encryptionToken);
|
|
36
|
+
}
|
|
24
37
|
}
|
|
25
|
-
|
|
38
|
+
const queryParams = options?.isDealUpload ? "?deal=true" : "";
|
|
39
|
+
return this.client.post(`/api/v1/ipfs/upload${queryParams}`, form, {
|
|
26
40
|
headers: headers,
|
|
27
41
|
});
|
|
28
42
|
}
|
|
@@ -34,7 +48,7 @@ class IpfsModule {
|
|
|
34
48
|
* @param userAddress Optional user address for authentication
|
|
35
49
|
* @returns Promise with directory CID and file information
|
|
36
50
|
*/
|
|
37
|
-
async uploadDirectory(files,
|
|
51
|
+
async uploadDirectory(files, options) {
|
|
38
52
|
if (!files || files.length === 0) {
|
|
39
53
|
throw new Error("At least one file is required for directory upload");
|
|
40
54
|
}
|
|
@@ -47,8 +61,14 @@ class IpfsModule {
|
|
|
47
61
|
});
|
|
48
62
|
});
|
|
49
63
|
const headers = form.getHeaders();
|
|
50
|
-
if (userAddress) {
|
|
51
|
-
headers["x-user-address"] = userAddress;
|
|
64
|
+
if (options?.userAddress) {
|
|
65
|
+
headers["x-user-address"] = options.userAddress;
|
|
66
|
+
}
|
|
67
|
+
if (options?.walletSignature) {
|
|
68
|
+
headers["x-wallet-signature"] = options.walletSignature;
|
|
69
|
+
}
|
|
70
|
+
if (options?.isDealUpload) {
|
|
71
|
+
headers["x-deal-upload"] = "true";
|
|
52
72
|
}
|
|
53
73
|
return this.client.post("/api/v1/ipfs/upload-directory", form, {
|
|
54
74
|
headers: headers,
|
|
@@ -124,18 +144,32 @@ class IpfsModule {
|
|
|
124
144
|
/**
|
|
125
145
|
* Upload a file using browser FormData (for browser environments)
|
|
126
146
|
* @param file File object from browser File API
|
|
127
|
-
* @param
|
|
147
|
+
* @param options Upload options including authentication
|
|
128
148
|
* @returns Promise with upload result
|
|
129
149
|
*/
|
|
130
|
-
async uploadFileBrowser(file,
|
|
150
|
+
async uploadFileBrowser(file, options) {
|
|
131
151
|
const formData = new form_data_1.default();
|
|
132
152
|
formData.append("file", file, file.name);
|
|
133
153
|
const headers = {};
|
|
134
|
-
if (userAddress) {
|
|
135
|
-
headers["x-user-address"] = userAddress;
|
|
154
|
+
if (options?.userAddress) {
|
|
155
|
+
headers["x-user-address"] = options.userAddress;
|
|
156
|
+
}
|
|
157
|
+
if (options?.walletSignature) {
|
|
158
|
+
headers["x-wallet-signature"] = options.walletSignature;
|
|
159
|
+
}
|
|
160
|
+
if (options?.isDealUpload) {
|
|
161
|
+
headers["x-deal-upload"] = "true";
|
|
162
|
+
}
|
|
163
|
+
if (options?.encrypted) {
|
|
164
|
+
formData.append("encrypted", "true");
|
|
165
|
+
formData.append("encryptionMethod", "SEA");
|
|
166
|
+
if (options.encryptionToken) {
|
|
167
|
+
formData.append("encryptionToken", options.encryptionToken);
|
|
168
|
+
}
|
|
136
169
|
}
|
|
170
|
+
const queryParams = options?.isDealUpload ? "?deal=true" : "";
|
|
137
171
|
// Explicitly don't set Content-Type - let browser set it with boundary for FormData
|
|
138
|
-
return this.client.post(
|
|
172
|
+
return this.client.post(`/api/v1/ipfs/upload${queryParams}`, formData, {
|
|
139
173
|
headers: headers,
|
|
140
174
|
// Ensure axios doesn't serialize FormData as JSON
|
|
141
175
|
transformRequest: [(data) => {
|
|
@@ -152,10 +186,10 @@ class IpfsModule {
|
|
|
152
186
|
* Maintains directory structure using relative paths from File.webkitRelativePath or file.name
|
|
153
187
|
*
|
|
154
188
|
* @param files Array of File objects from browser File API
|
|
155
|
-
* @param
|
|
189
|
+
* @param options Upload options including authentication
|
|
156
190
|
* @returns Promise with directory CID and file information
|
|
157
191
|
*/
|
|
158
|
-
async uploadDirectoryBrowser(files,
|
|
192
|
+
async uploadDirectoryBrowser(files, options) {
|
|
159
193
|
if (!files || files.length === 0) {
|
|
160
194
|
throw new Error("At least one file is required for directory upload");
|
|
161
195
|
}
|
|
@@ -167,8 +201,14 @@ class IpfsModule {
|
|
|
167
201
|
formData.append("files", file, relativePath);
|
|
168
202
|
});
|
|
169
203
|
const headers = {};
|
|
170
|
-
if (userAddress) {
|
|
171
|
-
headers["x-user-address"] = userAddress;
|
|
204
|
+
if (options?.userAddress) {
|
|
205
|
+
headers["x-user-address"] = options.userAddress;
|
|
206
|
+
}
|
|
207
|
+
if (options?.walletSignature) {
|
|
208
|
+
headers["x-wallet-signature"] = options.walletSignature;
|
|
209
|
+
}
|
|
210
|
+
if (options?.isDealUpload) {
|
|
211
|
+
headers["x-deal-upload"] = "true";
|
|
172
212
|
}
|
|
173
213
|
// Explicitly don't set Content-Type - let browser set it with boundary for FormData
|
|
174
214
|
return this.client.post("/api/v1/ipfs/upload-directory", formData, {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet utility functions for Shogun Relay SDK
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Message that must be signed for wallet authentication
|
|
6
|
+
*/
|
|
7
|
+
export declare const WALLET_AUTH_MESSAGE = "I Love Shogun";
|
|
8
|
+
/**
|
|
9
|
+
* Generate wallet signature for authentication
|
|
10
|
+
*
|
|
11
|
+
* @param signer - Ethers.js Signer instance or similar that implements signMessage
|
|
12
|
+
* @returns Promise<string> - EIP-191 signature of the auth message
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { ethers } from 'ethers';
|
|
17
|
+
* import { generateWalletSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
18
|
+
*
|
|
19
|
+
* const provider = new ethers.BrowserProvider(window.ethereum);
|
|
20
|
+
* const signer = await provider.getSigner();
|
|
21
|
+
* const signature = await generateWalletSignature(signer);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateWalletSignature(signer: {
|
|
25
|
+
signMessage: (message: string) => Promise<string>;
|
|
26
|
+
}): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Verify wallet signature
|
|
29
|
+
*
|
|
30
|
+
* @param address - Ethereum wallet address
|
|
31
|
+
* @param signature - EIP-191 signature
|
|
32
|
+
* @returns Promise<boolean> - True if signature is valid for the address
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* import { ethers } from 'ethers';
|
|
37
|
+
* import { verifyWalletSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
38
|
+
*
|
|
39
|
+
* const isValid = await verifyWalletSignature(address, signature);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function verifyWalletSignature(address: string, signature: string): Promise<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Get wallet address from signature
|
|
45
|
+
*
|
|
46
|
+
* @param signature - EIP-191 signature
|
|
47
|
+
* @returns Promise<string | null> - Recovered wallet address or null if invalid
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* import { getAddressFromSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
52
|
+
*
|
|
53
|
+
* const address = await getAddressFromSignature(signature);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function getAddressFromSignature(signature: string): Promise<string | null>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Wallet utility functions for Shogun Relay SDK
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.WALLET_AUTH_MESSAGE = void 0;
|
|
40
|
+
exports.generateWalletSignature = generateWalletSignature;
|
|
41
|
+
exports.verifyWalletSignature = verifyWalletSignature;
|
|
42
|
+
exports.getAddressFromSignature = getAddressFromSignature;
|
|
43
|
+
/**
|
|
44
|
+
* Message that must be signed for wallet authentication
|
|
45
|
+
*/
|
|
46
|
+
exports.WALLET_AUTH_MESSAGE = "I Love Shogun";
|
|
47
|
+
/**
|
|
48
|
+
* Generate wallet signature for authentication
|
|
49
|
+
*
|
|
50
|
+
* @param signer - Ethers.js Signer instance or similar that implements signMessage
|
|
51
|
+
* @returns Promise<string> - EIP-191 signature of the auth message
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { ethers } from 'ethers';
|
|
56
|
+
* import { generateWalletSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
57
|
+
*
|
|
58
|
+
* const provider = new ethers.BrowserProvider(window.ethereum);
|
|
59
|
+
* const signer = await provider.getSigner();
|
|
60
|
+
* const signature = await generateWalletSignature(signer);
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
async function generateWalletSignature(signer) {
|
|
64
|
+
return await signer.signMessage(exports.WALLET_AUTH_MESSAGE);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Verify wallet signature
|
|
68
|
+
*
|
|
69
|
+
* @param address - Ethereum wallet address
|
|
70
|
+
* @param signature - EIP-191 signature
|
|
71
|
+
* @returns Promise<boolean> - True if signature is valid for the address
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* import { ethers } from 'ethers';
|
|
76
|
+
* import { verifyWalletSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
77
|
+
*
|
|
78
|
+
* const isValid = await verifyWalletSignature(address, signature);
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
async function verifyWalletSignature(address, signature) {
|
|
82
|
+
try {
|
|
83
|
+
const { ethers } = await Promise.resolve().then(() => __importStar(require("ethers")));
|
|
84
|
+
const recoveredAddress = ethers.verifyMessage(exports.WALLET_AUTH_MESSAGE, signature);
|
|
85
|
+
return recoveredAddress.toLowerCase() === address.toLowerCase();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get wallet address from signature
|
|
93
|
+
*
|
|
94
|
+
* @param signature - EIP-191 signature
|
|
95
|
+
* @returns Promise<string | null> - Recovered wallet address or null if invalid
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* import { getAddressFromSignature } from '@shogun/relay-sdk/utils/wallet';
|
|
100
|
+
*
|
|
101
|
+
* const address = await getAddressFromSignature(signature);
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
async function getAddressFromSignature(signature) {
|
|
105
|
+
try {
|
|
106
|
+
const { ethers } = await Promise.resolve().then(() => __importStar(require("ethers")));
|
|
107
|
+
return ethers.verifyMessage(exports.WALLET_AUTH_MESSAGE, signature);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
package/package.json
CHANGED