@tuwaio/quasar-sdk 1.0.0-fix-docs-alpha.7.481db45 → 1.0.0-fix-docs-alpha.8.45d929e

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/dist/index.d.mts CHANGED
@@ -7,135 +7,63 @@ import * as zustand from 'zustand';
7
7
  /**
8
8
  * @module types
9
9
  * @description Shared type definitions for the Quasar SDK.
10
- * Contains configuration interfaces, query parameters, paginated result structure,
11
- * and re-exports from `@tuwaio/pulsar-core`.
10
+ * Contains configuration interfaces, query parameters, and authentication structures.
12
11
  */
13
12
 
14
13
  /**
15
14
  * Configuration options for initializing the {@link Quasar} SDK client.
16
15
  *
17
16
  * @public
18
- * @example
19
- * ```typescript
20
- * const config: QuasarConfig = {
21
- * secretKey: 'sk_live_abc123...',
22
- * baseUrl: 'https://api.tuwa.io',
23
- * timeout: 15000,
24
- * };
25
- * ```
26
17
  */
27
18
  interface QuasarConfig {
28
- /**
29
- * Your secret API key starting with `sk_live_`.
30
- *
31
- * @remarks
32
- * This key authenticates every request through the Iron Dome security perimeter.
33
- * It **MUST** be kept secure on the server side — never expose it in client-side bundles
34
- * as it grants full access to your organization's Quasar data.
35
- */
19
+ /** Your secret API key starting with `sk_live_`. */
36
20
  secretKey: string;
37
- /**
38
- * Optional internal secret sent as `x-internal-secret` header on every request.
39
- *
40
- * @remarks
41
- * This is used for system-to-system communication between TUWA internal services.
42
- * Most third-party developers do not need to provide this.
43
- */
21
+ /** Optional internal secret for system-to-system communication. */
44
22
  internalSecret?: string;
45
- /**
46
- * The base URL of the Quasar Cloud API.
47
- *
48
- * @defaultValue `'https://api.tuwa.io'`
49
- */
23
+ /** The base URL of the Quasar Cloud API. Defaults to 'https://api.tuwa.io'. */
50
24
  baseUrl?: string;
51
- /**
52
- * Request timeout in milliseconds for all API calls.
53
- *
54
- * @defaultValue `10000` (10 seconds)
55
- */
25
+ /** Request timeout in milliseconds. Defaults to 10000. */
56
26
  timeout?: number;
57
27
  }
58
28
  /**
59
29
  * Query parameters for filtering and paginating transaction history.
60
30
  *
61
- * All fields are optional. When omitted, no filtering is applied to that field.
62
- *
63
31
  * @public
64
- * @example
65
- * ```typescript
66
- * const query: HistoryQuery = {
67
- * page: 1,
68
- * limit: 10,
69
- * chainId: 1, // Ethereum Mainnet
70
- * status: 'Success', // Only successful transactions
71
- * appName: 'Tuwa App', // Filter by application
72
- * };
73
- * ```
74
32
  */
75
33
  interface HistoryQuery {
76
- /**
77
- * Page number for pagination (1-indexed).
78
- *
79
- * @defaultValue `1`
80
- */
34
+ /** Page number for pagination (1-indexed). */
81
35
  page?: number;
82
- /**
83
- * Maximum number of results to return per page.
84
- *
85
- * @defaultValue `10`
86
- */
36
+ /** Maximum number of results to return per page. */
87
37
  limit?: number;
88
- /**
89
- * Filter by blockchain chain ID.
90
- *
91
- * @example `1` (Ethereum), `'solana'`, `'SN_MAIN'` (Starknet)
92
- */
38
+ /** Filter by blockchain chain ID (e.g., 1, 'solana'). */
93
39
  chainId?: string | number;
94
- /**
95
- * Filter by transaction status.
96
- *
97
- * @example `'pending'`, `'Success'`, `'Failed'`, `'Replaced'`
98
- */
40
+ /** Filter by transaction status (e.g., 'Success', 'Failed'). */
99
41
  status?: string;
100
- /**
101
- * Filter by a specific unique transaction key assigned by Quasar.
102
- */
42
+ /** Filter by a specific Quasar transaction key. */
103
43
  txKey?: string;
104
- /**
105
- * Filter by the application name that synced the transaction.
106
- */
44
+ /** Filter by the application name. */
107
45
  appName?: string;
108
- /**
109
- * Filter by the sender's wallet address.
110
- */
46
+ /** Filter by the sender's wallet address. */
111
47
  walletAddress?: string;
112
48
  }
113
49
  /**
114
50
  * Generic wrapper for paginated API responses.
115
51
  *
116
52
  * @typeParam T - The type of the documents contained in the result set.
117
- *
118
53
  * @public
119
- * @example
120
- * ```typescript
121
- * const result: PaginatedResult<Transaction> = await quasar.pulsar.getHistory();
122
- *
123
- * console.log(`Showing page ${result.page} of ${result.totalPages}`);
124
- * console.log(`Total transactions found: ${result.totalDocs}`);
125
- * ```
126
54
  */
127
55
  interface PaginatedResult<T> {
128
56
  /** Array of documents for the current page. */
129
57
  docs: T[];
130
- /** Total number of documents matching the query across all pages. */
58
+ /** Total number of documents matching the query. */
131
59
  totalDocs: number;
132
- /** Total number of available pages based on the limit. */
60
+ /** Total number of available pages. */
133
61
  totalPages: number;
134
62
  /** The current page number (1-indexed). */
135
63
  page: number;
136
- /** Indicates if a subsequent page of results is available. */
64
+ /** Indicates if a subsequent page is available. */
137
65
  hasNextPage: boolean;
138
- /** Indicates if a preceding page of results is available. */
66
+ /** Indicates if a preceding page is available. */
139
67
  hasPrevPage: boolean;
140
68
  }
141
69
 
