shogun-relay-sdk 1.2.10 → 1.3.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 ADDED
@@ -0,0 +1,304 @@
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
+ ## IPFS Operations
80
+
81
+ ### Upload Single File
82
+
83
+ ```typescript
84
+ // Admin upload
85
+ const result = await sdk.ipfs.uploadFile(
86
+ fileBuffer,
87
+ 'example.txt',
88
+ 'text/plain'
89
+ );
90
+
91
+ // User upload with subscription
92
+ const result = await sdk.ipfs.uploadFile(
93
+ fileBuffer,
94
+ 'example.txt',
95
+ 'text/plain',
96
+ {
97
+ userAddress: address,
98
+ walletSignature: signature
99
+ }
100
+ );
101
+
102
+ // Deal upload (no subscription required)
103
+ const result = await sdk.ipfs.uploadFile(
104
+ fileBuffer,
105
+ 'example.txt',
106
+ 'text/plain',
107
+ {
108
+ userAddress: address,
109
+ walletSignature: signature,
110
+ isDealUpload: true
111
+ }
112
+ );
113
+
114
+ // Encrypted upload
115
+ const encryptedResult = await sdk.ipfs.uploadFile(
116
+ fileBuffer,
117
+ 'example.txt',
118
+ 'text/plain',
119
+ {
120
+ userAddress: address,
121
+ walletSignature: signature,
122
+ encrypted: true,
123
+ encryptionToken: signature // Use same signature for encryption
124
+ }
125
+ );
126
+ ```
127
+
128
+ ### Upload Directory
129
+
130
+ ```typescript
131
+ const files = [
132
+ {
133
+ buffer: indexHtmlBuffer,
134
+ filename: 'index.html',
135
+ path: 'index.html',
136
+ contentType: 'text/html'
137
+ },
138
+ {
139
+ buffer: styleCssBuffer,
140
+ filename: 'style.css',
141
+ path: 'css/style.css',
142
+ contentType: 'text/css'
143
+ }
144
+ ];
145
+
146
+ const result = await sdk.ipfs.uploadDirectory(files, {
147
+ userAddress: address,
148
+ walletSignature: signature,
149
+ isDealUpload: true
150
+ });
151
+ ```
152
+
153
+ ### Browser Upload
154
+
155
+ ```typescript
156
+ // Single file
157
+ const fileInput = document.querySelector('input[type="file"]');
158
+ const file = fileInput.files[0];
159
+
160
+ const result = await sdk.ipfs.uploadFileBrowser(file, {
161
+ userAddress: address,
162
+ walletSignature: signature,
163
+ isDealUpload: true
164
+ });
165
+
166
+ // Directory upload
167
+ const directoryInput = document.querySelector('input[type="file"][webkitdirectory]');
168
+ const files = Array.from(directoryInput.files);
169
+
170
+ const result = await sdk.ipfs.uploadDirectoryBrowser(files, {
171
+ userAddress: address,
172
+ walletSignature: signature
173
+ });
174
+ ```
175
+
176
+ ### Retrieve File
177
+
178
+ ```typescript
179
+ // Get file content
180
+ const content = await sdk.ipfs.cat('QmHash...');
181
+
182
+ // Get encrypted file (decrypted)
183
+ const decryptedContent = await sdk.ipfs.catDecrypt(
184
+ 'QmHash...',
185
+ signature, // Encryption token
186
+ address // Optional: for signature verification
187
+ );
188
+ ```
189
+
190
+ ## Storage Deals
191
+
192
+ ### Upload for Deal
193
+
194
+ ```typescript
195
+ const signature = await generateWalletSignature(signer);
196
+
197
+ const result = await sdk.deals.uploadForDeal(
198
+ fileBuffer,
199
+ 'example.txt',
200
+ 'text/plain',
201
+ address,
202
+ signature // Required: wallet signature
203
+ );
204
+ ```
205
+
206
+ ### Create Deal
207
+
208
+ ```typescript
209
+ const deal = await sdk.deals.createDeal({
210
+ cid: 'QmHash...',
211
+ clientAddress: address,
212
+ sizeMB: 10,
213
+ durationDays: 30,
214
+ tier: 'standard'
215
+ });
216
+ ```
217
+
218
+ ## Wallet Utilities
219
+
220
+ The SDK includes utility functions for wallet operations:
221
+
222
+ ```typescript
223
+ import {
224
+ generateWalletSignature,
225
+ verifyWalletSignature,
226
+ getAddressFromSignature,
227
+ WALLET_AUTH_MESSAGE
228
+ } from '@shogun/relay-sdk/utils/wallet';
229
+
230
+ // Generate signature
231
+ const signature = await generateWalletSignature(signer);
232
+
233
+ // Verify signature
234
+ const isValid = await verifyWalletSignature(address, signature);
235
+
236
+ // Get address from signature
237
+ const recoveredAddress = await getAddressFromSignature(signature);
238
+
239
+ // The message that must be signed
240
+ console.log(WALLET_AUTH_MESSAGE); // "I Love Shogun"
241
+ ```
242
+
243
+ ## Complete Example
244
+
245
+ ```typescript
246
+ import ShogunRelaySDK from '@shogun/relay-sdk';
247
+ import { generateWalletSignature } from '@shogun/relay-sdk/utils/wallet';
248
+ import { ethers } from 'ethers';
249
+ import fs from 'fs';
250
+
251
+ async function uploadFileExample() {
252
+ // Initialize SDK
253
+ const sdk = new ShogunRelaySDK({
254
+ baseURL: 'https://shogun-relay.scobrudot.dev'
255
+ });
256
+
257
+ // Connect wallet
258
+ const provider = new ethers.BrowserProvider(window.ethereum);
259
+ const signer = await provider.getSigner();
260
+ const address = await signer.getAddress();
261
+
262
+ // Generate signature for authentication
263
+ const signature = await generateWalletSignature(signer);
264
+
265
+ // Read file
266
+ const fileBuffer = fs.readFileSync('example.txt');
267
+
268
+ // Upload as deal (no subscription required)
269
+ const result = await sdk.ipfs.uploadFile(
270
+ fileBuffer,
271
+ 'example.txt',
272
+ 'text/plain',
273
+ {
274
+ userAddress: address,
275
+ walletSignature: signature,
276
+ isDealUpload: true
277
+ }
278
+ );
279
+
280
+ console.log('Uploaded! CID:', result.cid);
281
+ return result;
282
+ }
283
+ ```
284
+
285
+ ## API Reference
286
+
287
+ See the main [API Documentation](../docs/API.md) for complete endpoint reference.
288
+
289
+ ## Modules
290
+
291
+ - **System**: Health checks, stats, system information
292
+ - **IPFS**: File uploads, directory uploads, content retrieval, pinning
293
+ - **Deals**: Storage deal creation, activation, management
294
+ - **Registry**: On-chain relay registry operations
295
+ - **Network**: Network federation, reputation, relay discovery
296
+ - **X402**: Subscription management, storage limits
297
+ - **Bridge**: L2 bridge operations, deposits, withdrawals
298
+ - **Uploads**: User upload metadata management
299
+ - **AnnasArchive**: Torrent and archive management
300
+
301
+ ## License
302
+
303
+ MIT
304
+
package/dist/index.d.ts CHANGED
@@ -7,7 +7,10 @@ import { DealsModule } from "./modules/deals";
7
7
  import { RegistryModule } from "./modules/registry";
