decane-connect-kit 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,3 +1,4 @@
1
+ import * as _simplewebauthn_browser from '@simplewebauthn/browser';
1
2
  import React, { ReactNode } from 'react';
2
3
 
3
4
  type ChainType = "evm" | "solana" | "tron" | "bitcoin";
@@ -72,12 +73,23 @@ interface DecaneProvider {
72
73
  readonly activeSession: ActiveSession | null;
73
74
  readonly activeChain: string | null;
74
75
  }
76
+ type ConnectMode = "all" | "social" | "wallets" | "evm" | "solana" | "tron" | "evm+social" | "solana+social" | "tron+social" | "evm+tron" | "evm+tron+social";
77
+ interface SocialConfig {
78
+ apiKey: string;
79
+ authMethods?: ("google" | "email")[];
80
+ promptPin?: () => Promise<string>;
81
+ apiBaseUrl?: string;
82
+ chains?: string[];
83
+ rpcUrls?: Record<string, string>;
84
+ }
75
85
  interface DecaneConfig {
76
86
  chains?: ChainDescriptor[];
77
87
  supportedChainIds?: string[];
78
88
  networks?: "evm" | "solana" | "tron" | "bitcoin" | "all";
79
89
  defaultChain?: string;
80
90
  theme?: "light" | "dark" | "auto";
91
+ mode?: ConnectMode;
92
+ social?: SocialConfig;
81
93
  }
