@rhinestone/1auth 0.1.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.
@@ -0,0 +1,777 @@
1
+ /**
2
+ * Theme configuration for the dialog UI
3
+ */
4
+ interface ThemeConfig {
5
+ /** Color mode: 'light', 'dark', or 'system' (follows user's OS preference) */
6
+ mode?: 'light' | 'dark' | 'system';
7
+ /** Primary accent color (hex). Used for buttons and interactive elements */
8
+ accent?: string;
9
+ }
10
+ interface PasskeyProviderConfig {
11
+ /** Base URL of the auth API (Next.js server) */
12
+ providerUrl: string;
13
+ /** Client identifier for this application */
14
+ clientId: string;
15
+ /** Optional redirect URL for redirect flow */
16
+ redirectUrl?: string;
17
+ /** Optional URL of the dialog UI (Vite app). Defaults to providerUrl + /dialog */
18
+ dialogUrl?: string;
19
+ /** Optional theme configuration for the dialog */
20
+ theme?: ThemeConfig;
21
+ }
22
+ interface LoginOptions {
23
+ username: string;
24
+ }
25
+ interface LoginResult {
26
+ success: boolean;
27
+ username?: string;
28
+ user?: {
29
+ id: string;
30
+ username: string;
31
+ };
32
+ error?: {
33
+ code: string;
34
+ message: string;
35
+ };
36
+ }
37
+ interface RegisterOptions {
38
+ username: string;
39
+ }
40
+ interface RegisterResult {
41
+ success: boolean;
42
+ username?: string;
43
+ error?: {
44
+ code: string;
45
+ message: string;
46
+ };
47
+ }
48
+ /**
49
+ * Options for the authenticate() method
50
+ */
51
+ interface AuthenticateOptions {
52
+ /**
53
+ * Human-readable challenge message for the user to sign.
54
+ * The provider will hash this with a domain separator to prevent
55
+ * the signature from being reused for transaction signing.
56
+ */
57
+ challenge?: string;
58
+ }
59
+ /**
60
+ * Result of the authenticate() method
61
+ */
62
+ interface AuthenticateResult {
63
+ success: boolean;
64
+ username?: string;
65
+ user?: {
66
+ id: string;
67
+ username: string;
68
+ };
69
+ /**
70
+ * The user's smart account address (derived from their passkey).
71
+ */
72
+ accountAddress?: `0x${string}`;
73
+ /**
74
+ * Signature of the hashed challenge.
75
+ * Only present if a challenge was provided in the options.
76
+ */
77
+ signature?: WebAuthnSignature;
78
+ /**
79
+ * The hash that was actually signed (so apps can verify server-side).
80
+ * Computed as: keccak256("\x19Passkey Signed Message:\n" + len + challenge)
81
+ */
82
+ signedHash?: `0x${string}`;
83
+ error?: {
84
+ code: string;
85
+ message: string;
86
+ };
87
+ }
88
+ /**
89
+ * Options for signMessage
90
+ */
91
+ interface SignMessageOptions {
92
+ /** Username of the signer */
93
+ username: string;
94
+ /** Human-readable message to sign */
95
+ message: string;
96
+ /** Optional custom challenge (defaults to message hash) */
97
+ challenge?: string;
98
+ /** Description shown to user in the dialog */
99
+ description?: string;
100
+ /** Optional metadata to display to the user */
101
+ metadata?: Record<string, unknown>;
102
+ /** Theme configuration */
103
+ theme?: ThemeConfig;
104
+ }
105
+ /**
106
+ * Result of signMessage
107
+ */
108
+ interface SignMessageResult {
109
+ success: boolean;
110
+ /** WebAuthn signature if successful */
111
+ signature?: WebAuthnSignature;
112
+ /** The message that was signed */
113
+ signedMessage?: string;
114
+ /**
115
+ * The hash that was actually signed (with domain separator).
116
+ * Computed as: keccak256("\x19Passkey Signed Message:\n" + len + message)
117
+ * Use hashMessage() from the SDK to verify this matches your original message.
118
+ */
119
+ signedHash?: `0x${string}`;
120
+ /** Passkey credentials used for signing */
121
+ passkey?: PasskeyCredentials;
122
+ /** Error details if failed */
123
+ error?: {
124
+ code: SigningErrorCode;
125
+ message: string;
126
+ };
127
+ }
128
+ interface TransactionAction {
129
+ type: 'send' | 'receive' | 'approve' | 'swap' | 'mint' | 'custom';
130
+ label: string;
131
+ sublabel?: string;
132
+ amount?: string;
133
+ icon?: string;
134
+ }
135
+ interface TransactionFees {
136
+ estimated: string;
137
+ network: {
138
+ name: string;
139
+ icon?: string;
140
+ };
141
+ }
142
+ interface BalanceRequirement {
143
+ token: string;
144
+ amount: string;
145
+ faucetUrl?: string;
146
+ }
147
+ interface TransactionDetails {
148
+ actions: TransactionAction[];
149
+ fees?: TransactionFees;
150
+ requiredBalance?: BalanceRequirement;
151
+ account?: {
152
+ address: string;
153
+ label?: string;
154
+ };
155
+ }
156
+ interface SigningRequestOptions {
157
+ challenge: string;
158
+ username: string;
159
+ description?: string;
160
+ metadata?: Record<string, unknown>;
161
+ transaction?: TransactionDetails;
162
+ }
163
+ interface PasskeyCredential {
164
+ id: string;
165
+ deviceName: string | null;
166
+ publicKeyX: string;
167
+ publicKeyY: string;
168
+ }
169
+ interface UserPasskeysResponse {
170
+ passkeys: PasskeyCredential[];
171
+ }
172
+ interface WebAuthnSignature {
173
+ authenticatorData: string;
174
+ clientDataJSON: string;
175
+ challengeIndex: number;
176
+ typeIndex: number;
177
+ r: string;
178
+ s: string;
179
+ topOrigin: string | null;
180
+ }
181
+ interface PasskeyCredentials {
182
+ credentialId: string;
183
+ publicKeyX: string;
184
+ publicKeyY: string;
185
+ }
186
+ interface SigningSuccess {
187
+ success: true;
188
+ requestId?: string;
189
+ signature: WebAuthnSignature;
190
+ passkey?: PasskeyCredentials;
191
+ }
192
+ type SigningErrorCode = "USER_REJECTED" | "EXPIRED" | "INVALID_REQUEST" | "NETWORK_ERROR" | "POPUP_BLOCKED" | "SIGNING_FAILED" | "UNKNOWN";
193
+ interface EmbedOptions {
194
+ container: HTMLElement;
195
+ width?: string;
196
+ height?: string;
197
+ onReady?: () => void;
198
+ onClose?: () => void;
199
+ }
200
+ interface SigningError {
201
+ success: false;
202
+ requestId?: string;
203
+ error: {
204
+ code: SigningErrorCode;
205
+ message: string;
206
+ };
207
+ }
208
+ type SigningResult = SigningSuccess | SigningError;
209
+ interface CreateSigningRequestResponse {
210
+ requestId: string;
211
+ nonce: string;
212
+ signingUrl: string;
213
+ expiresAt: string;
214
+ }
215
+ interface SigningRequestStatus {
216
+ id: string;
217
+ status: "PENDING" | "COMPLETED" | "REJECTED" | "EXPIRED" | "FAILED";
218
+ signature?: WebAuthnSignature;
219
+ error?: {
220
+ code: SigningErrorCode;
221
+ message: string;
222
+ };
223
+ }
224
+ /**
225
+ * A call to execute on the target chain
226
+ */
227
+ interface IntentCall {
228
+ /** Target contract address */
229
+ to: string;
230
+ /** Calldata to send */
231
+ data?: string;
232
+ /** Value in wei (as string for serialization) */
233
+ value?: string;
234
+ /** Optional label for the transaction review UI */
235
+ label?: string;
236
+ /** Optional sublabel for additional context */
237
+ sublabel?: string;
238
+ }
239
+ /**
240
+ * Token request for the intent
241
+ */
242
+ interface IntentTokenRequest {
243
+ /** Token contract address */
244
+ token: string;
245
+ /** Amount (as string for serialization) */
246
+ amount: string;
247
+ }
248
+ /**
249
+ * A signed intent request from a merchant backend
250
+ * This provides XSS protection by ensuring calls were constructed server-side
251
+ */
252
+ interface MerchantSignedIntent {
253
+ /** Merchant ID (from seed/registration) */
254
+ merchantId: string;
255
+ /** Target chain ID */
256
+ targetChain: number;
257
+ /** Calls to execute (signed by merchant) */
258
+ calls: IntentCall[];
259
+ /** Username of the signer */
260
+ username?: string;
261
+ /** Alternative to username: account address */
262
+ accountAddress?: string;
263
+ /** Unique nonce for replay protection */
264
+ nonce: string;
265
+ /** Expiry timestamp (Unix ms) */
266
+ expiresAt: number;
267
+ /** Ed25519 signature over the canonical message (base64) */
268
+ signature: string;
269
+ /** Optional client ID */
270
+ clientId?: string;
271
+ /** Optional token requests */
272
+ tokenRequests?: IntentTokenRequest[];
273
+ }
274
+ /**
275
+ * Options for sendIntent
276
+ */
277
+ interface SendIntentOptions {
278
+ /** Username of the signer (for unsigned requests) */
279
+ username?: string;
280
+ /** Target chain ID (for unsigned requests) */
281
+ targetChain?: number;
282
+ /** Calls to execute on the target chain (for unsigned requests) */
283
+ calls?: IntentCall[];
284
+ /** Optional token requests (for unsigned requests) */
285
+ tokenRequests?: IntentTokenRequest[];
286
+ /**
287
+ * Constrain which tokens can be used as input/payment.
288
+ * If not specified, orchestrator picks from all available balances.
289
+ * Example: ['USDC'] or ['0x...'] to only use USDC as input.
290
+ */
291
+ sourceAssets?: string[];
292
+ /** When to close the dialog and return success. Defaults to "preconfirmed" */
293
+ closeOn?: CloseOnStatus;
294
+ /**
295
+ * Pre-signed intent from merchant backend (XSS protected)
296
+ * If provided, username/targetChain/calls/tokenRequests are ignored
297
+ */
298
+ signedIntent?: MerchantSignedIntent;
299
+ /**
300
+ * Wait for a transaction hash before resolving.
301
+ * Defaults to false to preserve existing behavior.
302
+ */
303
+ waitForHash?: boolean;
304
+ /** Maximum time to wait for a transaction hash in ms. */
305
+ hashTimeoutMs?: number;
306
+ /** Poll interval for transaction hash in ms. */
307
+ hashIntervalMs?: number;
308
+ }
309
+ /**
310
+ * Quote from the Rhinestone orchestrator
311
+ */
312
+ interface IntentQuote {
313
+ /** Total cost in input tokens */
314
+ cost: {
315
+ total: string;
316
+ breakdown?: {
317
+ gas?: string;
318
+ bridge?: string;
319
+ swap?: string;
320
+ };
321
+ };
322
+ /** Token requirements to fulfill the intent */
323
+ tokenRequirements: Array<{
324
+ token: string;
325
+ amount: string;
326
+ chainId: number;
327
+ }>;
328
+ }
329
+ /**
330
+ * Status of an intent (local states)
331
+ */
332
+ type IntentStatus = "pending" | "quoted" | "signed" | "submitted" | "completed" | "failed" | "expired";
333
+ /**
334
+ * Orchestrator status (from Rhinestone)
335
+ * These are the statuses we can receive when polling
336
+ */
337
+ type OrchestratorStatus = "PENDING" | "CLAIMED" | "PRECONFIRMED" | "FILLED" | "COMPLETED" | "FAILED" | "EXPIRED";
338
+ /**
339
+ * When to consider the transaction complete and close the dialog
340
+ * - "claimed" - Close when a solver has claimed the intent (fastest)
341
+ * - "preconfirmed" - Close on pre-confirmation (recommended)
342
+ * - "filled" - Close when the transaction is filled
343
+ * - "completed" - Wait for full completion (slowest, most certain)
344
+ */
345
+ type CloseOnStatus = "claimed" | "preconfirmed" | "filled" | "completed";
346
+ /**
347
+ * Result of sendIntent
348
+ */
349
+ interface SendIntentResult {
350
+ /** Whether the intent was successfully submitted */
351
+ success: boolean;
352
+ /** Intent ID for tracking */
353
+ intentId: string;
354
+ /** Current status */
355
+ status: IntentStatus;
356
+ /** Transaction hash if completed */
357
+ transactionHash?: string;
358
+ /** Operation ID from orchestrator */
359
+ operationId?: string;
360
+ /** Error details if failed */
361
+ error?: {
362
+ code: string;
363
+ message: string;
364
+ };
365
+ }
366
+ /**
367
+ * Prepare intent response from auth service
368
+ */
369
+ interface PrepareIntentResponse {
370
+ intentId: string;
371
+ quote: IntentQuote;
372
+ transaction: TransactionDetails;
373
+ challenge: string;
374
+ expiresAt: string;
375
+ /** Account address for the sign dialog to detect self-transfer vs external send */
376
+ accountAddress?: string;
377
+ }
378
+ /**
379
+ * Execute intent response from auth service
380
+ */
381
+ interface ExecuteIntentResponse {
382
+ success: boolean;
383
+ intentId: string;
384
+ operationId?: string;
385
+ status: IntentStatus;
386
+ transactionHash?: string;
387
+ error?: {
388
+ code: string;
389
+ message: string;
390
+ };
391
+ }
392
+ /**
393
+ * Options for sendSwap - high-level swap abstraction
394
+ */
395
+ interface SendSwapOptions {
396
+ /** Username of the signer */
397
+ username: string;
398
+ /** Target chain ID where swap executes */
399
+ targetChain: number;
400
+ /** Token to swap from (address or supported symbol like 'ETH', 'USDC') */
401
+ fromToken: string;
402
+ /** Token to swap to (address or supported symbol) */
403
+ toToken: string;
404
+ /** Amount to swap in human-readable format (e.g., "0.1") */
405
+ amount: string;
406
+ /** Maximum slippage in basis points (1 bp = 0.01%). Default: 50 (0.5%) */
407
+ slippageBps?: number;
408
+ /**
409
+ * Override source assets for the swap. If not specified, defaults to [fromToken].
410
+ * This constrains which tokens the orchestrator can use as input.
411
+ */
412
+ sourceAssets?: string[];
413
+ /** When to close the dialog. Defaults to "preconfirmed" */
414
+ closeOn?: CloseOnStatus;
415
+ /** Wait for a transaction hash before resolving. */
416
+ waitForHash?: boolean;
417
+ /** Maximum time to wait for a transaction hash in ms. */
418
+ hashTimeoutMs?: number;
419
+ /** Poll interval for transaction hash in ms. */
420
+ hashIntervalMs?: number;
421
+ }
422
+ /**
423
+ * Quote information from DEX aggregator
424
+ */
425
+ interface SwapQuote {
426
+ /** Token being sold */
427
+ fromToken: string;
428
+ /** Token being bought */
429
+ toToken: string;
430
+ /** Amount of fromToken being sold */
431
+ amountIn: string;
432
+ /** Amount of toToken being received */
433
+ amountOut: string;
434
+ /** Exchange rate (amountOut / amountIn) */
435
+ rate: string;
436
+ /** Price impact percentage (if available) */
437
+ priceImpact?: string;
438
+ }
439
+ /**
440
+ * Result of sendSwap - extends SendIntentResult with swap-specific data
441
+ */
442
+ interface SendSwapResult extends SendIntentResult {
443
+ /** The swap quote that was executed */
444
+ quote?: SwapQuote;
445
+ }
446
+ /**
447
+ * EIP-712 Domain parameters
448
+ */
449
+ interface EIP712Domain {
450
+ /** Name of the signing domain (e.g., "Dai Stablecoin") */
451
+ name: string;
452
+ /** Version of the signing domain (e.g., "1") */
453
+ version: string;
454
+ /** Chain ID (optional) */
455
+ chainId?: number;
456
+ /** Verifying contract address (optional) */
457
+ verifyingContract?: `0x${string}`;
458
+ /** Salt for disambiguation (optional) */
459
+ salt?: `0x${string}`;
460
+ }
461
+ /**
462
+ * EIP-712 Type field definition
463
+ */
464
+ interface EIP712TypeField {
465
+ /** Field name */
466
+ name: string;
467
+ /** Solidity type (e.g., "address", "uint256", "bytes32") */
468
+ type: string;
469
+ }
470
+ /**
471
+ * EIP-712 Types map - maps type names to their field definitions
472
+ */
473
+ type EIP712Types = {
474
+ [typeName: string]: EIP712TypeField[];
475
+ };
476
+ /**
477
+ * Options for signTypedData
478
+ */
479
+ interface SignTypedDataOptions {
480
+ /** Username of the signer */
481
+ username: string;
482
+ /** EIP-712 domain parameters */
483
+ domain: EIP712Domain;
484
+ /** Type definitions for all types used in the message */
485
+ types: EIP712Types;
486
+ /** Primary type being signed (must be a key in types) */
487
+ primaryType: string;
488
+ /** Message values matching the primaryType structure */
489
+ message: Record<string, unknown>;
490
+ /** Optional description shown in the dialog */
491
+ description?: string;
492
+ /** Theme configuration */
493
+ theme?: ThemeConfig;
494
+ }
495
+ /**
496
+ * Result of signTypedData
497
+ */
498
+ interface SignTypedDataResult {
499
+ success: boolean;
500
+ /** WebAuthn signature if successful */
501
+ signature?: WebAuthnSignature;
502
+ /** The EIP-712 hash that was signed */
503
+ signedHash?: `0x${string}`;
504
+ /** Passkey credentials used for signing */
505
+ passkey?: PasskeyCredentials;
506
+ /** Error details if failed */
507
+ error?: {
508
+ code: SigningErrorCode;
509
+ message: string;
510
+ };
511
+ }
512
+
513
+ declare class PasskeyProviderClient {
514
+ private config;
515
+ private theme;
516
+ constructor(config: PasskeyProviderConfig);
517
+ /**
518
+ * Update the theme configuration at runtime
519
+ */
520
+ setTheme(theme: ThemeConfig): void;
521
+ /**
522
+ * Build theme URL parameters
523
+ */
524
+ private getThemeParams;
525
+ /**
526
+ * Get the dialog URL (Vite app URL)
527
+ * Defaults to providerUrl if dialogUrl is not set
528
+ */
529
+ private getDialogUrl;
530
+ /**
531
+ * Get the origin for message validation
532
+ * Uses dialogUrl origin if set, otherwise providerUrl origin
533
+ */
534
+ private getDialogOrigin;
535
+ /**
536
+ * Get the base provider URL
537
+ */
538
+ getProviderUrl(): string;
539
+ /**
540
+ * Get the configured client ID
541
+ */
542
+ getClientId(): string;
543
+ private waitForTransactionHash;
544
+ /**
545
+ * Show Porto-style "Get started" auth dialog (combines sign in + sign up)
546
+ * This is the recommended method for authentication - shows a modal overlay
547
+ * with both sign in and create account options.
548
+ */
549
+ authWithModal(options?: {
550
+ username?: string;
551
+ theme?: ThemeConfig;
552
+ oauthEnabled?: boolean;
553
+ }): Promise<LoginResult | RegisterResult>;
554
+ /**
555
+ * Authenticate a user with an optional challenge to sign.
556
+ *
557
+ * This method combines authentication (sign in / sign up) with optional
558
+ * challenge signing, enabling off-chain login without on-chain transactions.
559
+ *
560
+ * When a challenge is provided:
561
+ * 1. User authenticates (sign in or sign up)
562
+ * 2. The challenge is hashed with a domain separator
563
+ * 3. User signs the hash with their passkey
564
+ * 4. Returns user info + signature for server-side verification
565
+ *
566
+ * The domain separator ("\x19Passkey Signed Message:\n") ensures the signature
567
+ * cannot be reused for transaction signing, preventing phishing attacks.
568
+ *
569
+ * @example
570
+ * ```typescript
571
+ * // Authenticate with a login challenge
572
+ * const result = await client.authenticate({
573
+ * challenge: `Login to MyApp\nTimestamp: ${Date.now()}\nNonce: ${crypto.randomUUID()}`
574
+ * });
575
+ *
576
+ * if (result.success && result.signature) {
577
+ * // Verify signature server-side
578
+ * const isValid = await verifyOnServer(
579
+ * result.username,
580
+ * result.signature,
581
+ * result.signedHash
582
+ * );
583
+ * }
584
+ * ```
585
+ */
586
+ authenticate(options?: AuthenticateOptions & {
587
+ theme?: ThemeConfig;
588
+ }): Promise<AuthenticateResult>;
589
+ /**
590
+ * Show signing in a modal overlay (Porto-style iframe dialog)
591
+ */
592
+ signWithModal(options: SigningRequestOptions & {
593
+ theme?: ThemeConfig;
594
+ }): Promise<SigningResult>;
595
+ /**
596
+ * Send an intent to the Rhinestone orchestrator
597
+ *
598
+ * This is the high-level method for cross-chain transactions:
599
+ * 1. Prepares the intent (gets quote from orchestrator)
600
+ * 2. Shows the signing modal with real fees
601
+ * 3. Submits the signed intent for execution
602
+ * 4. Returns the transaction hash
603
+ *
604
+ * @example
605
+ * ```typescript
606
+ * const result = await client.sendIntent({
607
+ * username: 'alice',
608
+ * targetChain: 8453, // Base
609
+ * calls: [
610
+ * {
611
+ * to: '0x...',
612
+ * data: '0x...',
613
+ * label: 'Swap ETH for USDC',
614
+ * sublabel: '0.1 ETH → ~250 USDC',
615
+ * },
616
+ * ],
617
+ * });
618
+ *
619
+ * if (result.success) {
620
+ * console.log('Transaction hash:', result.transactionHash);
621
+ * }
622
+ * ```
623
+ */
624
+ sendIntent(options: SendIntentOptions): Promise<SendIntentResult>;
625
+ /**
626
+ * Send transaction status to the dialog iframe
627
+ */
628
+ private sendTransactionStatus;
629
+ /**
630
+ * Wait for the signing result without closing the modal
631
+ */
632
+ private waitForIntentSigningResponse;
633
+ /**
634
+ * Wait for signing result (simplified - no requestId matching)
635
+ */
636
+ private waitForSigningResponse;
637
+ /**
638
+ * Wait for the dialog to be closed
639
+ */
640
+ private waitForDialogClose;
641
+ /**
642
+ * Poll for intent status
643
+ *
644
+ * Use this to check on the status of a submitted intent
645
+ * that hasn't completed yet.
646
+ */
647
+ getIntentStatus(intentId: string): Promise<SendIntentResult>;
648
+ /**
649
+ * Send a swap intent through the Rhinestone orchestrator
650
+ *
651
+ * This is a high-level abstraction for token swaps (including cross-chain):
652
+ * 1. Resolves token symbols to addresses
653
+ * 2. Builds the swap intent with tokenRequests (output-first model)
654
+ * 3. The orchestrator's solver network finds the best route
655
+ * 4. Executes via the standard intent flow
656
+ *
657
+ * NOTE: The `amount` parameter specifies the OUTPUT amount (what the user wants to receive),
658
+ * not the input amount. The orchestrator will calculate the required input from sourceAssets.
659
+ *
660
+ * @example
661
+ * ```typescript
662
+ * // Buy 100 USDC using ETH on Base
663
+ * const result = await client.sendSwap({
664
+ * username: 'alice',
665
+ * targetChain: 8453,
666
+ * fromToken: 'ETH',
667
+ * toToken: 'USDC',
668
+ * amount: '100', // Receive 100 USDC
669
+ * });
670
+ *
671
+ * // Cross-chain: Buy 50 USDC on Base, paying with ETH from any chain
672
+ * const result = await client.sendSwap({
673
+ * username: 'alice',
674
+ * targetChain: 8453, // Base
675
+ * fromToken: 'ETH',
676
+ * toToken: 'USDC',
677
+ * amount: '50', // Receive 50 USDC
678
+ * });
679
+ * ```
680
+ */
681
+ sendSwap(options: SendSwapOptions): Promise<SendSwapResult>;
682
+ /**
683
+ * Sign an arbitrary message with the user's passkey
684
+ *
685
+ * This is for off-chain message signing (e.g., authentication challenges,
686
+ * terms acceptance, login signatures), NOT for transaction signing.
687
+ * The message is displayed to the user and signed with their passkey.
688
+ *
689
+ * @example
690
+ * ```typescript
691
+ * // Sign a login challenge
692
+ * const result = await client.signMessage({
693
+ * username: 'alice',
694
+ * message: `Sign in to MyApp\nTimestamp: ${Date.now()}\nNonce: ${crypto.randomUUID()}`,
695
+ * description: 'Verify your identity to continue',
696
+ * });
697
+ *
698
+ * if (result.success) {
699
+ * // Send signature to your backend for verification
700
+ * await fetch('/api/verify', {
701
+ * method: 'POST',
702
+ * body: JSON.stringify({
703
+ * signature: result.signature,
704
+ * message: result.signedMessage,
705
+ * }),
706
+ * });
707
+ * }
708
+ * ```
709
+ */
710
+ signMessage(options: SignMessageOptions): Promise<SignMessageResult>;
711
+ /**
712
+ * Sign EIP-712 typed data with the user's passkey
713
+ *
714
+ * This method allows signing structured data following the EIP-712 standard.
715
+ * The typed data is displayed to the user in a human-readable format before signing.
716
+ *
717
+ * @example
718
+ * ```typescript
719
+ * // Sign an ERC-2612 Permit
720
+ * const result = await client.signTypedData({
721
+ * username: 'alice',
722
+ * domain: {
723
+ * name: 'Dai Stablecoin',
724
+ * version: '1',
725
+ * chainId: 1,
726
+ * verifyingContract: '0x6B175474E89094C44Da98b954EecdeCB5BE3830F',
727
+ * },
728
+ * types: {
729
+ * Permit: [
730
+ * { name: 'owner', type: 'address' },
731
+ * { name: 'spender', type: 'address' },
732
+ * { name: 'value', type: 'uint256' },
733
+ * { name: 'nonce', type: 'uint256' },
734
+ * { name: 'deadline', type: 'uint256' },
735
+ * ],
736
+ * },
737
+ * primaryType: 'Permit',
738
+ * message: {
739
+ * owner: '0xabc...',
740
+ * spender: '0xdef...',
741
+ * value: 1000000000000000000n,
742
+ * nonce: 0n,
743
+ * deadline: 1735689600n,
744
+ * },
745
+ * });
746
+ *
747
+ * if (result.success) {
748
+ * console.log('Signed hash:', result.signedHash);
749
+ * }
750
+ * ```
751
+ */
752
+ signTypedData(options: SignTypedDataOptions): Promise<SignTypedDataResult>;
753
+ signWithPopup(options: SigningRequestOptions): Promise<SigningResult>;
754
+ signWithRedirect(options: SigningRequestOptions, redirectUrl?: string): Promise<void>;
755
+ signWithEmbed(options: SigningRequestOptions, embedOptions: EmbedOptions): Promise<SigningResult>;
756
+ private createEmbed;
757
+ private waitForEmbedResponse;
758
+ removeEmbed(requestId: string): void;
759
+ handleRedirectCallback(): Promise<SigningResult>;
760
+ /**
761
+ * Fetch passkeys for a user from the auth provider
762
+ */
763
+ getPasskeys(username: string): Promise<PasskeyCredential[]>;
764
+ private createSigningRequest;
765
+ private openPopup;
766
+ /**
767
+ * Create a modal dialog with an iframe inside (Porto-style overlay)
768
+ */
769
+ private createModalDialog;
770
+ private waitForModalAuthResponse;
771
+ private waitForAuthenticateResponse;
772
+ private waitForModalSigningResponse;
773
+ private waitForPopupResponse;
774
+ private fetchSigningResult;
775
+ }
776
+
777
+ export { type AuthenticateOptions as A, type BalanceRequirement as B, type CreateSigningRequestResponse as C, type ExecuteIntentResponse as D, type EmbedOptions as E, type SendSwapOptions as F, type SendSwapResult as G, type SwapQuote as H, type IntentCall as I, type ThemeConfig as J, type LoginOptions as L, type MerchantSignedIntent as M, type OrchestratorStatus as O, PasskeyProviderClient as P, type RegisterOptions as R, type SendIntentResult as S, type TransactionAction as T, type UserPasskeysResponse as U, type WebAuthnSignature as W, type PasskeyProviderConfig as a, type SigningRequestOptions as b, type SigningResult as c, type SigningSuccess as d, type SigningError as e, type SigningErrorCode as f, type SigningRequestStatus as g, type PasskeyCredential as h, type RegisterResult as i, type LoginResult as j, type AuthenticateResult as k, type SignMessageOptions as l, type SignMessageResult as m, type SignTypedDataOptions as n, type SignTypedDataResult as o, type EIP712Domain as p, type EIP712Types as q, type EIP712TypeField as r, type TransactionFees as s, type TransactionDetails as t, type IntentTokenRequest as u, type SendIntentOptions as v, type IntentQuote as w, type IntentStatus as x, type CloseOnStatus as y, type PrepareIntentResponse as z };