8
8
  import { UploadsModule } from "./modules/uploads";
9
9
  import { BridgeModule } from "./modules/bridge";
10
+ import { AnnasArchiveModule } from "./modules/annas-archive";
10
11
  export * from "./types";
12
+ export * from "./modules/annas-archive";
13
+ export * from "./utils/wallet";
11
14
  export declare class ShogunRelaySDK {
12
15
  private client;
13
16
  system: SystemModule;
@@ -18,6 +21,7 @@ export declare class ShogunRelaySDK {
18
21
  registry: RegistryModule;
19
22
  uploads: UploadsModule;
20
23
  bridge: BridgeModule;
24
+ annasArchive: AnnasArchiveModule;
21
25
  constructor(config: ApiClientConfig);
22
26
  setToken(token: string): void;
23
27
  }
package/dist/index.js CHANGED
@@ -24,8 +24,12 @@ const deals_1 = require("./modules/deals");
24
24
  const registry_1 = require("./modules/registry");
25
25
  const uploads_1 = require("./modules/uploads");
26
26
  const bridge_1 = require("./modules/bridge");
27
+ const annas_archive_1 = require("./modules/annas-archive");
27
28
  // Export types
28
29
  __exportStar(require("./types"), exports);
30
+ __exportStar(require("./modules/annas-archive"), exports);
31
+ // Export wallet utilities
32
+ __exportStar(require("./utils/wallet"), exports);
29
33
  class ShogunRelaySDK {
30
34
  constructor(config) {
31
35
  this.client = new client_1.ApiClient(config);
@@ -37,6 +41,7 @@ class ShogunRelaySDK {
37
41
  this.registry = new registry_1.RegistryModule(this.client);
38
42
  this.uploads = new uploads_1.UploadsModule(this.client);
39
43
  this.bridge = new bridge_1.BridgeModule(this.client);
44
+ this.annasArchive = new annas_archive_1.AnnasArchiveModule(this.client);
40
45
  }
41
46
  setToken(token) {
42
47
  this.client.setToken(token);
@@ -0,0 +1,35 @@
1
+ import { ApiClient } from "../client";
2
+ export interface AnnasArchiveStatus {
3
+ enabled: boolean;
4
+ activeTorrents: number;
5
+ downloadSpeed: number;
6
+ uploadSpeed: number;
7
+ ratio: number;
8
+ torrents: {
9
+ infoHash: string;
10
+ name: string;
11
+ progress: number;
12
+ downloadSpeed: number;
13
+ uploadSpeed: number;
14
+ peers: number;
15
+ }[];
16
+ }
17
+ export declare class AnnasArchiveModule {
18
+ private client;
19
+ constructor(client: ApiClient);
20
+ /**
21
+ * Get Anna's Archive integration status
22
+ */
23
+ getStatus(): Promise<{
24
+ success: boolean;
25
+ data: AnnasArchiveStatus;
26
+ }>;
27
+ /**
28
+ * Add a manual torrent
29
+ * @param magnet Magnet link or URL
30
+ */
31
+ addTorrent(magnet: string): Promise<{
32
+ success: boolean;
33
+ message: string;
34
+ }>;
35
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnnasArchiveModule = void 0;
4
+ class AnnasArchiveModule {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ /**
9
+ * Get Anna's Archive integration status
10
+ */
11
+ async getStatus() {
12
+ return this.client.get("/api/v1/annas-archive/status");
13
+ }
14
+ /**
15
+ * Add a manual torrent
16
+ * @param magnet Magnet link or URL
17
+ */
18
+ async addTorrent(magnet) {
19
+ return this.client.post("/api/v1/annas-archive/add", { magnet });
20
+ }
21
+ }
22
+ exports.AnnasArchiveModule = AnnasArchiveModule;
@@ -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;
@@ -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-wallet-address": walletAddress,
31
+ "x-user-address": walletAddress,
32
+ "x-wallet-signature": walletSignature,
33
+ "x-deal-upload": "true",
32
34
  },
33
35
  });
34
36
  }
@@ -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, userAddress?: string): Promise<any>;
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
- }>, userAddress?: string): Promise<any>;
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 userAddress Optional user address for authentication
50
+ * @param options Upload options including authentication
41
51
  * @returns Promise with upload result
42
52
  */
43
- uploadFileBrowser(file: File, userAddress?: string): Promise<any>;
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 userAddress Optional user address for authentication
65
+ * @param options Upload options including authentication
50
66
  * @returns Promise with directory CID and file information
51
67
  */
52
- uploadDirectoryBrowser(files: File[], userAddress?: string): Promise<any>;
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
@@ -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, userAddress) {
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
- return this.client.post("/api/v1/ipfs/upload", form, {
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, userAddress) {
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 userAddress Optional user address for authentication
147
+ * @param options Upload options including authentication
128
148
  * @returns Promise with upload result
129
149
  */
130
- async uploadFileBrowser(file, userAddress) {
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("/api/v1/ipfs/upload", formData, {
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 userAddress Optional user address for authentication
189
+ * @param options Upload options including authentication
156
190
  * @returns Promise with directory CID and file information
157
191
  */
158
- async uploadDirectoryBrowser(files, userAddress) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shogun-relay-sdk",
3
- "version": "1.2.10",
3
+ "version": "1.3.0",
4
4
  "description": "SDK for interacting with Shogun Relay API - HTTP client for IPFS, deals, registry, and network operations",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",