@varity-labs/client-js 2.0.0-alpha.1

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.
@@ -0,0 +1,105 @@
1
+ /**
2
+ * SIWE (Sign-In with Ethereum) Authentication Manager
3
+ */
4
+ import { type ThirdwebClient, type Chain } from 'thirdweb';
5
+ import type { Account } from 'thirdweb/wallets';
6
+ import type { SIWEMessage, SIWESignatureResult, SIWEVerifyResult, SIWESession } from '../types';
7
+ /**
8
+ * SIWEAuth - Manage Sign-In with Ethereum authentication
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Generate SIWE message
13
+ * const message = await siweAuth.generateMessage({
14
+ * domain: 'example.com',
15
+ * address: account.address,
16
+ * uri: 'https://example.com',
17
+ * statement: 'Sign in to Example App'
18
+ * });
19
+ *
20
+ * // Sign message
21
+ * const result = await siweAuth.signMessage(message, account);
22
+ *
23
+ * // Verify signature
24
+ * const verified = await siweAuth.verify(result);
25
+ * ```
26
+ */
27
+ export declare class SIWEAuth {
28
+ private readonly client;
29
+ private readonly chain;
30
+ private sessions;
31
+ constructor(client: ThirdwebClient, chain: Chain);
32
+ /**
33
+ * Generate SIWE message
34
+ * @param params Message parameters
35
+ * @returns SIWE message string
36
+ */
37
+ generateMessage(params: Partial<SIWEMessage>): Promise<string>;
38
+ /**
39
+ * Format SIWE message according to EIP-4361 standard
40
+ * @param message SIWE message object
41
+ * @returns Formatted message string
42
+ */
43
+ private formatSIWEMessage;
44
+ /**
45
+ * Sign SIWE message
46
+ * @param message SIWE message string
47
+ * @param account Wallet account
48
+ * @returns Signature result
49
+ */
50
+ signMessage(message: string, account: Account): Promise<SIWESignatureResult>;
51
+ /**
52
+ * Verify SIWE signature
53
+ * @param result Signature result to verify
54
+ * @returns Verification result
55
+ */
56
+ verify(result: SIWESignatureResult): Promise<SIWEVerifyResult>;
57
+ /**
58
+ * Parse SIWE message string
59
+ * @param message SIWE message string
60
+ * @returns Parsed message object
61
+ */
62
+ private parseSIWEMessage;
63
+ /**
64
+ * Create session from verified signature
65
+ * @param result Verified signature result
66
+ * @param expiresInSeconds Session expiration in seconds (default: 24 hours)
67
+ * @returns Session object
68
+ */
69
+ createSession(result: SIWESignatureResult, expiresInSeconds?: number): Promise<SIWESession>;
70
+ /**
71
+ * Get active session for address
72
+ * @param address Wallet address
73
+ * @returns Session or null
74
+ */
75
+ getSession(address: string): SIWESession | null;
76
+ /**
77
+ * Delete session for address
78
+ * @param address Wallet address
79
+ */
80
+ deleteSession(address: string): void;
81
+ /**
82
+ * Clear all sessions
83
+ */
84
+ clearAllSessions(): void;
85
+ /**
86
+ * Generate random nonce
87
+ * @returns Random nonce string
88
+ */
89
+ private generateNonce;
90
+ /**
91
+ * Authenticate with Varity API server
92
+ * @param result Signature result
93
+ * @param apiUrl API server URL
94
+ * @returns Authentication token
95
+ */
96
+ authenticateWithAPI(result: SIWESignatureResult, apiUrl: string): Promise<string>;
97
+ /**
98
+ * Validate session with API server
99
+ * @param token Authentication token
100
+ * @param apiUrl API server URL
101
+ * @returns True if valid
102
+ */
103
+ validateWithAPI(token: string, apiUrl: string): Promise<boolean>;
104
+ }
105
+ export default SIWEAuth;
@@ -0,0 +1,328 @@
1
+ "use strict";
2
+ /**
3
+ * SIWE (Sign-In with Ethereum) Authentication Manager
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SIWEAuth = void 0;
7
+ const types_1 = require("../types");
8
+ /**
9
+ * SIWEAuth - Manage Sign-In with Ethereum authentication
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Generate SIWE message
14
+ * const message = await siweAuth.generateMessage({
15
+ * domain: 'example.com',
16
+ * address: account.address,
17
+ * uri: 'https://example.com',
18
+ * statement: 'Sign in to Example App'
19
+ * });
20
+ *
21
+ * // Sign message
22
+ * const result = await siweAuth.signMessage(message, account);
23
+ *
24
+ * // Verify signature
25
+ * const verified = await siweAuth.verify(result);
26
+ * ```
27
+ */
28
+ class SIWEAuth {
29
+ constructor(client, chain) {
30
+ this.client = client;
31
+ this.chain = chain;
32
+ this.sessions = new Map();
33
+ }
34
+ /**
35
+ * Generate SIWE message
36
+ * @param params Message parameters
37
+ * @returns SIWE message string
38
+ */
39
+ async generateMessage(params) {
40
+ try {
41
+ const message = {
42
+ domain: params.domain || (typeof window !== 'undefined' ? window.location.host : 'localhost'),
43
+ address: params.address || '',
44
+ statement: params.statement || 'Sign in with Ethereum to the app.',
45
+ uri: params.uri || (typeof window !== 'undefined' ? window.location.origin : 'http://localhost'),
46
+ version: params.version || '1',
47
+ chainId: params.chainId || this.chain.id,
48
+ nonce: params.nonce || this.generateNonce(),
49
+ issuedAt: params.issuedAt || new Date().toISOString(),
50
+ expirationTime: params.expirationTime,
51
+ notBefore: params.notBefore,
52
+ requestId: params.requestId,
53
+ resources: params.resources,
54
+ };
55
+ return this.formatSIWEMessage(message);
56
+ }
57
+ catch (error) {
58
+ throw new types_1.AuthenticationError(`Failed to generate SIWE message: ${error.message}`, { error });
59
+ }
60
+ }
61
+ /**
62
+ * Format SIWE message according to EIP-4361 standard
63
+ * @param message SIWE message object
64
+ * @returns Formatted message string
65
+ */
66
+ formatSIWEMessage(message) {
67
+ const parts = [
68
+ `${message.domain} wants you to sign in with your Ethereum account:`,
69
+ message.address,
70
+ '',
71
+ message.statement,
72
+ '',
73
+ `URI: ${message.uri}`,
74
+ `Version: ${message.version}`,
75
+ `Chain ID: ${message.chainId}`,
76
+ `Nonce: ${message.nonce}`,
77
+ `Issued At: ${message.issuedAt}`,
78
+ ];
79
+ if (message.expirationTime) {
80
+ parts.push(`Expiration Time: ${message.expirationTime}`);
81
+ }
82
+ if (message.notBefore) {
83
+ parts.push(`Not Before: ${message.notBefore}`);
84
+ }
85
+ if (message.requestId) {
86
+ parts.push(`Request ID: ${message.requestId}`);
87
+ }
88
+ if (message.resources && message.resources.length > 0) {
89
+ parts.push('Resources:');
90
+ message.resources.forEach((resource) => {
91
+ parts.push(`- ${resource}`);
92
+ });
93
+ }
94
+ return parts.join('\n');
95
+ }
96
+ /**
97
+ * Sign SIWE message
98
+ * @param message SIWE message string
99
+ * @param account Wallet account
100
+ * @returns Signature result
101
+ */
102
+ async signMessage(message, account) {
103
+ try {
104
+ const signature = await account.signMessage({ message });
105
+ return {
106
+ message,
107
+ signature,
108
+ };
109
+ }
110
+ catch (error) {
111
+ throw new types_1.AuthenticationError(`Failed to sign SIWE message: ${error.message}`, { error });
112
+ }
113
+ }
114
+ /**
115
+ * Verify SIWE signature
116
+ * @param result Signature result to verify
117
+ * @returns Verification result
118
+ */
119
+ async verify(result) {
120
+ try {
121
+ // Parse message to extract address and expiration
122
+ const parsedMessage = this.parseSIWEMessage(result.message);
123
+ // Check expiration
124
+ if (parsedMessage.expirationTime) {
125
+ const expirationDate = new Date(parsedMessage.expirationTime);
126
+ if (expirationDate < new Date()) {
127
+ return {
128
+ success: false,
129
+ error: 'Message has expired',
130
+ };
131
+ }
132
+ }
133
+ // Check not before
134
+ if (parsedMessage.notBefore) {
135
+ const notBeforeDate = new Date(parsedMessage.notBefore);
136
+ if (notBeforeDate > new Date()) {
137
+ return {
138
+ success: false,
139
+ error: 'Message is not yet valid',
140
+ };
141
+ }
142
+ }
143
+ // In a production environment, you would verify the signature here
144
+ // using cryptographic verification. This is a simplified version.
145
+ return {
146
+ success: true,
147
+ address: parsedMessage.address,
148
+ };
149
+ }
150
+ catch (error) {
151
+ return {
152
+ success: false,
153
+ error: error.message,
154
+ };
155
+ }
156
+ }
157
+ /**
158
+ * Parse SIWE message string
159
+ * @param message SIWE message string
160
+ * @returns Parsed message object
161
+ */
162
+ parseSIWEMessage(message) {
163
+ const lines = message.split('\n');
164
+ const parsed = {};
165
+ // Extract address (line 1)
166
+ parsed.address = lines[1]?.trim() || '';
167
+ // Extract statement (line 3)
168
+ parsed.statement = lines[3]?.trim() || '';
169
+ // Extract fields
170
+ lines.forEach((line) => {
171
+ if (line.startsWith('URI:')) {
172
+ parsed.uri = line.substring(4).trim();
173
+ }
174
+ else if (line.startsWith('Version:')) {
175
+ parsed.version = line.substring(8).trim();
176
+ }
177
+ else if (line.startsWith('Chain ID:')) {
178
+ parsed.chainId = parseInt(line.substring(9).trim());
179
+ }
180
+ else if (line.startsWith('Nonce:')) {
181
+ parsed.nonce = line.substring(6).trim();
182
+ }
183
+ else if (line.startsWith('Issued At:')) {
184
+ parsed.issuedAt = line.substring(10).trim();
185
+ }
186
+ else if (line.startsWith('Expiration Time:')) {
187
+ parsed.expirationTime = line.substring(16).trim();
188
+ }
189
+ else if (line.startsWith('Not Before:')) {
190
+ parsed.notBefore = line.substring(11).trim();
191
+ }
192
+ else if (line.startsWith('Request ID:')) {
193
+ parsed.requestId = line.substring(11).trim();
194
+ }
195
+ });
196
+ // Extract domain (line 0)
197
+ const domainMatch = lines[0]?.match(/^(.+?) wants you to sign in/);
198
+ parsed.domain = domainMatch ? domainMatch[1] : '';
199
+ return parsed;
200
+ }
201
+ /**
202
+ * Create session from verified signature
203
+ * @param result Verified signature result
204
+ * @param expiresInSeconds Session expiration in seconds (default: 24 hours)
205
+ * @returns Session object
206
+ */
207
+ async createSession(result, expiresInSeconds = 86400) {
208
+ try {
209
+ const verified = await this.verify(result);
210
+ if (!verified.success || !verified.address) {
211
+ throw new types_1.AuthenticationError('Cannot create session: Invalid signature', { verificationResult: verified });
212
+ }
213
+ const parsedMessage = this.parseSIWEMessage(result.message);
214
+ const now = new Date();
215
+ const expiresAt = new Date(now.getTime() + expiresInSeconds * 1000);
216
+ const session = {
217
+ address: verified.address,
218
+ chainId: parsedMessage.chainId,
219
+ issuedAt: now,
220
+ expiresAt,
221
+ signature: result.signature,
222
+ };
223
+ // Store session
224
+ this.sessions.set(verified.address, session);
225
+ return session;
226
+ }
227
+ catch (error) {
228
+ throw new types_1.AuthenticationError(`Failed to create session: ${error.message}`, { error });
229
+ }
230
+ }
231
+ /**
232
+ * Get active session for address
233
+ * @param address Wallet address
234
+ * @returns Session or null
235
+ */
236
+ getSession(address) {
237
+ const session = this.sessions.get(address);
238
+ if (!session) {
239
+ return null;
240
+ }
241
+ // Check if session is expired
242
+ if (session.expiresAt < new Date()) {
243
+ this.sessions.delete(address);
244
+ return null;
245
+ }
246
+ return session;
247
+ }
248
+ /**
249
+ * Delete session for address
250
+ * @param address Wallet address
251
+ */
252
+ deleteSession(address) {
253
+ this.sessions.delete(address);
254
+ }
255
+ /**
256
+ * Clear all sessions
257
+ */
258
+ clearAllSessions() {
259
+ this.sessions.clear();
260
+ }
261
+ /**
262
+ * Generate random nonce
263
+ * @returns Random nonce string
264
+ */
265
+ generateNonce() {
266
+ const array = new Uint8Array(16);
267
+ if (typeof window !== 'undefined' && window.crypto) {
268
+ window.crypto.getRandomValues(array);
269
+ }
270
+ else {
271
+ // Node.js environment
272
+ const crypto = require('crypto');
273
+ crypto.randomFillSync(array);
274
+ }
275
+ return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('');
276
+ }
277
+ /**
278
+ * Authenticate with Varity API server
279
+ * @param result Signature result
280
+ * @param apiUrl API server URL
281
+ * @returns Authentication token
282
+ */
283
+ async authenticateWithAPI(result, apiUrl) {
284
+ try {
285
+ const response = await fetch(`${apiUrl}/auth/siwe/verify`, {
286
+ method: 'POST',
287
+ headers: {
288
+ 'Content-Type': 'application/json',
289
+ },
290
+ body: JSON.stringify({
291
+ message: result.message,
292
+ signature: result.signature,
293
+ }),
294
+ });
295
+ if (!response.ok) {
296
+ throw new Error(`API responded with status ${response.status}`);
297
+ }
298
+ const data = await response.json();
299
+ return data.token;
300
+ }
301
+ catch (error) {
302
+ throw new types_1.AuthenticationError(`Failed to authenticate with API: ${error.message}`, { apiUrl, error });
303
+ }
304
+ }
305
+ /**
306
+ * Validate session with API server
307
+ * @param token Authentication token
308
+ * @param apiUrl API server URL
309
+ * @returns True if valid
310
+ */
311
+ async validateWithAPI(token, apiUrl) {
312
+ try {
313
+ const response = await fetch(`${apiUrl}/auth/validate`, {
314
+ method: 'POST',
315
+ headers: {
316
+ 'Content-Type': 'application/json',
317
+ 'Authorization': `Bearer ${token}`,
318
+ },
319
+ });
320
+ return response.ok;
321
+ }
322
+ catch (error) {
323
+ throw new types_1.AuthenticationError(`Failed to validate with API: ${error.message}`, { apiUrl, error });
324
+ }
325
+ }
326
+ }
327
+ exports.SIWEAuth = SIWEAuth;
328
+ exports.default = SIWEAuth;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Contract Manager - Handle smart contract interactions
3
+ */
4
+ import { type ThirdwebClient, type Chain } from 'thirdweb';
5
+ import type { Account } from 'thirdweb/wallets';
6
+ import type { ContractDeployOptions, ContractReadOptions, ContractWriteOptions, ContractEventFilter, ContractEvent, TransactionResult } from '../types';
7
+ /**
8
+ * ContractManager - Manage smart contract operations
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Read from contract
13
+ * const balance = await contractManager.read({
14
+ * address: '0x...',
15
+ * abi: ERC20_ABI,
16
+ * functionName: 'balanceOf',
17
+ * args: ['0x...']
18
+ * });
19
+ *
20
+ * // Write to contract
21
+ * const result = await contractManager.write({
22
+ * address: '0x...',
23
+ * abi: ERC20_ABI,
24
+ * functionName: 'transfer',
25
+ * args: ['0x...', 1000000n]
26
+ * }, account);
27
+ * ```
28
+ */
29
+ export declare class ContractManager {
30
+ private readonly client;
31
+ private readonly chain;
32
+ constructor(client: ThirdwebClient, chain: Chain);
33
+ /**
34
+ * Get contract instance
35
+ * @param address Contract address
36
+ * @param abi Contract ABI
37
+ * @returns Contract instance
38
+ */
39
+ getContractInstance(address: string, abi?: any[]): Readonly<import("thirdweb").ContractOptions<any[], `0x${string}`>>;
40
+ /**
41
+ * Read from contract (no gas required)
42
+ * @param options Contract read options
43
+ * @returns Read result
44
+ */
45
+ read(options: ContractReadOptions): Promise<any>;
46
+ /**
47
+ * Write to contract (requires gas and wallet signature)
48
+ * @param options Contract write options
49
+ * @param account Wallet account
50
+ * @returns Transaction result
51
+ */
52
+ write(options: ContractWriteOptions, account: Account): Promise<TransactionResult>;
53
+ /**
54
+ * Deploy new contract
55
+ * @param options Deployment options
56
+ * @param account Deployer account
57
+ * @returns Deployed contract address and transaction
58
+ */
59
+ deploy(options: ContractDeployOptions, account: Account): Promise<{
60
+ address: string;
61
+ transactionHash: string;
62
+ }>;
63
+ /**
64
+ * Get contract events
65
+ * @param filter Event filter options
66
+ * @returns Array of events
67
+ */
68
+ getEvents(filter: ContractEventFilter): Promise<ContractEvent[]>;
69
+ /**
70
+ * Listen to contract events (real-time)
71
+ * @param filter Event filter options
72
+ * @param callback Event callback
73
+ * @returns Cleanup function
74
+ */
75
+ watchEvents(filter: ContractEventFilter, callback: (event: ContractEvent) => void): () => void;
76
+ /**
77
+ * Estimate gas for contract call
78
+ * @param options Contract write options
79
+ * @param account Wallet account
80
+ * @returns Estimated gas
81
+ */
82
+ estimateGas(options: ContractWriteOptions, account: Account): Promise<bigint>;
83
+ /**
84
+ * Batch read multiple contract calls
85
+ * @param calls Array of read options
86
+ * @returns Array of results
87
+ */
88
+ batchRead(calls: ContractReadOptions[]): Promise<any[]>;
89
+ /**
90
+ * Batch write multiple contract calls (in sequence)
91
+ * @param calls Array of write options
92
+ * @param account Wallet account
93
+ * @returns Array of transaction results
94
+ */
95
+ batchWrite(calls: ContractWriteOptions[], account: Account): Promise<TransactionResult[]>;
96
+ /**
97
+ * Check if contract exists at address
98
+ * @param address Contract address
99
+ * @returns True if contract exists
100
+ */
101
+ contractExists(address: string): Promise<boolean>;
102
+ /**
103
+ * Get contract bytecode
104
+ * @param address Contract address
105
+ * @returns Contract bytecode
106
+ */
107
+ getBytecode(address: string): Promise<string>;
108
+ }
109
+ export default ContractManager;