@@ -144,19 +72,27 @@ interface PaginatedResult<T> {
144
72
  * @public
145
73
  */
146
74
  declare enum ChainType {
75
+ /** Ethereum and compatible L2s. */
147
76
  EVM = "EVM",
77
+ /** Solana blockchain. */
148
78
  SOLANA = "SOLANA"
149
79
  }
150
80
  /**
151
- * Result of the Mini-Session signing process.
152
- * Used for both frontend-side caching and backend-side verification.
81
+ * Result structure for a signed message.
153
82
  * @public
154
83
  */
155
- interface MiniSessionAuth {
156
- /** The cryptographic signature (hex for EVM, base58 for Solana). */
84
+ interface SignSessionResult {
85
+ /** The cryptographic signature string. */
157
86
  signature: string;
158
- /** ISO string timestamp used in the signed message. */
87
+ /** The ISO timestamp used to generate the message. */
159
88
  timestamp: string;
89
+ }
90
+ /**
91
+ * Result of the Mini-Session signing process.
92
+ * Used for both frontend-side caching and backend-side verification.
93
+ * @public
94
+ */
95
+ interface MiniSessionAuth extends SignSessionResult {
160
96
  /** The blockchain ecosystem type. */
161
97
  chainType: ChainType;
162
98
  /** The wallet address that signed the message. */
@@ -169,26 +105,67 @@ interface MiniSessionAuth {
169
105
  interface VerifySessionParams extends Omit<MiniSessionAuth, 'walletAddress'> {
170
106
  /** The wallet address that allegedly signed the message. */
171
107
  walletAddress: string;
108
+ /** Maximum allowed age for the signature in milliseconds. Defaults to 5 minutes. */
109
+ maxAge?: number;
110
+ }
111
+ /**
112
+ * Interface for an EVM signer (compatible with Viem WalletClient).
113
+ * @public
114
+ */
115
+ interface EvmSigner {
116
+ /** Signs a message using the specified account. */
117
+ signMessage: (params: {
118
+ account: `0x${string}`;
119
+ message: string;
120
+ }) => Promise<`0x${string}`>;
121
+ }
122
+ /**
123
+ * Result structure for a signed Solana message in Web3 v2.
124
+ * @public
125
+ */
126
+ interface SolanaSignedMessage {
127
+ /** A map of public addresses to their corresponding signature bytes. */
128
+ readonly signatures: Readonly<Record<string, Uint8Array>>;
129
+ }
130
+ /**
131
+ * Interface for a Solana signer.
132
+ * Optimized to handle modern Web3 v2 (MessageModifyingSigner), Standard, and Legacy interfaces.
133
+ * @public
134
+ */
135
+ interface SolanaSigner {
136
+ /** The public address of the signer. */
137
+ readonly address: string;
172
138
  /**
173
- * Maximum allowed age for the signature in milliseconds.
174
- * Default: 5 minutes (300,000ms).
139
+ * Modern Web3 v2 method to modify and sign messages.
140
+ * Used by latest @solana/react hooks.
175
141
  */
176
- maxAge?: number;
142
+ modifyAndSignMessages?: (messages: readonly unknown[]) => Promise<readonly SolanaSignedMessage[]>;
143
+ /**
144
+ * Plural signing method (Wallet Standard).
145
+ */
146
+ signMessages?: (messages: readonly Uint8Array[]) => Promise<readonly {
147
+ signature: Uint8Array;
148
+ }[]>;
149
+ /**
150
+ * Singular signing method (Legacy).
151
+ */
152
+ signMessage?: (message: Uint8Array) => Promise<Uint8Array>;
177
153
  }
178
154
  /**
179
155
  * Parameters for signing a mini-session message.
180
156
  * @public
181
157
  */
182
158
  interface SignSessionParams {
183
- /** The signer object. For EVM, a `WalletClient`. For Solana, a `KeyPairSigner` or `TransactionSendingSigner`. */
184
- signer: any;
185
- /** The wallet address to sign with (required for EVM). */
186
- walletAddress?: string;
159
+ /** The signer object for the respective ecosystem. */
160
+ signer: EvmSigner | SolanaSigner;
161
+ /** The wallet address to sign with. */
162
+ walletAddress: string;
187
163
  /** The blockchain ecosystem type. */
188
164
  chainType: ChainType;
189
165
  }
190
166
  /**
191
- * Zustand store interface for managing Mini-Sessions.
167
+ * Interface for a store that manages Mini-Session persistence.
168
+ * Designed to be compatible with Zustand.
192
169
  * @public
193
170
  */
194
171
  interface MiniSessionStore {
@@ -210,8 +187,8 @@ interface ConnectionData {
210
187
  address: string;
211
188
  /** The blockchain ecosystem type. */
212
189
  chainType: ChainType;
213
- /** The wallet signer object (WalletClient for EVM, TransactionSendingSigner for Solana). */
214
- signer: any;
190
+ /** The wallet signer object. */
191
+ signer: EvmSigner | SolanaSigner;
215
192
  }
216
193
 
217
194
  /**
@@ -406,12 +383,19 @@ declare class PulsarModule {
406
383
 
407
384
  /**
408
385
  * @module utils/auth
409
- * @description Security utilities for Mini-Session signature verification.
386
+ * @description Security utilities for Mini-Session signature creation and verification.
387
+ * Supports dual-ecosystem (EVM & Solana) authentication flows with strict type safety.
410
388
  */
411
389
 
412
390
  /**
413
- * Standardizes the message format for Mini-Session login.
414
- * Both frontend and backend must use this exact template.
391
+ * Default maximum allowed age for a signature (5 minutes).
392
+ * Prevents replay attacks using stale signatures.
393
+ * @internal
394
+ */
395
+ declare const DEFAULT_MAX_AGE: number;
396
+ /**
397
+ * Standardizes the message format for Mini-Session authentication.
398
+ * Both frontend and backend MUST use this exact template for verification to pass.
415
399
  *
416
400
  * @param timestamp - ISO string timestamp (e.g., `new Date().toISOString()`).
417
401
  * @returns The formatted message string to be signed.
@@ -423,50 +407,40 @@ declare class PulsarModule {
423
407
  * ```
424
408
  */
425
409
  declare function createMiniSessionMessage(timestamp: string): string;
426
- /**
427
- * Result of a mini-session signing operation.
428
- */
429
- interface SignSessionResult {
430
- /** The cryptographic signature. */
431
- signature: string;
432
- /** The ISO timestamp used to generate the message. */
433
- timestamp: string;
434
- }
435
410
  /**
436
411
  * Triggers a signature request in the connected wallet to create a Mini-Session.
437
412
  *
438
- * This is a frontend-friendly helper that:
439
- * 1. Generates a fresh ISO timestamp.
440
- * 2. Formats the standard login message.
441
- * 3. Triggers the wallet's signMessage method.
442
- * 4. Returns the signature and timestamp for verification on the backend.
413
+ * This function detects the signer's capabilities and uses the most appropriate
414
+ * signing method available (e.g., Web3 v2, Standard, or Legacy).
415
+ *
416
+ * @param params - Parameters containing the signer and target ecosystem.
417
+ * @returns A promise resolving to the signature and timestamp.
418
+ * @throws {Error} If signing fails or the signer lacks required methods.
443
419
  *
444
- * @param params - The signing parameters including the signer and ecosystem type.
445
- * @returns A promise that resolves to the signature and timestamp.
446
- * @throws {Error} If the required peer dependencies are missing or signing fails.
420
+ * @public
447
421
  */
448
422
  declare function signMiniSession(params: SignSessionParams): Promise<SignSessionResult>;
449
423
  /**
450
- * Verifies a Mini-Session signature to protect API quota from unauthorized access.
424
+ * Verifies a Mini-Session signature for authenticity and freshness.
425
+ *
426
+ * Performs cryptographic verification against the provided wallet address and
427
+ * ensures the signature hasn't expired according to the `maxAge` parameter.
451
428
  *
452
- * This utility performs three checks:
453
- * 1. Timestamp freshness (rejects if older than 5 minutes or in the future).
454
- * 2. Cryptographic validity (checks if the signature matches the wallet address and message).
455
- * 3. Ecosystem-specific logic (EVM via `viem`, Solana via `gill`).
429
+ * @param params - Verification data including signature and timestamp.
430
+ * @returns A promise resolving to true if the session is valid.
456
431
  *
457
- * @param params - The verification parameters including address, signature, and timestamp.
458
- * @returns A promise that resolves to `true` if the signature is valid and fresh.
459
- * @throws {Error} If the required peer dependencies (`viem` or `gill`) are missing.
460
- * @throws {Error} If the timestamp is invalid or expired.
432
+ * @public
461
433
  */
462
434
  declare function verifyMiniSession(params: VerifySessionParams): Promise<boolean>;
463
435
 
464
436
  /**
465
437
  * Creates a persistent Zustand store to cache Mini-Session signatures.
466
- * Requires `zustand` to be installed as a peer dependency.
438
+ * This is the recommended way to manage sessions in React applications.
467
439
  *
468
- * @param storageName - Key name for localStorage persistence.
469
- * @returns A Zustand store instance.
440
+ * @param storageName - The localStorage key for persistence. Defaults to 'mini-session-storage'.
441
+ * @returns A Zustand store instance initialized with MiniSessionStore interface.
442
+ *
443
+ * @public
470
444
  */
471
445
  declare function createMiniSessionStore(storageName?: string): zustand.UseBoundStore<Omit<zustand.StoreApi<MiniSessionStore>, "setState" | "persist"> & {
472
446
  setState(partial: MiniSessionStore | Partial<MiniSessionStore> | ((state: MiniSessionStore) => MiniSessionStore | Partial<MiniSessionStore>), replace?: false | undefined): unknown;
@@ -482,19 +456,22 @@ declare function createMiniSessionStore(storageName?: string): zustand.UseBoundS
482
456
  };
483
457
  }>;
484
458
  /**
485
- * Generic helper to manage Mini-Session signing and caching.
459
+ * High-level orchestrator to retrieve an existing Mini-Session or trigger a new signature.
460
+ *
461
+ * This function checks the provided store for a valid, non-expired session matching
462
+ * the current wallet connection. If no session is found or it has expired, it
463
+ * triggers a signature request through the wallet.
486
464
  *
487
- * Checks the provided store for an existing session matching the current connection.
488
- * If no session is found, it triggers a signature request using the provided signer.
465
+ * @param connection - The current active wallet connection data (address, signer, etc).
466
+ * @param store - A store implementation (Zustand or compatible) for session persistence.
467
+ * @returns A promise resolving to a valid MiniSessionAuth object.
468
+ * @throws {Error} If the wallet is disconnected or signing fails.
489
469
  *
490
- * @param connection - Current active connection state.
491
- * @param store - An object compatible with MiniSessionStore to read/write the session.
492
- * @returns A promise resolving to the authenticated session.
493
- * @throws {Error} If no wallet is connected or signing fails.
470
+ * @public
494
471
  */
495
472
  declare function getMiniSessionAuth(connection: ConnectionData, store: {
496
473
  miniSession: MiniSessionAuth | null;
497
- setMiniSession: (s: MiniSessionAuth) => void;
474
+ setMiniSession: (session: MiniSessionAuth | null) => void;
498
475
  }): Promise<MiniSessionAuth>;
499
476
 
500
477
  declare const BASE_API_URL = "https://api.tuwa.io";
@@ -639,4 +616,4 @@ declare class Quasar {
639
616
  constructor(config: QuasarConfig);
640
617
  }
641
618
 
642
- export { BASE_API_URL, ChainType, type ConnectionData, type HistoryQuery, type MiniSessionAuth, type MiniSessionStore, PULSAR_HISTORY_ENDPOINT, PULSAR_SYNC_ENDPOINT, type PaginatedResult, PulsarModule, Quasar, type QuasarConfig, QuasarSDKError, type SignSessionParams, type SignSessionResult, type VerifySessionParams, createMiniSessionMessage, createMiniSessionStore, getMiniSessionAuth, signMiniSession, utils, verifyMiniSession };
619
+ export { BASE_API_URL, ChainType, type ConnectionData, DEFAULT_MAX_AGE, type EvmSigner, type HistoryQuery, type MiniSessionAuth, type MiniSessionStore, PULSAR_HISTORY_ENDPOINT, PULSAR_SYNC_ENDPOINT, type PaginatedResult, PulsarModule, Quasar, type QuasarConfig, QuasarSDKError, type SignSessionParams, type SignSessionResult, type SolanaSignedMessage, type SolanaSigner, type VerifySessionParams, createMiniSessionMessage, createMiniSessionStore, getMiniSessionAuth, signMiniSession, utils, verifyMiniSession };
package/dist/index.d.ts CHANGED
@@ -7,135 +7,63 @@ import * as zustand from 'zustand';
7
7
  /**
8
8
  * @module types
9
9
  * @description Shared type definitions for the Quasar SDK.
10
- * Contains configuration interfaces, query parameters, paginated result structure,
11
- * and re-exports from `@tuwaio/pulsar-core`.
10
+ * Contains configuration interfaces, query parameters, and authentication structures.
12
11
  */
13
12
 
14
13
  /**
15
14
  * Configuration options for initializing the {@link Quasar} SDK client.
16
15
  *
17
16
  * @public
18
- * @example
19
- * ```typescript
20
- * const config: QuasarConfig = {
21
- * secretKey: 'sk_live_abc123...',
22
- * baseUrl: 'https://api.tuwa.io',
23
- * timeout: 15000,
24
- * };
25
- * ```
26
17
  */
27
18
  interface QuasarConfig {
28
- /**
29
- * Your secret API key starting with `sk_live_`.
30
- *
31
- * @remarks
32
- * This key authenticates every request through the Iron Dome security perimeter.
33
- * It **MUST** be kept secure on the server side — never expose it in client-side bundles
34
- * as it grants full access to your organization's Quasar data.
35
- */
19
+ /** Your secret API key starting with `sk_live_`. */
36
20
  secretKey: string;
37
- /**
38
- * Optional internal secret sent as `x-internal-secret` header on every request.
39
- *
40
- * @remarks
41
- * This is used for system-to-system communication between TUWA internal services.
42
- * Most third-party developers do not need to provide this.
43
- */
21
+ /** Optional internal secret for system-to-system communication. */
44
22
  internalSecret?: string;
45
- /**
46
- * The base URL of the Quasar Cloud API.
47
- *
48
- * @defaultValue `'https://api.tuwa.io'`
49
- */
23
+ /** The base URL of the Quasar Cloud API. Defaults to 'https://api.tuwa.io'. */
50
24
  baseUrl?: string;
51
- /**
52
- * Request timeout in milliseconds for all API calls.
53
- *
54
- * @defaultValue `10000` (10 seconds)
55
- */
25
+ /** Request timeout in milliseconds. Defaults to 10000. */
56
26
  timeout?: number;
57
27
  }
58
28
  /**
59
29
  * Query parameters for filtering and paginating transaction history.
60
30
  *
61
- * All fields are optional. When omitted, no filtering is applied to that field.
62
- *
63
31
  * @public
64
- * @example
65
- * ```typescript
66
- * const query: HistoryQuery = {
67
- * page: 1,
68
- * limit: 10,
69
- * chainId: 1, // Ethereum Mainnet
70
- * status: 'Success', // Only successful transactions
71
- * appName: 'Tuwa App', // Filter by application
72
- * };
73
- * ```
74
32
  */
75
33
  interface HistoryQuery {
76
- /**
77
- * Page number for pagination (1-indexed).
78
- *
79
- * @defaultValue `1`
80
- */
34
+ /** Page number for pagination (1-indexed). */
81
35
  page?: number;
82
- /**
83
- * Maximum number of results to return per page.
84
- *
85
- * @defaultValue `10`
86
- */
36
+ /** Maximum number of results to return per page. */
87
37
  limit?: number;
88
- /**
89
- * Filter by blockchain chain ID.
90
- *
91
- * @example `1` (Ethereum), `'solana'`, `'SN_MAIN'` (Starknet)
92
- */
38
+ /** Filter by blockchain chain ID (e.g., 1, 'solana'). */
93
39
  chainId?: string | number;
94
- /**
95
- * Filter by transaction status.
96
- *
97
- * @example `'pending'`, `'Success'`, `'Failed'`, `'Replaced'`
98
- */
40
+ /** Filter by transaction status (e.g., 'Success', 'Failed'). */
99
41
  status?: string;
100
- /**
101
- * Filter by a specific unique transaction key assigned by Quasar.
102
- */
42
+ /** Filter by a specific Quasar transaction key. */
103
43
  txKey?: string;
104
- /**
105
- * Filter by the application name that synced the transaction.
106
- */
44
+ /** Filter by the application name. */
107
45
  appName?: string;
108
- /**
109
- * Filter by the sender's wallet address.
110
- */
46
+ /** Filter by the sender's wallet address. */
111
47
  walletAddress?: string;
112
48
  }
113
49
  /**
114
50
  * Generic wrapper for paginated API responses.
115
51
  *
116
52
  * @typeParam T - The type of the documents contained in the result set.
117
- *
118
53
  * @public
119
- * @example
120
- * ```typescript
121
- * const result: PaginatedResult<Transaction> = await quasar.pulsar.getHistory();
122
- *
123
- * console.log(`Showing page ${result.page} of ${result.totalPages}`);
124
- * console.log(`Total transactions found: ${result.totalDocs}`);
125
- * ```
126
54
  */
127
55
  interface PaginatedResult<T> {
128
56
  /** Array of documents for the current page. */
129
57
  docs: T[];
130
- /** Total number of documents matching the query across all pages. */
58
+ /** Total number of documents matching the query. */
131
59
  totalDocs: number;
132
- /** Total number of available pages based on the limit. */
60
+ /** Total number of available pages. */
133
61
  totalPages: number;
134
62
  /** The current page number (1-indexed). */
135
63
  page: number;
136
- /** Indicates if a subsequent page of results is available. */
64
+ /** Indicates if a subsequent page is available. */
137
65
  hasNextPage: boolean;
138
- /** Indicates if a preceding page of results is available. */
66
+ /** Indicates if a preceding page is available. */
139
67
  hasPrevPage: boolean;
140
68
  }
141
69
 
@@ -144,19 +72,27 @@ interface PaginatedResult<T> {
144
72
  * @public
145
73
  */
146
74
  declare enum ChainType {
75
+ /** Ethereum and compatible L2s. */
147
76
  EVM = "EVM",
77
+ /** Solana blockchain. */
148
78
  SOLANA = "SOLANA"
149
79
  }
150
80
  /**
151
- * Result of the Mini-Session signing process.
152
- * Used for both frontend-side caching and backend-side verification.
81
+ * Result structure for a signed message.
153
82
  * @public
154
83
  */
155
- interface MiniSessionAuth {
156
- /** The cryptographic signature (hex for EVM, base58 for Solana). */
84
+ interface SignSessionResult {
85
+ /** The cryptographic signature string. */
157
86
  signature: string;
158
- /** ISO string timestamp used in the signed message. */
87
+ /** The ISO timestamp used to generate the message. */
159
88
  timestamp: string;
89
+ }
90
+ /**
91
+ * Result of the Mini-Session signing process.
92
+ * Used for both frontend-side caching and backend-side verification.
93
+ * @public
94
+ */
95
+ interface MiniSessionAuth extends SignSessionResult {
160
96
  /** The blockchain ecosystem type. */
161
97
  chainType: ChainType;
162
98
  /** The wallet address that signed the message. */
@@ -169,26 +105,67 @@ interface MiniSessionAuth {
169
105
  interface VerifySessionParams extends Omit<MiniSessionAuth, 'walletAddress'> {
170
106
  /** The wallet address that allegedly signed the message. */
171
107
  walletAddress: string;
108
+ /** Maximum allowed age for the signature in milliseconds. Defaults to 5 minutes. */
109
+ maxAge?: number;
110
+ }
111
+ /**
112
+ * Interface for an EVM signer (compatible with Viem WalletClient).
113
+ * @public
114
+ */
115
+ interface EvmSigner {
116
+ /** Signs a message using the specified account. */
117
+ signMessage: (params: {
118
+ account: `0x${string}`;
119
+ message: string;
120
+ }) => Promise<`0x${string}`>;
121
+ }
122
+ /**
123
+ * Result structure for a signed Solana message in Web3 v2.
124
+ * @public
125
+ */
126
+ interface SolanaSignedMessage {
127
+ /** A map of public addresses to their corresponding signature bytes. */
128
+ readonly signatures: Readonly<Record<string, Uint8Array>>;
129
+ }
130
+ /**
131
+ * Interface for a Solana signer.
132
+ * Optimized to handle modern Web3 v2 (MessageModifyingSigner), Standard, and Legacy interfaces.
133
+ * @public
134
+ */
135
+ interface SolanaSigner {
136
+ /** The public address of the signer. */
137
+ readonly address: string;
172
138
  /**
173
- * Maximum allowed age for the signature in milliseconds.
174
- * Default: 5 minutes (300,000ms).
139
+ * Modern Web3 v2 method to modify and sign messages.
140
+ * Used by latest @solana/react hooks.
175
141
  */
176
- maxAge?: number;
142
+ modifyAndSignMessages?: (messages: readonly unknown[]) => Promise<readonly SolanaSignedMessage[]>;
143
+ /**
144
+ * Plural signing method (Wallet Standard).
145
+ */
146
+ signMessages?: (messages: readonly Uint8Array[]) => Promise<readonly {
147
+ signature: Uint8Array;
148
+ }[]>;
149
+ /**
150
+ * Singular signing method (Legacy).
151
+ */
152
+ signMessage?: (message: Uint8Array) => Promise<Uint8Array>;
177
153
  }
178
154
  /**
179
155
  * Parameters for signing a mini-session message.
180
156
  * @public
181
157
  */
182
158
  interface SignSessionParams {
183
- /** The signer object. For EVM, a `WalletClient`. For Solana, a `KeyPairSigner` or `TransactionSendingSigner`. */
184
- signer: any;
185
- /** The wallet address to sign with (required for EVM). */
186
- walletAddress?: string;
159
+ /** The signer object for the respective ecosystem. */
160
+ signer: EvmSigner | SolanaSigner;
161
+ /** The wallet address to sign with. */
162
+ walletAddress: string;
187
163
  /** The blockchain ecosystem type. */
188
164
  chainType: ChainType;
189
165
  }
190
166
  /**
191
- * Zustand store interface for managing Mini-Sessions.
167
+ * Interface for a store that manages Mini-Session persistence.
168
+ * Designed to be compatible with Zustand.
192
169
  * @public
193
170
  */
194
171
  interface MiniSessionStore {
@@ -210,8 +187,8 @@ interface ConnectionData {
210
187
  address: string;
211
188
  /** The blockchain ecosystem type. */
212
189
  chainType: ChainType;
213
- /** The wallet signer object (WalletClient for EVM, TransactionSendingSigner for Solana). */
214
- signer: any;
190
+ /** The wallet signer object. */
191
+ signer: EvmSigner | SolanaSigner;
215
192
  }
216
193
 
217
194
  /**
@@ -406,12 +383,19 @@ declare class PulsarModule {
406
383
 
407
384
  /**
408
385
  * @module utils/auth
409
- * @description Security utilities for Mini-Session signature verification.
386
+ * @description Security utilities for Mini-Session signature creation and verification.
387
+ * Supports dual-ecosystem (EVM & Solana) authentication flows with strict type safety.
410
388
  */
411
389
 
412
390
  /**
413
- * Standardizes the message format for Mini-Session login.
414
- * Both frontend and backend must use this exact template.
391
+ * Default maximum allowed age for a signature (5 minutes).
392
+ * Prevents replay attacks using stale signatures.
393
+ * @internal
394
+ */
395
+ declare const DEFAULT_MAX_AGE: number;
396
+ /**
397
+ * Standardizes the message format for Mini-Session authentication.
398
+ * Both frontend and backend MUST use this exact template for verification to pass.
415
399
  *
416
400
  * @param timestamp - ISO string timestamp (e.g., `new Date().toISOString()`).
417
401
  * @returns The formatted message string to be signed.
@@ -423,50 +407,40 @@ declare class PulsarModule {
423
407
  * ```
424
408
  */
425
409
  declare function createMiniSessionMessage(timestamp: string): string;
426
- /**
427
- * Result of a mini-session signing operation.
428
- */
429
- interface SignSessionResult {
430
- /** The cryptographic signature. */
431
- signature: string;
432
- /** The ISO timestamp used to generate the message. */
433
- timestamp: string;
434
- }
435
410
  /**
436
411
  * Triggers a signature request in the connected wallet to create a Mini-Session.
437
412
  *
438
- * This is a frontend-friendly helper that:
439
- * 1. Generates a fresh ISO timestamp.
440
- * 2. Formats the standard login message.
441
- * 3. Triggers the wallet's signMessage method.
442
- * 4. Returns the signature and timestamp for verification on the backend.
413
+ * This function detects the signer's capabilities and uses the most appropriate
414
+ * signing method available (e.g., Web3 v2, Standard, or Legacy).
415
+ *
416
+ * @param params - Parameters containing the signer and target ecosystem.
417
+ * @returns A promise resolving to the signature and timestamp.
418
+ * @throws {Error} If signing fails or the signer lacks required methods.
443
419
  *
444
- * @param params - The signing parameters including the signer and ecosystem type.
445
- * @returns A promise that resolves to the signature and timestamp.
446
- * @throws {Error} If the required peer dependencies are missing or signing fails.
420
+ * @public
447
421
  */
448
422
  declare function signMiniSession(params: SignSessionParams): Promise<SignSessionResult>;
449
423
  /**
450
- * Verifies a Mini-Session signature to protect API quota from unauthorized access.
424
+ * Verifies a Mini-Session signature for authenticity and freshness.
425
+ *
426
+ * Performs cryptographic verification against the provided wallet address and
427
+ * ensures the signature hasn't expired according to the `maxAge` parameter.
451
428
  *
452
- * This utility performs three checks:
453
- * 1. Timestamp freshness (rejects if older than 5 minutes or in the future).
454
- * 2. Cryptographic validity (checks if the signature matches the wallet address and message).
455
- * 3. Ecosystem-specific logic (EVM via `viem`, Solana via `gill`).
429
+ * @param params - Verification data including signature and timestamp.
430
+ * @returns A promise resolving to true if the session is valid.
456
431
  *
457
- * @param params - The verification parameters including address, signature, and timestamp.
458
- * @returns A promise that resolves to `true` if the signature is valid and fresh.
459
- * @throws {Error} If the required peer dependencies (`viem` or `gill`) are missing.
460
- * @throws {Error} If the timestamp is invalid or expired.
432
+ * @public
461
433
  */
462
434
  declare function verifyMiniSession(params: VerifySessionParams): Promise<boolean>;
463
435
 
464
436
  /**
465
437
  * Creates a persistent Zustand store to cache Mini-Session signatures.
466
- * Requires `zustand` to be installed as a peer dependency.
438
+ * This is the recommended way to manage sessions in React applications.
467
439
  *
468
- * @param storageName - Key name for localStorage persistence.
469
- * @returns A Zustand store instance.
440
+ * @param storageName - The localStorage key for persistence. Defaults to 'mini-session-storage'.
441
+ * @returns A Zustand store instance initialized with MiniSessionStore interface.
442
+ *
443
+ * @public
470
444
  */
471
445
  declare function createMiniSessionStore(storageName?: string): zustand.UseBoundStore<Omit<zustand.StoreApi<MiniSessionStore>, "setState" | "persist"> & {
472
446
  setState(partial: MiniSessionStore | Partial<MiniSessionStore> | ((state: MiniSessionStore) => MiniSessionStore | Partial<MiniSessionStore>), replace?: false | undefined): unknown;
@@ -482,19 +456,22 @@ declare function createMiniSessionStore(storageName?: string): zustand.UseBoundS
482
456
  };
483
457
  }>;
484
458
  /**
485
- * Generic helper to manage Mini-Session signing and caching.
459
+ * High-level orchestrator to retrieve an existing Mini-Session or trigger a new signature.
460
+ *
461
+ * This function checks the provided store for a valid, non-expired session matching
462
+ * the current wallet connection. If no session is found or it has expired, it
463
+ * triggers a signature request through the wallet.
486
464
  *
487
- * Checks the provided store for an existing session matching the current connection.
488
- * If no session is found, it triggers a signature request using the provided signer.
465
+ * @param connection - The current active wallet connection data (address, signer, etc).
466
+ * @param store - A store implementation (Zustand or compatible) for session persistence.
467
+ * @returns A promise resolving to a valid MiniSessionAuth object.
468
+ * @throws {Error} If the wallet is disconnected or signing fails.
489
469
  *
490
- * @param connection - Current active connection state.
491
- * @param store - An object compatible with MiniSessionStore to read/write the session.
492
- * @returns A promise resolving to the authenticated session.
493
- * @throws {Error} If no wallet is connected or signing fails.
470
+ * @public
494
471
  */
495
472
  declare function getMiniSessionAuth(connection: ConnectionData, store: {
496
473
  miniSession: MiniSessionAuth | null;
497
- setMiniSession: (s: MiniSessionAuth) => void;
474
+ setMiniSession: (session: MiniSessionAuth | null) => void;
498
475
  }): Promise<MiniSessionAuth>;
499
476
 
500
477
  declare const BASE_API_URL = "https://api.tuwa.io";
@@ -639,4 +616,4 @@ declare class Quasar {
639
616
  constructor(config: QuasarConfig);
640
617
  }
641
618
 
642
- export { BASE_API_URL, ChainType, type ConnectionData, type HistoryQuery, type MiniSessionAuth, type MiniSessionStore, PULSAR_HISTORY_ENDPOINT, PULSAR_SYNC_ENDPOINT, type PaginatedResult, PulsarModule, Quasar, type QuasarConfig, QuasarSDKError, type SignSessionParams, type SignSessionResult, type VerifySessionParams, createMiniSessionMessage, createMiniSessionStore, getMiniSessionAuth, signMiniSession, utils, verifyMiniSession };
619
+ export { BASE_API_URL, ChainType, type ConnectionData, DEFAULT_MAX_AGE, type EvmSigner, type HistoryQuery, type MiniSessionAuth, type MiniSessionStore, PULSAR_HISTORY_ENDPOINT, PULSAR_SYNC_ENDPOINT, type PaginatedResult, PulsarModule, Quasar, type QuasarConfig, QuasarSDKError, type SignSessionParams, type SignSessionResult, type SolanaSignedMessage, type SolanaSigner, type VerifySessionParams, createMiniSessionMessage, createMiniSessionStore, getMiniSessionAuth, signMiniSession, utils, verifyMiniSession };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var ofetch=require('ofetch'),zustand=require('zustand'),middleware=require('zustand/middleware');var d="https://api.tuwa.io",p="/v1/engine/pulsar/sync",m="/v1/engine/pulsar/history";var c=class extends Error{status;originalError;constructor(e,r,s){super(e),this.name="QuasarSDKError",this.status=r,this.originalError=s;}},u=class{secretKey;internalSecret;baseUrl;timeout;constructor(e){if(!e.secretKey)throw new Error("[Quasar SDK] Missing API Key. Provide a secretKey starting with sk_live_.");this.secretKey=e.secretKey,this.internalSecret=e.internalSecret,this.baseUrl=e.baseUrl||d,this.timeout=e.timeout||1e4;}async request(e,r={}){try{return await ofetch.ofetch(e,{baseURL:this.baseUrl,timeout:this.timeout,...r,headers:{"Content-Type":"application/json","x-tuwa-secret-key":this.secretKey,...this.internalSecret?{"x-internal-secret":this.internalSecret}:{},...r.headers}})}catch(s){throw this.buildError(s)}}buildError(e){let r=e,s=r.statusCode??r.response?.status,o=(r.data??r.response?._data)?.error??r.message??"Unknown Error";return (s===401||s===403)&&console.error("\u{1F6A8} [Quasar SDK] Auth Error. Check your Secret Key and scopes."),new c(`[Quasar SDK] Request Failed (${s}): ${o}`,s,r)}};var a=class{constructor(e){this.client=e;}async syncCreate(e,r){return this.client.request(p,{method:"POST",body:{...e,appName:r}})}async getHistory(e={}){return this.client.request(m,{method:"GET",query:{page:e.page??1,limit:e.limit??10,chainId:e.chainId,status:e.status,txKey:e.txKey,appName:e.appName,walletAddress:e.walletAddress}})}};var S=(r=>(r.EVM="EVM",r.SOLANA="SOLANA",r))(S||{});var M=300*1e3,x=60*1e3;function l(t){return `Mini-Session Login: ${t}`}async function g(t){let e=new Date().toISOString(),r=l(e);if(t.chainType==="EVM"){if(!t.walletAddress)throw new Error("[SDK] walletAddress is required for EVM signing.");try{return {signature:await t.signer.signMessage({account:t.walletAddress,message:r}),timestamp:e}}catch(s){throw new Error(`[SDK] EVM signing failed: ${s.message}`,{cause:s})}}if(t.chainType==="SOLANA"){let s;try{s=await import('gill');}catch(n){throw new Error('[SDK] Peer dependency "gill" is required for Solana signing.',{cause:n})}try{let o=s.getUtf8Encoder().encode(r),[i]=await t.signer.signMessages([o]);if(!i||!i.signature)throw new Error("[SDK] Wallet returned invalid signature output.",{cause:i});return {signature:s.getSignatureFromBytes(i.signature),timestamp:e}}catch(n){throw new Error(`[SDK] Solana signing failed: ${n.message}`,{cause:n})}}throw new Error(`[SDK] Unsupported chain type: ${t.chainType}`)}async function h(t){let e=new Date(t.timestamp).getTime(),r=Date.now();if(isNaN(e))throw new Error("[SDK] Invalid timestamp format. Use ISO string.");let s=t.maxAge??M;if(r-e>s)throw new Error("[SDK] Signature expired. Please sign a fresh message.");if(e>r+x)throw new Error("[SDK] Timestamp is in the future. Check your system clock.");let n=l(t.timestamp);if(t.chainType==="EVM"){let o;try{o=await import('viem');}catch(i){throw new Error('[SDK] Peer dependency "viem" is required for EVM verification.',{cause:i})}return await o.verifyMessage({address:t.walletAddress,message:n,signature:t.signature})}if(t.chainType==="SOLANA"){let o;try{o=await import('gill');}catch(i){throw new Error('[SDK] Peer dependency "gill" is required for Solana verification.',{cause:i})}try{return await o.verifySignatureForAddress(o.address(t.walletAddress),t.signature,n)}catch{return false}}return false}function y(t="mini-session-storage"){return zustand.create()(middleware.persist(e=>({miniSession:null,setMiniSession:r=>e({miniSession:r}),clearSession:()=>e({miniSession:null})}),{name:t}))}async function f(t,e){if(!t.isConnected||!t.address)throw new Error("Wallet not connected. Please connect your wallet first.");let{address:r,chainType:s,signer:n}=t;if(e.miniSession&&e.miniSession.walletAddress===r&&e.miniSession.chainType===s)return e.miniSession;let i={...await g({signer:n,walletAddress:r,chainType:s}),chainType:s,walletAddress:r};return e.setMiniSession(i),i}var b={createMiniSessionMessage:l,verifyMiniSession:h,signMiniSession:g,createMiniSessionStore:y,getMiniSessionAuth:f},w=class{static utils=b;client;pulsar;constructor(e){this.client=new u(e),this.pulsar=new a(this.client);}};
2
- exports.BASE_API_URL=d;exports.ChainType=S;exports.PULSAR_HISTORY_ENDPOINT=m;exports.PULSAR_SYNC_ENDPOINT=p;exports.PulsarModule=a;exports.Quasar=w;exports.QuasarSDKError=c;exports.createMiniSessionMessage=l;exports.createMiniSessionStore=y;exports.getMiniSessionAuth=f;exports.signMiniSession=g;exports.utils=b;exports.verifyMiniSession=h;
1
+ 'use strict';var ofetch=require('ofetch'),zustand=require('zustand'),middleware=require('zustand/middleware');var f="https://api.tuwa.io",w="/v1/engine/pulsar/sync",A="/v1/engine/pulsar/history";var g=class extends Error{status;originalError;constructor(e,r,t){super(e),this.name="QuasarSDKError",this.status=r,this.originalError=t;}},u=class{secretKey;internalSecret;baseUrl;timeout;constructor(e){if(!e.secretKey)throw new Error("[Quasar SDK] Missing API Key. Provide a secretKey starting with sk_live_.");this.secretKey=e.secretKey,this.internalSecret=e.internalSecret,this.baseUrl=e.baseUrl||f,this.timeout=e.timeout||1e4;}async request(e,r={}){try{return await ofetch.ofetch(e,{baseURL:this.baseUrl,timeout:this.timeout,...r,headers:{"Content-Type":"application/json","x-tuwa-secret-key":this.secretKey,...this.internalSecret?{"x-internal-secret":this.internalSecret}:{},...r.headers}})}catch(t){throw this.buildError(t)}}buildError(e){let r=e,t=r.statusCode??r.response?.status,i=(r.data??r.response?._data)?.error??r.message??"Unknown Error";return (t===401||t===403)&&console.error("\u{1F6A8} [Quasar SDK] Auth Error. Check your Secret Key and scopes."),new g(`[Quasar SDK] Request Failed (${t}): ${i}`,t,r)}};var l=class{constructor(e){this.client=e;}async syncCreate(e,r){return this.client.request(w,{method:"POST",body:{...e,appName:r}})}async getHistory(e={}){return this.client.request(A,{method:"GET",query:{page:e.page??1,limit:e.limit??10,chainId:e.chainId,status:e.status,txKey:e.txKey,appName:e.appName,walletAddress:e.walletAddress}})}};var M=(r=>(r.EVM="EVM",r.SOLANA="SOLANA",r))(M||{});var y=300*1e3,b=60*1e3;function S(s){return `Mini-Session Login: ${s}`}async function d(s){let e=new Date().toISOString(),r=S(e);if(s.chainType==="EVM"){let t=s.signer;try{return {signature:await t.signMessage({account:s.walletAddress,message:r}),timestamp:e}}catch(n){throw new Error(`[SDK] EVM signing failed: ${n.message}`,{cause:n})}}if(s.chainType==="SOLANA"){let t=s.signer,n;try{n=await import('gill');}catch(i){throw new Error('[SDK] Peer dependency "gill" is required for Solana signing.',{cause:i})}try{let a=n.getUtf8Encoder().encode(r),c;if(t.modifyAndSignMessages){let o=n.createSignableMessage(a),[p]=await t.modifyAndSignMessages([o]),h=p.signatures[t.address];if(!h)throw new Error(`[SDK] Signature missing for address: ${t.address}`);c=h;}else if(t.signMessages){let[o]=await t.signMessages([a]);if(!o?.signature)throw new Error("[SDK] Wallet returned invalid signMessages output.");c=o.signature;}else if(t.signMessage)c=await t.signMessage(a);else throw new Error("[SDK] Signer lacks message signing capabilities.");return {signature:n.getSignatureFromBytes(c),timestamp:e}}catch(i){throw new Error(`[SDK] Solana signing failed: ${i.message}`,{cause:i})}}throw new Error(`[SDK] Unsupported chain type: ${s.chainType}`)}async function x(s){let e=new Date(s.timestamp).getTime(),r=Date.now();if(isNaN(e))throw new Error("[SDK] Invalid timestamp format. Use ISO string.");let t=s.maxAge??y;if(r-e>t)throw new Error("[SDK] Signature expired. Please sign a fresh message.");if(e>r+b)throw new Error("[SDK] Timestamp is in the future. Check your system clock.");let n=S(s.timestamp);if(s.chainType==="EVM"){let i;try{i=await import('viem');}catch(a){throw new Error('[SDK] Peer dependency "viem" is required for EVM verification.',{cause:a})}return await i.verifyMessage({address:s.walletAddress,message:n,signature:s.signature})}if(s.chainType==="SOLANA"){let i;try{i=await import('gill');}catch(a){throw new Error('[SDK] Peer dependency "gill" is required for Solana verification.',{cause:a})}try{let a=i.address(s.walletAddress);return await i.verifySignatureForAddress(a,s.signature,n)}catch{return false}}return false}function E(s="mini-session-storage"){return zustand.create()(middleware.persist(e=>({miniSession:null,setMiniSession:r=>e({miniSession:r}),clearSession:()=>e({miniSession:null})}),{name:s}))}async function P(s,e){let{isConnected:r,address:t,chainType:n,signer:i}=s;if(!r||!t)throw new Error("[SDK] Wallet not connected. Please connect your wallet first.");let a=e.miniSession;if(a&&a.walletAddress===t&&a.chainType===n){let o=Date.now(),p=new Date(a.timestamp).getTime();if(o-p<y)return a}let m={...await d({signer:i,walletAddress:t,chainType:n}),chainType:n,walletAddress:t};return e.setMiniSession(m),m}var C={createMiniSessionMessage:S,verifyMiniSession:x,signMiniSession:d,createMiniSessionStore:E,getMiniSessionAuth:P},T=class{static utils=C;client;pulsar;constructor(e){this.client=new u(e),this.pulsar=new l(this.client);}};
2
+ exports.BASE_API_URL=f;exports.ChainType=M;exports.DEFAULT_MAX_AGE=y;exports.PULSAR_HISTORY_ENDPOINT=A;exports.PULSAR_SYNC_ENDPOINT=w;exports.PulsarModule=l;exports.Quasar=T;exports.QuasarSDKError=g;exports.createMiniSessionMessage=S;exports.createMiniSessionStore=E;exports.getMiniSessionAuth=P;exports.signMiniSession=d;exports.utils=C;exports.verifyMiniSession=x;
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import {ofetch}from'ofetch';import {create}from'zustand';import {persist}from'zustand/middleware';var d="https://api.tuwa.io",p="/v1/engine/pulsar/sync",m="/v1/engine/pulsar/history";var c=class extends Error{status;originalError;constructor(e,r,s){super(e),this.name="QuasarSDKError",this.status=r,this.originalError=s;}},u=class{secretKey;internalSecret;baseUrl;timeout;constructor(e){if(!e.secretKey)throw new Error("[Quasar SDK] Missing API Key. Provide a secretKey starting with sk_live_.");this.secretKey=e.secretKey,this.internalSecret=e.internalSecret,this.baseUrl=e.baseUrl||d,this.timeout=e.timeout||1e4;}async request(e,r={}){try{return await ofetch(e,{baseURL:this.baseUrl,timeout:this.timeout,...r,headers:{"Content-Type":"application/json","x-tuwa-secret-key":this.secretKey,...this.internalSecret?{"x-internal-secret":this.internalSecret}:{},...r.headers}})}catch(s){throw this.buildError(s)}}buildError(e){let r=e,s=r.statusCode??r.response?.status,o=(r.data??r.response?._data)?.error??r.message??"Unknown Error";return (s===401||s===403)&&console.error("\u{1F6A8} [Quasar SDK] Auth Error. Check your Secret Key and scopes."),new c(`[Quasar SDK] Request Failed (${s}): ${o}`,s,r)}};var a=class{constructor(e){this.client=e;}async syncCreate(e,r){return this.client.request(p,{method:"POST",body:{...e,appName:r}})}async getHistory(e={}){return this.client.request(m,{method:"GET",query:{page:e.page??1,limit:e.limit??10,chainId:e.chainId,status:e.status,txKey:e.txKey,appName:e.appName,walletAddress:e.walletAddress}})}};var S=(r=>(r.EVM="EVM",r.SOLANA="SOLANA",r))(S||{});var M=300*1e3,x=60*1e3;function l(t){return `Mini-Session Login: ${t}`}async function g(t){let e=new Date().toISOString(),r=l(e);if(t.chainType==="EVM"){if(!t.walletAddress)throw new Error("[SDK] walletAddress is required for EVM signing.");try{return {signature:await t.signer.signMessage({account:t.walletAddress,message:r}),timestamp:e}}catch(s){throw new Error(`[SDK] EVM signing failed: ${s.message}`,{cause:s})}}if(t.chainType==="SOLANA"){let s;try{s=await import('gill');}catch(n){throw new Error('[SDK] Peer dependency "gill" is required for Solana signing.',{cause:n})}try{let o=s.getUtf8Encoder().encode(r),[i]=await t.signer.signMessages([o]);if(!i||!i.signature)throw new Error("[SDK] Wallet returned invalid signature output.",{cause:i});return {signature:s.getSignatureFromBytes(i.signature),timestamp:e}}catch(n){throw new Error(`[SDK] Solana signing failed: ${n.message}`,{cause:n})}}throw new Error(`[SDK] Unsupported chain type: ${t.chainType}`)}async function h(t){let e=new Date(t.timestamp).getTime(),r=Date.now();if(isNaN(e))throw new Error("[SDK] Invalid timestamp format. Use ISO string.");let s=t.maxAge??M;if(r-e>s)throw new Error("[SDK] Signature expired. Please sign a fresh message.");if(e>r+x)throw new Error("[SDK] Timestamp is in the future. Check your system clock.");let n=l(t.timestamp);if(t.chainType==="EVM"){let o;try{o=await import('viem');}catch(i){throw new Error('[SDK] Peer dependency "viem" is required for EVM verification.',{cause:i})}return await o.verifyMessage({address:t.walletAddress,message:n,signature:t.signature})}if(t.chainType==="SOLANA"){let o;try{o=await import('gill');}catch(i){throw new Error('[SDK] Peer dependency "gill" is required for Solana verification.',{cause:i})}try{return await o.verifySignatureForAddress(o.address(t.walletAddress),t.signature,n)}catch{return false}}return false}function y(t="mini-session-storage"){return create()(persist(e=>({miniSession:null,setMiniSession:r=>e({miniSession:r}),clearSession:()=>e({miniSession:null})}),{name:t}))}async function f(t,e){if(!t.isConnected||!t.address)throw new Error("Wallet not connected. Please connect your wallet first.");let{address:r,chainType:s,signer:n}=t;if(e.miniSession&&e.miniSession.walletAddress===r&&e.miniSession.chainType===s)return e.miniSession;let i={...await g({signer:n,walletAddress:r,chainType:s}),chainType:s,walletAddress:r};return e.setMiniSession(i),i}var b={createMiniSessionMessage:l,verifyMiniSession:h,signMiniSession:g,createMiniSessionStore:y,getMiniSessionAuth:f},w=class{static utils=b;client;pulsar;constructor(e){this.client=new u(e),this.pulsar=new a(this.client);}};
2
- export{d as BASE_API_URL,S as ChainType,m as PULSAR_HISTORY_ENDPOINT,p as PULSAR_SYNC_ENDPOINT,a as PulsarModule,w as Quasar,c as QuasarSDKError,l as createMiniSessionMessage,y as createMiniSessionStore,f as getMiniSessionAuth,g as signMiniSession,b as utils,h as verifyMiniSession};
1
+ import {ofetch}from'ofetch';import {create}from'zustand';import {persist}from'zustand/middleware';var f="https://api.tuwa.io",w="/v1/engine/pulsar/sync",A="/v1/engine/pulsar/history";var g=class extends Error{status;originalError;constructor(e,r,t){super(e),this.name="QuasarSDKError",this.status=r,this.originalError=t;}},u=class{secretKey;internalSecret;baseUrl;timeout;constructor(e){if(!e.secretKey)throw new Error("[Quasar SDK] Missing API Key. Provide a secretKey starting with sk_live_.");this.secretKey=e.secretKey,this.internalSecret=e.internalSecret,this.baseUrl=e.baseUrl||f,this.timeout=e.timeout||1e4;}async request(e,r={}){try{return await ofetch(e,{baseURL:this.baseUrl,timeout:this.timeout,...r,headers:{"Content-Type":"application/json","x-tuwa-secret-key":this.secretKey,...this.internalSecret?{"x-internal-secret":this.internalSecret}:{},...r.headers}})}catch(t){throw this.buildError(t)}}buildError(e){let r=e,t=r.statusCode??r.response?.status,i=(r.data??r.response?._data)?.error??r.message??"Unknown Error";return (t===401||t===403)&&console.error("\u{1F6A8} [Quasar SDK] Auth Error. Check your Secret Key and scopes."),new g(`[Quasar SDK] Request Failed (${t}): ${i}`,t,r)}};var l=class{constructor(e){this.client=e;}async syncCreate(e,r){return this.client.request(w,{method:"POST",body:{...e,appName:r}})}async getHistory(e={}){return this.client.request(A,{method:"GET",query:{page:e.page??1,limit:e.limit??10,chainId:e.chainId,status:e.status,txKey:e.txKey,appName:e.appName,walletAddress:e.walletAddress}})}};var M=(r=>(r.EVM="EVM",r.SOLANA="SOLANA",r))(M||{});var y=300*1e3,b=60*1e3;function S(s){return `Mini-Session Login: ${s}`}async function d(s){let e=new Date().toISOString(),r=S(e);if(s.chainType==="EVM"){let t=s.signer;try{return {signature:await t.signMessage({account:s.walletAddress,message:r}),timestamp:e}}catch(n){throw new Error(`[SDK] EVM signing failed: ${n.message}`,{cause:n})}}if(s.chainType==="SOLANA"){let t=s.signer,n;try{n=await import('gill');}catch(i){throw new Error('[SDK] Peer dependency "gill" is required for Solana signing.',{cause:i})}try{let a=n.getUtf8Encoder().encode(r),c;if(t.modifyAndSignMessages){let o=n.createSignableMessage(a),[p]=await t.modifyAndSignMessages([o]),h=p.signatures[t.address];if(!h)throw new Error(`[SDK] Signature missing for address: ${t.address}`);c=h;}else if(t.signMessages){let[o]=await t.signMessages([a]);if(!o?.signature)throw new Error("[SDK] Wallet returned invalid signMessages output.");c=o.signature;}else if(t.signMessage)c=await t.signMessage(a);else throw new Error("[SDK] Signer lacks message signing capabilities.");return {signature:n.getSignatureFromBytes(c),timestamp:e}}catch(i){throw new Error(`[SDK] Solana signing failed: ${i.message}`,{cause:i})}}throw new Error(`[SDK] Unsupported chain type: ${s.chainType}`)}async function x(s){let e=new Date(s.timestamp).getTime(),r=Date.now();if(isNaN(e))throw new Error("[SDK] Invalid timestamp format. Use ISO string.");let t=s.maxAge??y;if(r-e>t)throw new Error("[SDK] Signature expired. Please sign a fresh message.");if(e>r+b)throw new Error("[SDK] Timestamp is in the future. Check your system clock.");let n=S(s.timestamp);if(s.chainType==="EVM"){let i;try{i=await import('viem');}catch(a){throw new Error('[SDK] Peer dependency "viem" is required for EVM verification.',{cause:a})}return await i.verifyMessage({address:s.walletAddress,message:n,signature:s.signature})}if(s.chainType==="SOLANA"){let i;try{i=await import('gill');}catch(a){throw new Error('[SDK] Peer dependency "gill" is required for Solana verification.',{cause:a})}try{let a=i.address(s.walletAddress);return await i.verifySignatureForAddress(a,s.signature,n)}catch{return false}}return false}function E(s="mini-session-storage"){return create()(persist(e=>({miniSession:null,setMiniSession:r=>e({miniSession:r}),clearSession:()=>e({miniSession:null})}),{name:s}))}async function P(s,e){let{isConnected:r,address:t,chainType:n,signer:i}=s;if(!r||!t)throw new Error("[SDK] Wallet not connected. Please connect your wallet first.");let a=e.miniSession;if(a&&a.walletAddress===t&&a.chainType===n){let o=Date.now(),p=new Date(a.timestamp).getTime();if(o-p<y)return a}let m={...await d({signer:i,walletAddress:t,chainType:n}),chainType:n,walletAddress:t};return e.setMiniSession(m),m}var C={createMiniSessionMessage:S,verifyMiniSession:x,signMiniSession:d,createMiniSessionStore:E,getMiniSessionAuth:P},T=class{static utils=C;client;pulsar;constructor(e){this.client=new u(e),this.pulsar=new l(this.client);}};
2
+ export{f as BASE_API_URL,M as ChainType,y as DEFAULT_MAX_AGE,A as PULSAR_HISTORY_ENDPOINT,w as PULSAR_SYNC_ENDPOINT,l as PulsarModule,T as Quasar,g as QuasarSDKError,S as createMiniSessionMessage,E as createMiniSessionStore,P as getMiniSessionAuth,d as signMiniSession,C as utils,x as verifyMiniSession};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuwaio/quasar-sdk",
3
- "version": "1.0.0-fix-docs-alpha.7.481db45",
3
+ "version": "1.0.0-fix-docs-alpha.8.45d929e",
4
4
  "private": false,
5
5
  "author": "Oleksandr Tkach",
6
6
  "license": "Apache-2.0",