82
94
  interface EIP1193Provider {
83
95
  request(args: {
@@ -122,6 +134,316 @@ interface BitcoinProvider {
122
134
 
123
135
  declare function createDecane(config?: DecaneConfig): DecaneProvider;
124
136
 
137
+ declare class ApiClient {
138
+ private readonly baseUrl;
139
+ private readonly apiKey;
140
+ constructor(baseUrl: string, apiKey: string);
141
+ private _request;
142
+ getGoogleInitUrl(): Promise<{
143
+ url: string;
144
+ }>;
145
+ authEmailStart(email: string): Promise<void>;
146
+ authEmailVerify(email: string, code: string): Promise<AuthResult>;
147
+ getAddresses(jwt: string): Promise<{
148
+ evm: string | null;
149
+ solana: string | null;
150
+ }>;
151
+ putShare(jwt: string, share: {
152
+ ciphertext: Uint8Array;
153
+ iv: Uint8Array;
154
+ wrappedShareMeta: WrappedShareMeta;
155
+ evmAddress: string;
156
+ solanaAddress: string;
157
+ }): Promise<void>;
158
+ getWebAuthnRegisterOptions(jwt: string, rpId: string, rpName: string): Promise<_simplewebauthn_browser.PublicKeyCredentialCreationOptionsJSON>;
159
+ postWebAuthnRegister(jwt: string, response: _simplewebauthn_browser.RegistrationResponseJSON, origin: string): Promise<void>;
160
+ revoke(jwt: string): Promise<void>;
161
+ hasRecoveryBackup(jwt: string): Promise<boolean>;
162
+ getRecoveryBackup(jwt: string): Promise<{
163
+ wrappedDeviceShare: Uint8Array;
164
+ iv: Uint8Array;
165
+ unlockMethod: 'passkey';
166
+ credentialId: Uint8Array;
167
+ prfSalt: Uint8Array;
168
+ formatVersion: number;
169
+ } | null>;
170
+ putRecoveryBackup(jwt: string, backup: {
171
+ wrappedDeviceShare: Uint8Array;
172
+ iv: Uint8Array;
173
+ unlockMethod: 'passkey';
174
+ credentialId: Uint8Array;
175
+ prfSalt: Uint8Array;
176
+ }): Promise<void>;
177
+ deleteRecoveryBackup(jwt: string): Promise<void>;
178
+ markRecoveryShareSaved(jwt: string): Promise<void>;
179
+ getRecoveryStatus(jwt: string): Promise<{
180
+ hasRecoveryShare: boolean;
181
+ savedAt: string | null;
182
+ nagged: boolean;
183
+ shareSetVersion: number;
184
+ }>;
185
+ dismissRecoveryNag(jwt: string): Promise<void>;
186
+ }
187
+
188
+ type RecoveryProgress = {
189
+ type: 'passkey-attempt';
190
+ } | {
191
+ type: 'passkey-failed';
192
+ reason: string;
193
+ } | {
194
+ type: 'recovery-file-prompt';
195
+ } | {
196
+ type: 'password-prompt';
197
+ passwordHint: string | null;
198
+ } | {
199
+ type: 'recovery-verifying';
200
+ } | {
201
+ type: 'rotated';
202
+ shareSetVersion: number;
203
+ };
204
+
205
+ interface RecoveryShareFile {
206
+ version: number;
207
+ type: 'decane-recovery-share';
208
+ shareSetVersion: number;
209
+ kdf: 'pbkdf2-sha256';
210
+ kdfParams: {
211
+ iterations: number;
212
+ salt: string;
213
+ };
214
+ cipher: 'aes-256-gcm';
215
+ iv: string;
216
+ ciphertext: string;
217
+ addresses: {
218
+ evm: string;
219
+ solana: string;
220
+ };
221
+ passwordHint: string | null;
222
+ createdAt: string;
223
+ }
224
+
225
+ interface PortableBackup {
226
+ version: number;
227
+ type: 'decane-portable-backup';
228
+ shareSetVersion: number;
229
+ kdf: 'pbkdf2-sha256';
230
+ kdfParams: {
231
+ iterations: number;
232
+ salt: string;
233
+ };
234
+ cipher: 'aes-256-gcm';
235
+ iv: string;
236
+ ciphertext: string;
237
+ addresses: {
238
+ evm: string;
239
+ solana: string;
240
+ };
241
+ passwordHint: string | null;
242
+ createdAt: string;
243
+ }
244
+
245
+ type Chain = `evm:${number}` | `solana:${'mainnet' | 'devnet'}`;
246
+ interface DecaneConnectConfig {
247
+ apiKey: string;
248
+ chains: Chain[];
249
+ authMethods: Array<'google' | 'email'>;
250
+ apiBaseUrl?: string;
251
+ sessionDurationMinutes?: number;
252
+ promptPin?: () => Promise<string>;
253
+ rpId?: string;
254
+ rpName?: string;
255
+ rpcUrls?: Record<string, string>;
256
+ teeUrl?: string;
257
+ /** Offer to save a recovery-share file at signup. Default true. Never blocks onboarding. */
258
+ offerRecoveryAtSignup?: boolean;
259
+ /** Ask the user whether they want a recovery share and, if so, a password for it. */
260
+ onRecoveryShareOffer?: (addresses: {
261
+ evmAddress: string;
262
+ solanaAddress: string;
263
+ }) => Promise<{
264
+ wants: boolean;
265
+ password: string;
266
+ passwordHint?: string;
267
+ }>;
268
+ /** Hand the built file + suggested filename to the dApp, which owns the actual download. */
269
+ onRecoveryFileReady?: (file: RecoveryShareFile, filename: string) => Promise<void>;
270
+ /** Prompt for a recovery-share file (and its password) during Flow B. Return null to cancel. */
271
+ promptForRecoveryFile?: () => Promise<{
272
+ value: unknown;
273
+ getPassword: () => Promise<string | null>;
274
+ } | null>;
275
+ /**
276
+ * Every successful recovery/rotation invalidates the previous recovery
277
+ * file — this MUST prompt for a new password and block progress until the
278
+ * dApp confirms the user saved the new file (see MIGRATE_SSS_RECOVERY.md §10).
279
+ */
280
+ onRecoveryRotated?: (addresses: {
281
+ evmAddress: string;
282
+ solanaAddress: string;
283
+ }) => Promise<{
284
+ password: string;
285
+ passwordHint?: string;
286
+ }>;
287
+ /** Recovery stage callbacks, for dApp UI. */
288
+ onRecoveryProgress?: (event: RecoveryProgress) => void;
289
+ }
290
+ interface ConnectResult {
291
+ addresses: {
292
+ evm?: string;
293
+ solana?: string;
294
+ };
295
+ isNewUser: boolean;
296
+ }
297
+ interface SignMessageRequest {
298
+ chain: Chain;
299
+ message: string | Uint8Array;
300
+ }
301
+ interface SendTransactionRequest {
302
+ chain: Chain;
303
+ to: string;
304
+ value?: bigint;
305
+ data?: string;
306
+ gasLimit?: bigint;
307
+ gasPrice?: bigint;
308
+ }
309
+ type SdkEvent = 'connected' | 'disconnected' | 'session-expired' | 'session-started';
310
+ interface DecaneConnect {
311
+ connect(): Promise<ConnectResult>;
312
+ connectWithGoogle(): Promise<ConnectResult>;
313
+ connectWithEmail(email: string): Promise<{
314
+ codeRequired: true;
315
+ }>;
316
+ verifyEmailCode(email: string, code: string): Promise<ConnectResult>;
317
+ unlock(): Promise<void>;
318
+ isUnlocked(): boolean;
319
+ sessionExpiresAt(): number | null;
320
+ signMessage(req: SignMessageRequest): Promise<string>;
321
+ sendTransaction(req: SendTransactionRequest): Promise<string>;
322
+ signSolanaTransaction(tx: Uint8Array): Promise<Uint8Array>;
323
+ disconnect(): Promise<void>;
324
+ getAddresses(): {
325
+ evm?: string;
326
+ solana?: string;
327
+ } | null;
328
+ /**
329
+ * Voluntary share rotation — after a suspected device compromise, or just
330
+ * to invalidate an old recovery file. Requires a fresh WebAuthn assertion.
331
+ * Returns the new recovery-share file (the caller still owns delivering it
332
+ * to the user — this does not download anything itself).
333
+ */
334
+ rotateShares(opts: {
335
+ password: string;
336
+ passwordHint?: string;
337
+ }): Promise<RecoveryShareFile>;
338
+ /**
339
+ * The two-share bearer portable backup (device + recovery). This file plus
340
+ * its password gives complete control of the wallet — see the mandatory
341
+ * warning-screen requirements in MIGRATE_SSS_RECOVERY.md §10. Requires a
342
+ * fresh WebAuthn assertion and rotates the share set on every export.
343
+ */
344
+ exportPortableBackup(opts: {
345
+ password: string;
346
+ passwordHint?: string;
347
+ }): Promise<PortableBackup>;
348
+ /** Whether the user has ever saved a recovery-share file (UX flag only — Decane never stores the share). */
349
+ hasRecoveryShare(): Promise<boolean>;
350
+ /** True at most once per account: no recovery share saved, never nagged, wallet holds value. */
351
+ shouldPromptRecovery(): Promise<boolean>;
352
+ /** Call regardless of the user's answer — the recovery nag fires once, ever. */
353
+ dismissRecoveryPrompt(): Promise<void>;
354
+ /** Whether a wrapped-share backup exists on the server. */
355
+ hasBackup(): Promise<boolean>;
356
+ /** Delete the server-side backup. Disables Flow A recovery. */
357
+ deleteBackup(): Promise<void>;
358
+ on(event: SdkEvent, handler: (...args: unknown[]) => void): void;
359
+ off(event: SdkEvent, handler: (...args: unknown[]) => void): void;
360
+ }
361
+ interface WrappedShareMeta {
362
+ unlockMethod: 'passkey' | 'pin';
363
+ credentialId?: string;
364
+ prfSalt?: string;
365
+ pinSalt?: string;
366
+ pinIterations?: number;
367
+ }
368
+ interface AuthResult {
369
+ jwt: string;
370
+ isNewUser: boolean;
371
+ hasShare: boolean;
372
+ userId: string;
373
+ }
374
+
375
+ declare function createDecaneConnect(config: DecaneConnectConfig): Promise<DecaneConnect>;
376
+
377
+ /**
378
+ * Sends a 6-digit magic-link code to the user's email.
379
+ * Always returns void regardless of whether the email exists (prevents enumeration).
380
+ */
381
+ declare function startEmailAuth(api: ApiClient, email: string): Promise<void>;
382
+ /**
383
+ * Verifies the 6-digit code and exchanges it for a JWT.
384
+ */
385
+ declare function verifyEmailCode(api: ApiClient, email: string, code: string): Promise<AuthResult>;
386
+
387
+ declare class DecaneConnectError extends Error {
388
+ code: string;
389
+ retryable: boolean;
390
+ constructor(code: string, message: string, retryable?: boolean);
391
+ }
392
+ declare class InvalidApiKeyError extends DecaneConnectError {
393
+ constructor();
394
+ }
395
+ declare class OriginNotAllowedError extends DecaneConnectError {
396
+ constructor(origin: string);
397
+ }
398
+ declare class SessionExpiredError extends DecaneConnectError {
399
+ constructor();
400
+ }
401
+ declare class UnlockRequiredError extends DecaneConnectError {
402
+ constructor();
403
+ }
404
+ declare class UserCancelledError extends DecaneConnectError {
405
+ constructor();
406
+ }
407
+ declare class WebAuthnNotSupportedError extends DecaneConnectError {
408
+ constructor();
409
+ }
410
+ declare class InvalidPinError extends DecaneConnectError {
411
+ constructor();
412
+ }
413
+ declare class CallSequenceError extends DecaneConnectError {
414
+ constructor(msg: string);
415
+ }
416
+ declare class NetworkError extends DecaneConnectError {
417
+ constructor();
418
+ }
419
+ declare class ShareCorruptedError extends DecaneConnectError {
420
+ constructor();
421
+ }
422
+ declare class NewDeviceError extends DecaneConnectError {
423
+ constructor();
424
+ }
425
+ declare class PromptPinNotConfiguredError extends DecaneConnectError {
426
+ constructor();
427
+ }
428
+ declare class AttestationError extends DecaneConnectError {
429
+ constructor(msg: string);
430
+ }
431
+ declare class RecoveryFailedError extends DecaneConnectError {
432
+ constructor(reason: string);
433
+ }
434
+ declare class InvalidRecoveryFileError extends DecaneConnectError {
435
+ constructor();
436
+ }
437
+ declare class WrongPasswordError extends DecaneConnectError {
438
+ constructor();
439
+ }
440
+ declare class RecoveryWalletMismatchError extends DecaneConnectError {
441
+ constructor();
442
+ }
443
+ declare class ExportNotAuthorizedError extends DecaneConnectError {
444
+ constructor();
445
+ }
446
+
125
447
  declare class DecaneError extends Error {
126
448
  code: DecaneErrorCode;
127
449
  constructor(code: DecaneErrorCode, message: string);
@@ -217,16 +539,91 @@ interface WalletSelectorProps {
217
539
  onConnect: (wallet: UnifiedWalletAccount, preference?: ChainType) => void;
218
540
  theme?: "light" | "dark" | "auto";
219
541
  networks?: "evm" | "solana" | "tron" | "bitcoin" | "all";
542
+ mode?: ConnectMode;
543
+ socialAuthMethods?: ("google" | "email")[];
544
+ onGoogleSignIn?: () => Promise<void>;
545
+ onEmailStart?: (email: string) => Promise<{
546
+ codeRequired: true;
547
+ }>;
548
+ onEmailVerify?: (email: string, code: string) => Promise<void>;
220
549
  }
221
- declare function WalletSelector({ provider, open, onClose, onConnect, theme, networks, }: WalletSelectorProps): React.ReactPortal | null;
550
+ declare function WalletSelector({ provider, open, onClose, onConnect, theme, networks, mode, socialAuthMethods, onGoogleSignIn, onEmailStart, onEmailVerify, }: WalletSelectorProps): React.ReactPortal | null;
222
551
 
223
552
  type Theme = "light" | "dark" | "auto";
553
+ interface SocialAuthState {
554
+ addresses: {
555
+ evm?: string;
556
+ solana?: string;
557
+ } | null;
558
+ isNewUser: boolean;
559
+ isUnlocked: boolean;
560
+ sessionExpiresAt: number | null;
561
+ }
224
562
  interface DecaneKitProps {
225
563
  config?: DecaneConfig;
226
564
  children: ReactNode;
227
565
  }
228
566
  declare function DecaneKit({ config, children }: DecaneKitProps): React.JSX.Element;
229
567
 
568
+ interface SocialWalletModalProps {
569
+ open: boolean;
570
+ onClose: () => void;
571
+ theme?: "light" | "dark" | "auto";
572
+ socialAuth: SocialAuthState;
573
+ onUnlock: () => Promise<void>;
574
+ onDisconnect: () => Promise<void>;
575
+ }
576
+ declare function SocialWalletModal({ open, onClose, theme, socialAuth, onUnlock, onDisconnect, }: SocialWalletModalProps): React.ReactPortal | null;
577
+
578
+ declare function useSocialAuth(): {
579
+ isConnected: boolean;
580
+ isUnlocked: boolean;
581
+ isNewUser: boolean;
582
+ addresses: {
583
+ evm?: string;
584
+ solana?: string;
585
+ } | null;
586
+ sessionExpiresAt: number | null;
587
+ googleLoading: boolean;
588
+ emailLoading: boolean;
589
+ error: string | null;
590
+ clearError: () => void;
591
+ signInWithGoogle: () => Promise<void>;
592
+ sendEmailCode: (email: string) => Promise<{
593
+ codeRequired: true;
594
+ }>;
595
+ confirmEmailCode: (email: string, code: string) => Promise<void>;
596
+ unlock: () => Promise<void>;
597
+ disconnect: () => Promise<void>;
598
+ };
599
+ declare function useSocialWallet(): {
600
+ isConnected: boolean;
601
+ isUnlocked: boolean;
602
+ isNewUser: boolean;
603
+ addresses: {
604
+ evm?: string;
605
+ solana?: string;
606
+ } | null;
607
+ sessionExpiresAt: number | null;
608
+ modalOpen: boolean;
609
+ openModal: () => void;
610
+ closeModal: () => void;
611
+ unlock: () => Promise<void>;
612
+ disconnect: () => Promise<void>;
613
+ signMessage: (chain: string, message: string | Uint8Array) => Promise<string>;
614
+ sendTransaction: (req: {
615
+ chain: string;
616
+ to: string;
617
+ value?: bigint;
618
+ data?: string;
619
+ gasLimit?: bigint;
620
+ gasPrice?: bigint;
621
+ }) => Promise<string>;
622
+ signSolanaTransaction: (tx: Uint8Array) => Promise<Uint8Array<ArrayBufferLike>>;
623
+ loading: boolean;
624
+ error: string | null;
625
+ clearError: () => void;
626
+ };
230
627
  declare function useDecane(): {
231
628
  provider: DecaneProvider;
232
629
  wallets: UnifiedWalletAccount[];
@@ -299,4 +696,4 @@ declare function useSignTypedData(): {
299
696
  reset: () => void;
300
697
  };
301
698
 
302
- export { type ActiveSession, BUILT_IN_CHAINS, type CAIP25Method, type CAIP25SessionRequest, type CAIP25SessionResult, CHAINS, type ChainDescriptor, type ChainId, type ChainScope, type ChainSupport, type ChainType, type DecaneConfig, DecaneError, DecaneErrorCode, DecaneKit, type DecaneProvider, type Theme, type TxParams, type UnifiedWalletAccount, WalletSelector, createDecane, useChainSwitch, useDecane, useSendTransaction, useSignMessage, useSignTypedData, useWalletSelector };
699
+ export { type ActiveSession, AttestationError, type AuthResult, BUILT_IN_CHAINS, type CAIP25Method, type CAIP25SessionRequest, type CAIP25SessionResult, CHAINS, CallSequenceError, type Chain, type ChainDescriptor, type ChainId, type ChainScope, type ChainSupport, type ChainType, type ConnectMode, type ConnectResult, type DecaneConfig, type DecaneConnect, type DecaneConnectConfig, DecaneConnectError, DecaneError, DecaneErrorCode, DecaneKit, type DecaneProvider, ExportNotAuthorizedError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPinNotConfiguredError, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SocialAuthState, type SocialConfig, SocialWalletModal, type Theme, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UserCancelledError, WalletSelector, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, createDecane, createDecaneConnect, startEmailAuth, useChainSwitch, useDecane, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialWallet, useWalletSelector, verifyEmailCode };