decane-connect-kit 2.22.0 → 2.24.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.cjs +186 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -2
- package/dist/index.d.ts +56 -2
- package/dist/index.js +185 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -146,6 +146,19 @@ interface DecaneConnectConfig {
|
|
|
146
146
|
* page load (stricter, but the reload friction that motivated this returns).
|
|
147
147
|
*/
|
|
148
148
|
persistSession?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Do not wrap and store this device's share at wallet creation or when a
|
|
151
|
+
* device is first provisioned — so sign-in asks for no passkey and no
|
|
152
|
+
* password. The session works without a stored share: signing runs on the
|
|
153
|
+
* open session, and a later visit provisions a fresh share against a live
|
|
154
|
+
* sign-in. What the device loses until it is protected is the short way
|
|
155
|
+
* back in (passkey / password unlock) — every visit is a full sign-in.
|
|
156
|
+
*
|
|
157
|
+
* Call `protectDevice()` at the moment the app wants that step, typically
|
|
158
|
+
* before the user's first transaction. `deviceProtected()` says whether it
|
|
159
|
+
* has happened. Default false: the share is wrapped and stored at creation.
|
|
160
|
+
*/
|
|
161
|
+
deferDeviceProtection?: boolean;
|
|
149
162
|
/**
|
|
150
163
|
* Offer to save a recovery-share file at signup. **Default false** since
|
|
151
164
|
* 2.7.4 — opt in explicitly with `true`.
|
|
@@ -345,6 +358,19 @@ interface DecaneConnect {
|
|
|
345
358
|
connectWithToken(token: string, opts?: {
|
|
346
359
|
providerId?: string;
|
|
347
360
|
}): Promise<ConnectResult>;
|
|
361
|
+
/**
|
|
362
|
+
* Adopt a Decane access token another app of the same project handed over
|
|
363
|
+
* (in a URL, say): signed in at once, unlocked on the first signature.
|
|
364
|
+
*
|
|
365
|
+
* The token is the one every API call carries as a Bearer. The backend
|
|
366
|
+
* judges it — a revoked or foreign token is refused — and the session lasts
|
|
367
|
+
* as long as the token does, at most two hours; when it lapses the client
|
|
368
|
+
* emits `session-expired` and reads as signed out. No enclave session is
|
|
369
|
+
* opened: the first `unlock()` (or any signing call) provisions or unwraps
|
|
370
|
+
* the device share as an ordinary returning sign-in would, and with
|
|
371
|
+
* `deferDeviceProtection` prompts for nothing.
|
|
372
|
+
*/
|
|
373
|
+
connectWithAccessToken(token: string): Promise<ConnectResult>;
|
|
348
374
|
verifyEmailCode(email: string, code: string): Promise<ConnectResult>;
|
|
349
375
|
/**
|
|
350
376
|
* Send a 6-digit sign-in code by SMS (delivered via Termii).
|
|
@@ -428,6 +454,21 @@ interface DecaneConnect {
|
|
|
428
454
|
* on the way).
|
|
429
455
|
*/
|
|
430
456
|
addPasskey(): Promise<void>;
|
|
457
|
+
/**
|
|
458
|
+
* Whether this device holds a wrapped share for the signed-in account, i.e.
|
|
459
|
+
* whether a passkey or password protects the wallet here. False on a device
|
|
460
|
+
* created with `deferDeviceProtection`, or whose share was never written.
|
|
461
|
+
*/
|
|
462
|
+
deviceProtected(): Promise<boolean>;
|
|
463
|
+
/**
|
|
464
|
+
* Wrap and store this device's share now: a passkey where the device can
|
|
465
|
+
* hold one, otherwise the unlock password (`promptUnlockPassword`). Needs a
|
|
466
|
+
* live session; provisions a fresh share from the enclave when the device
|
|
467
|
+
* has none. Idempotent — a protected device returns true at once. Resolves
|
|
468
|
+
* false when the user dismissed the prompt, so the app can decide whether
|
|
469
|
+
* to go on without protection; throws for anything else.
|
|
470
|
+
*/
|
|
471
|
+
protectDevice(): Promise<boolean>;
|
|
431
472
|
sessionExpiresAt(): number | null;
|
|
432
473
|
signMessage(req: SignMessageRequest): Promise<string>;
|
|
433
474
|
sendTransaction(req: SendTransactionRequest): Promise<string>;
|
|
@@ -533,7 +574,7 @@ interface DecaneConnect {
|
|
|
533
574
|
off(event: SdkEvent, handler: (...args: unknown[]) => void): void;
|
|
534
575
|
}
|
|
535
576
|
interface WrappedShareMeta {
|
|
536
|
-
unlockMethod: 'passkey' | 'pin' | 'password';
|
|
577
|
+
unlockMethod: 'passkey' | 'pin' | 'password' | 'deferred';
|
|
537
578
|
credentialId?: string;
|
|
538
579
|
prfSalt?: string;
|
|
539
580
|
pinSalt?: string;
|
|
@@ -847,6 +888,13 @@ interface SocialConfig {
|
|
|
847
888
|
* a silent multi-second pause reads as a broken page.
|
|
848
889
|
*/
|
|
849
890
|
showStatusOverlay?: boolean;
|
|
891
|
+
/**
|
|
892
|
+
* Ask for no passkey or password at sign-in; protect the wallet on this
|
|
893
|
+
* device later, when the app calls `protectDevice()` (typically before the
|
|
894
|
+
* first transaction). Mirrors the headless client's option of the same name;
|
|
895
|
+
* see it for what a device gives up until then. Default false.
|
|
896
|
+
*/
|
|
897
|
+
deferDeviceProtection?: boolean;
|
|
850
898
|
/**
|
|
851
899
|
* Offer to save a recovery-share file at signup. **Default false** since
|
|
852
900
|
* 2.7.4 — opt in explicitly with `true`.
|
|
@@ -1095,6 +1143,9 @@ declare class PromptPasswordNotConfiguredError extends DecaneConnectError {
|
|
|
1095
1143
|
declare class WrongUnlockPasswordError extends DecaneConnectError {
|
|
1096
1144
|
constructor();
|
|
1097
1145
|
}
|
|
1146
|
+
declare class InvalidAccessTokenError extends DecaneConnectError {
|
|
1147
|
+
constructor(reason: string);
|
|
1148
|
+
}
|
|
1098
1149
|
declare class UnlockTokenRejectedError extends DecaneConnectError {
|
|
1099
1150
|
constructor();
|
|
1100
1151
|
}
|
|
@@ -1388,6 +1439,7 @@ declare function useSocialAuth(): {
|
|
|
1388
1439
|
signInWithToken: (token: string, opts?: {
|
|
1389
1440
|
providerId?: string;
|
|
1390
1441
|
}) => Promise<void>;
|
|
1442
|
+
signInWithAccessToken: (token: string) => Promise<void>;
|
|
1391
1443
|
signInWithCustomAuth: (() => Promise<void>) | undefined;
|
|
1392
1444
|
signInWithPasskey: () => Promise<void>;
|
|
1393
1445
|
unlock: () => Promise<void>;
|
|
@@ -1448,6 +1500,8 @@ declare function useSocialWallet(): {
|
|
|
1448
1500
|
getAccessToken: () => string | null;
|
|
1449
1501
|
hasPasskey: () => Promise<boolean>;
|
|
1450
1502
|
addPasskey: () => Promise<void>;
|
|
1503
|
+
deviceProtected: () => Promise<boolean>;
|
|
1504
|
+
protectDevice: () => Promise<boolean>;
|
|
1451
1505
|
setUnlockPassword: (password: string) => Promise<void>;
|
|
1452
1506
|
canUnlockWithPassword: () => Promise<boolean>;
|
|
1453
1507
|
unlockWithPassword: (password: string) => Promise<void>;
|
|
@@ -1561,4 +1615,4 @@ declare class WeakPasswordError extends Error {
|
|
|
1561
1615
|
*/
|
|
1562
1616
|
declare function validateUnlockPassword(password: string): void;
|
|
1563
1617
|
|
|
1564
|
-
export { type ActiveSession, AttestationError, type AuthProfile, type AuthResult, BUILT_IN_CHAINS, type BalanceResult, 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, DecaneLogo, DecaneMark, type DecaneProvider, DecaneWordmark, type Eip1193Provider, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, type KingsChatTokens, MIN_PASSWORD_LENGTH, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPasswordNotConfiguredError, PromptPinNotConfiguredError, ProvisioningTimeoutError, ReconnectRequiredError, type RecordTransactionInput, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SignTypedDataRequest, type SignedAuthorization, type SocialAuthState, type SocialConfig, SocialWalletModal, StaleDeviceShareError, type Theme, type TransactionRecord, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UnlockTokenRejectedError, UserCancelledError, WalletSelector, WeakPasswordError, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, WrongUnlockPasswordError, createDecane, createDecaneConnect, createEthereumProvider, loginWithKingsChatPopup, startEmailAuth, useChainSwitch, useDecane, useEthereumProvider, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, validateUnlockPassword, verifyEmailCode };
|
|
1618
|
+
export { type ActiveSession, AttestationError, type AuthProfile, type AuthResult, BUILT_IN_CHAINS, type BalanceResult, 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, DecaneLogo, DecaneMark, type DecaneProvider, DecaneWordmark, type Eip1193Provider, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidAccessTokenError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, type KingsChatTokens, MIN_PASSWORD_LENGTH, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPasswordNotConfiguredError, PromptPinNotConfiguredError, ProvisioningTimeoutError, ReconnectRequiredError, type RecordTransactionInput, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SignTypedDataRequest, type SignedAuthorization, type SocialAuthState, type SocialConfig, SocialWalletModal, StaleDeviceShareError, type Theme, type TransactionRecord, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UnlockTokenRejectedError, UserCancelledError, WalletSelector, WeakPasswordError, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, WrongUnlockPasswordError, createDecane, createDecaneConnect, createEthereumProvider, loginWithKingsChatPopup, startEmailAuth, useChainSwitch, useDecane, useEthereumProvider, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, validateUnlockPassword, verifyEmailCode };
|
package/dist/index.d.ts
CHANGED
|
@@ -146,6 +146,19 @@ interface DecaneConnectConfig {
|
|
|
146
146
|
* page load (stricter, but the reload friction that motivated this returns).
|
|
147
147
|
*/
|
|
148
148
|
persistSession?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Do not wrap and store this device's share at wallet creation or when a
|
|
151
|
+
* device is first provisioned — so sign-in asks for no passkey and no
|
|
152
|
+
* password. The session works without a stored share: signing runs on the
|
|
153
|
+
* open session, and a later visit provisions a fresh share against a live
|
|
154
|
+
* sign-in. What the device loses until it is protected is the short way
|
|
155
|
+
* back in (passkey / password unlock) — every visit is a full sign-in.
|
|
156
|
+
*
|
|
157
|
+
* Call `protectDevice()` at the moment the app wants that step, typically
|
|
158
|
+
* before the user's first transaction. `deviceProtected()` says whether it
|
|
159
|
+
* has happened. Default false: the share is wrapped and stored at creation.
|
|
160
|
+
*/
|
|
161
|
+
deferDeviceProtection?: boolean;
|
|
149
162
|
/**
|
|
150
163
|
* Offer to save a recovery-share file at signup. **Default false** since
|
|
151
164
|
* 2.7.4 — opt in explicitly with `true`.
|
|
@@ -345,6 +358,19 @@ interface DecaneConnect {
|
|
|
345
358
|
connectWithToken(token: string, opts?: {
|
|
346
359
|
providerId?: string;
|
|
347
360
|
}): Promise<ConnectResult>;
|
|
361
|
+
/**
|
|
362
|
+
* Adopt a Decane access token another app of the same project handed over
|
|
363
|
+
* (in a URL, say): signed in at once, unlocked on the first signature.
|
|
364
|
+
*
|
|
365
|
+
* The token is the one every API call carries as a Bearer. The backend
|
|
366
|
+
* judges it — a revoked or foreign token is refused — and the session lasts
|
|
367
|
+
* as long as the token does, at most two hours; when it lapses the client
|
|
368
|
+
* emits `session-expired` and reads as signed out. No enclave session is
|
|
369
|
+
* opened: the first `unlock()` (or any signing call) provisions or unwraps
|
|
370
|
+
* the device share as an ordinary returning sign-in would, and with
|
|
371
|
+
* `deferDeviceProtection` prompts for nothing.
|
|
372
|
+
*/
|
|
373
|
+
connectWithAccessToken(token: string): Promise<ConnectResult>;
|
|
348
374
|
verifyEmailCode(email: string, code: string): Promise<ConnectResult>;
|
|
349
375
|
/**
|
|
350
376
|
* Send a 6-digit sign-in code by SMS (delivered via Termii).
|
|
@@ -428,6 +454,21 @@ interface DecaneConnect {
|
|
|
428
454
|
* on the way).
|
|
429
455
|
*/
|
|
430
456
|
addPasskey(): Promise<void>;
|
|
457
|
+
/**
|
|
458
|
+
* Whether this device holds a wrapped share for the signed-in account, i.e.
|
|
459
|
+
* whether a passkey or password protects the wallet here. False on a device
|
|
460
|
+
* created with `deferDeviceProtection`, or whose share was never written.
|
|
461
|
+
*/
|
|
462
|
+
deviceProtected(): Promise<boolean>;
|
|
463
|
+
/**
|
|
464
|
+
* Wrap and store this device's share now: a passkey where the device can
|
|
465
|
+
* hold one, otherwise the unlock password (`promptUnlockPassword`). Needs a
|
|
466
|
+
* live session; provisions a fresh share from the enclave when the device
|
|
467
|
+
* has none. Idempotent — a protected device returns true at once. Resolves
|
|
468
|
+
* false when the user dismissed the prompt, so the app can decide whether
|
|
469
|
+
* to go on without protection; throws for anything else.
|
|
470
|
+
*/
|
|
471
|
+
protectDevice(): Promise<boolean>;
|
|
431
472
|
sessionExpiresAt(): number | null;
|
|
432
473
|
signMessage(req: SignMessageRequest): Promise<string>;
|
|
433
474
|
sendTransaction(req: SendTransactionRequest): Promise<string>;
|
|
@@ -533,7 +574,7 @@ interface DecaneConnect {
|
|
|
533
574
|
off(event: SdkEvent, handler: (...args: unknown[]) => void): void;
|
|
534
575
|
}
|
|
535
576
|
interface WrappedShareMeta {
|
|
536
|
-
unlockMethod: 'passkey' | 'pin' | 'password';
|
|
577
|
+
unlockMethod: 'passkey' | 'pin' | 'password' | 'deferred';
|
|
537
578
|
credentialId?: string;
|
|
538
579
|
prfSalt?: string;
|
|
539
580
|
pinSalt?: string;
|
|
@@ -847,6 +888,13 @@ interface SocialConfig {
|
|
|
847
888
|
* a silent multi-second pause reads as a broken page.
|
|
848
889
|
*/
|
|
849
890
|
showStatusOverlay?: boolean;
|
|
891
|
+
/**
|
|
892
|
+
* Ask for no passkey or password at sign-in; protect the wallet on this
|
|
893
|
+
* device later, when the app calls `protectDevice()` (typically before the
|
|
894
|
+
* first transaction). Mirrors the headless client's option of the same name;
|
|
895
|
+
* see it for what a device gives up until then. Default false.
|
|
896
|
+
*/
|
|
897
|
+
deferDeviceProtection?: boolean;
|
|
850
898
|
/**
|
|
851
899
|
* Offer to save a recovery-share file at signup. **Default false** since
|
|
852
900
|
* 2.7.4 — opt in explicitly with `true`.
|
|
@@ -1095,6 +1143,9 @@ declare class PromptPasswordNotConfiguredError extends DecaneConnectError {
|
|
|
1095
1143
|
declare class WrongUnlockPasswordError extends DecaneConnectError {
|
|
1096
1144
|
constructor();
|
|
1097
1145
|
}
|
|
1146
|
+
declare class InvalidAccessTokenError extends DecaneConnectError {
|
|
1147
|
+
constructor(reason: string);
|
|
1148
|
+
}
|
|
1098
1149
|
declare class UnlockTokenRejectedError extends DecaneConnectError {
|
|
1099
1150
|
constructor();
|
|
1100
1151
|
}
|
|
@@ -1388,6 +1439,7 @@ declare function useSocialAuth(): {
|
|
|
1388
1439
|
signInWithToken: (token: string, opts?: {
|
|
1389
1440
|
providerId?: string;
|
|
1390
1441
|
}) => Promise<void>;
|
|
1442
|
+
signInWithAccessToken: (token: string) => Promise<void>;
|
|
1391
1443
|
signInWithCustomAuth: (() => Promise<void>) | undefined;
|
|
1392
1444
|
signInWithPasskey: () => Promise<void>;
|
|
1393
1445
|
unlock: () => Promise<void>;
|
|
@@ -1448,6 +1500,8 @@ declare function useSocialWallet(): {
|
|
|
1448
1500
|
getAccessToken: () => string | null;
|
|
1449
1501
|
hasPasskey: () => Promise<boolean>;
|
|
1450
1502
|
addPasskey: () => Promise<void>;
|
|
1503
|
+
deviceProtected: () => Promise<boolean>;
|
|
1504
|
+
protectDevice: () => Promise<boolean>;
|
|
1451
1505
|
setUnlockPassword: (password: string) => Promise<void>;
|
|
1452
1506
|
canUnlockWithPassword: () => Promise<boolean>;
|
|
1453
1507
|
unlockWithPassword: (password: string) => Promise<void>;
|
|
@@ -1561,4 +1615,4 @@ declare class WeakPasswordError extends Error {
|
|
|
1561
1615
|
*/
|
|
1562
1616
|
declare function validateUnlockPassword(password: string): void;
|
|
1563
1617
|
|
|
1564
|
-
export { type ActiveSession, AttestationError, type AuthProfile, type AuthResult, BUILT_IN_CHAINS, type BalanceResult, 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, DecaneLogo, DecaneMark, type DecaneProvider, DecaneWordmark, type Eip1193Provider, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, type KingsChatTokens, MIN_PASSWORD_LENGTH, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPasswordNotConfiguredError, PromptPinNotConfiguredError, ProvisioningTimeoutError, ReconnectRequiredError, type RecordTransactionInput, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SignTypedDataRequest, type SignedAuthorization, type SocialAuthState, type SocialConfig, SocialWalletModal, StaleDeviceShareError, type Theme, type TransactionRecord, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UnlockTokenRejectedError, UserCancelledError, WalletSelector, WeakPasswordError, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, WrongUnlockPasswordError, createDecane, createDecaneConnect, createEthereumProvider, loginWithKingsChatPopup, startEmailAuth, useChainSwitch, useDecane, useEthereumProvider, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, validateUnlockPassword, verifyEmailCode };
|
|
1618
|
+
export { type ActiveSession, AttestationError, type AuthProfile, type AuthResult, BUILT_IN_CHAINS, type BalanceResult, 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, DecaneLogo, DecaneMark, type DecaneProvider, DecaneWordmark, type Eip1193Provider, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidAccessTokenError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, type KingsChatTokens, MIN_PASSWORD_LENGTH, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPasswordNotConfiguredError, PromptPinNotConfiguredError, ProvisioningTimeoutError, ReconnectRequiredError, type RecordTransactionInput, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SignTypedDataRequest, type SignedAuthorization, type SocialAuthState, type SocialConfig, SocialWalletModal, StaleDeviceShareError, type Theme, type TransactionRecord, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UnlockTokenRejectedError, UserCancelledError, WalletSelector, WeakPasswordError, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, WrongUnlockPasswordError, createDecane, createDecaneConnect, createEthereumProvider, loginWithKingsChatPopup, startEmailAuth, useChainSwitch, useDecane, useEthereumProvider, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, validateUnlockPassword, verifyEmailCode };
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ __export(errors_exports, {
|
|
|
15
15
|
CallSequenceError: () => CallSequenceError,
|
|
16
16
|
DecaneConnectError: () => DecaneConnectError,
|
|
17
17
|
ExportNotAuthorizedError: () => ExportNotAuthorizedError,
|
|
18
|
+
InvalidAccessTokenError: () => InvalidAccessTokenError,
|
|
18
19
|
InvalidApiKeyError: () => InvalidApiKeyError,
|
|
19
20
|
InvalidPinError: () => InvalidPinError,
|
|
20
21
|
InvalidRecoveryFileError: () => InvalidRecoveryFileError,
|
|
@@ -37,7 +38,7 @@ __export(errors_exports, {
|
|
|
37
38
|
WrongPasswordError: () => WrongPasswordError,
|
|
38
39
|
WrongUnlockPasswordError: () => WrongUnlockPasswordError
|
|
39
40
|
});
|
|
40
|
-
var DecaneConnectError, InvalidApiKeyError, OriginNotAllowedError, SessionExpiredError, UnlockRequiredError, ReconnectRequiredError, UserCancelledError, WebAuthnNotSupportedError, InvalidPinError, CallSequenceError, NetworkError, ShareCorruptedError, ProvisioningTimeoutError, NewDeviceError, StaleDeviceShareError, PromptPinNotConfiguredError, PromptPasswordNotConfiguredError, WrongUnlockPasswordError, UnlockTokenRejectedError, AttestationError, RecoveryFailedError, InvalidRecoveryFileError, WrongPasswordError, RecoveryWalletMismatchError, ExportNotAuthorizedError;
|
|
41
|
+
var DecaneConnectError, InvalidApiKeyError, OriginNotAllowedError, SessionExpiredError, UnlockRequiredError, ReconnectRequiredError, UserCancelledError, WebAuthnNotSupportedError, InvalidPinError, CallSequenceError, NetworkError, ShareCorruptedError, ProvisioningTimeoutError, NewDeviceError, StaleDeviceShareError, PromptPinNotConfiguredError, PromptPasswordNotConfiguredError, WrongUnlockPasswordError, InvalidAccessTokenError, UnlockTokenRejectedError, AttestationError, RecoveryFailedError, InvalidRecoveryFileError, WrongPasswordError, RecoveryWalletMismatchError, ExportNotAuthorizedError;
|
|
41
42
|
var init_errors = __esm({
|
|
42
43
|
"src/social/errors.ts"() {
|
|
43
44
|
"use strict";
|
|
@@ -142,6 +143,11 @@ var init_errors = __esm({
|
|
|
142
143
|
super("WRONG_UNLOCK_PASSWORD", "That password did not unlock this device");
|
|
143
144
|
}
|
|
144
145
|
};
|
|
146
|
+
InvalidAccessTokenError = class extends DecaneConnectError {
|
|
147
|
+
constructor(reason) {
|
|
148
|
+
super("INVALID_ACCESS_TOKEN", `That access token cannot open a session: ${reason}`);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
145
151
|
UnlockTokenRejectedError = class extends DecaneConnectError {
|
|
146
152
|
constructor() {
|
|
147
153
|
super("UNLOCK_TOKEN_REJECTED", "This device's unlock token is no longer valid \u2014 sign in normally to re-enable password unlock");
|
|
@@ -2273,6 +2279,20 @@ function b64ToBytes(b644) {
|
|
|
2273
2279
|
return Uint8Array.from(atob(b644), (c) => c.charCodeAt(0));
|
|
2274
2280
|
}
|
|
2275
2281
|
|
|
2282
|
+
// src/social/accessToken.ts
|
|
2283
|
+
function decodeAccessToken(token) {
|
|
2284
|
+
try {
|
|
2285
|
+
const payload = token.split(".")[1];
|
|
2286
|
+
if (!payload) return null;
|
|
2287
|
+
const json = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
|
|
2288
|
+
if (typeof json.uid !== "string" || json.uid === "") return null;
|
|
2289
|
+
if (typeof json.exp !== "number" || !Number.isFinite(json.exp)) return null;
|
|
2290
|
+
return { userId: json.uid, expiresAt: json.exp * 1e3 };
|
|
2291
|
+
} catch {
|
|
2292
|
+
return null;
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2276
2296
|
// src/social/storage.ts
|
|
2277
2297
|
import { openDB } from "idb";
|
|
2278
2298
|
var DB_NAME = "decane-connect-kit";
|
|
@@ -3667,8 +3687,10 @@ async function createDecaneConnect(config) {
|
|
|
3667
3687
|
const durationMs = (config.sessionDurationMinutes ?? DEFAULT_SESSION_MINUTES) * 6e4;
|
|
3668
3688
|
const rpId = config.rpId ?? (typeof window !== "undefined" ? window.location.hostname : "localhost");
|
|
3669
3689
|
const rpName = config.rpName ?? "Decane Connect";
|
|
3670
|
-
const PERSIST_KEY = makePersistKey(config.
|
|
3671
|
-
const LAST_USER_KEY = makeLastUserKey(config.
|
|
3690
|
+
const PERSIST_KEY = makePersistKey(config.appId);
|
|
3691
|
+
const LAST_USER_KEY = makeLastUserKey(config.appId);
|
|
3692
|
+
const LEGACY_PERSIST_KEY = makePersistKey(config.apiKey);
|
|
3693
|
+
const LEGACY_LAST_USER_KEY = makeLastUserKey(config.apiKey);
|
|
3672
3694
|
const teeUrl = config.teeUrl ?? DEFAULT_TEE_URL;
|
|
3673
3695
|
const events = new EventEmitter();
|
|
3674
3696
|
const api = new ApiClient(baseUrl, config.apiKey, config.appId);
|
|
@@ -3681,9 +3703,17 @@ async function createDecaneConnect(config) {
|
|
|
3681
3703
|
);
|
|
3682
3704
|
let auth = null;
|
|
3683
3705
|
let persisted = loadPersisted(PERSIST_KEY);
|
|
3684
|
-
|
|
3706
|
+
if (!persisted && LEGACY_PERSIST_KEY !== PERSIST_KEY) {
|
|
3707
|
+
persisted = loadPersisted(LEGACY_PERSIST_KEY);
|
|
3708
|
+
if (persisted) {
|
|
3709
|
+
savePersisted(PERSIST_KEY, persisted);
|
|
3710
|
+
clearPersisted(LEGACY_PERSIST_KEY);
|
|
3711
|
+
}
|
|
3712
|
+
}
|
|
3713
|
+
let lastUserId = loadLastUser(LAST_USER_KEY) ?? (LEGACY_LAST_USER_KEY !== LAST_USER_KEY ? loadLastUser(LEGACY_LAST_USER_KEY) : null);
|
|
3685
3714
|
let ethProvider = null;
|
|
3686
3715
|
const persistSession = config.persistSession !== false;
|
|
3716
|
+
const deferDeviceProtection = config.deferDeviceProtection === true;
|
|
3687
3717
|
const serverAssistedRecovery = true;
|
|
3688
3718
|
const RECOVERY_OFFER_TIMEOUT_MS = 5 * 6e4;
|
|
3689
3719
|
const selfHealAttempted = /* @__PURE__ */ new Set();
|
|
@@ -3743,12 +3773,13 @@ async function createDecaneConnect(config) {
|
|
|
3743
3773
|
})
|
|
3744
3774
|
]).finally(() => clearTimeout(timer));
|
|
3745
3775
|
}
|
|
3746
|
-
const SESSION_KEY = sessionPersistKey(config.
|
|
3776
|
+
const SESSION_KEY = sessionPersistKey(config.appId);
|
|
3777
|
+
const LEGACY_SESSION_KEY = sessionPersistKey(config.apiKey);
|
|
3747
3778
|
function persistLiveSession() {
|
|
3748
|
-
if (!persistSession) return;
|
|
3779
|
+
if (!persistSession || !auth) return;
|
|
3749
3780
|
const handle = session.getHandle();
|
|
3750
|
-
const expiresAt = session.expiresAtTimestamp();
|
|
3751
|
-
if (!
|
|
3781
|
+
const expiresAt = handle ? session.expiresAtTimestamp() : decodeAccessToken(auth.jwt)?.expiresAt ?? null;
|
|
3782
|
+
if (!expiresAt) return;
|
|
3752
3783
|
saveSession(SESSION_KEY, {
|
|
3753
3784
|
handle,
|
|
3754
3785
|
jwt: auth.jwt,
|
|
@@ -3760,11 +3791,23 @@ async function createDecaneConnect(config) {
|
|
|
3760
3791
|
function dropLiveSession() {
|
|
3761
3792
|
clearSessionPersist(SESSION_KEY);
|
|
3762
3793
|
}
|
|
3794
|
+
let accessTokenExpiry = null;
|
|
3795
|
+
function scheduleAccessTokenExpiry(jwt, expiresAt) {
|
|
3796
|
+
if (accessTokenExpiry) clearTimeout(accessTokenExpiry);
|
|
3797
|
+
accessTokenExpiry = setTimeout(() => {
|
|
3798
|
+
accessTokenExpiry = null;
|
|
3799
|
+
if (auth?.jwt !== jwt || session.isActive()) return;
|
|
3800
|
+
auth = null;
|
|
3801
|
+
dropLiveSession();
|
|
3802
|
+
events.emit("session-expired");
|
|
3803
|
+
}, Math.max(0, expiresAt - Date.now()));
|
|
3804
|
+
}
|
|
3763
3805
|
if (persistSession) {
|
|
3764
|
-
const saved = loadSession(SESSION_KEY);
|
|
3765
|
-
if (saved
|
|
3806
|
+
const saved = loadSession(SESSION_KEY) ?? (LEGACY_SESSION_KEY !== SESSION_KEY ? loadSession(LEGACY_SESSION_KEY) : null);
|
|
3807
|
+
if (saved && saved.expiresAt > Date.now() + 5e3) {
|
|
3766
3808
|
try {
|
|
3767
|
-
session.resume(saved.handle, saved.addresses, saved.expiresAt);
|
|
3809
|
+
if (saved.handle) session.resume(saved.handle, saved.addresses, saved.expiresAt);
|
|
3810
|
+
else scheduleAccessTokenExpiry(saved.jwt, saved.expiresAt);
|
|
3768
3811
|
auth = { jwt: saved.jwt, userId: saved.userId, addresses: saved.addresses };
|
|
3769
3812
|
persisted = { userId: saved.userId, addresses: saved.addresses };
|
|
3770
3813
|
} catch {
|
|
@@ -3773,6 +3816,7 @@ async function createDecaneConnect(config) {
|
|
|
3773
3816
|
} else if (saved) {
|
|
3774
3817
|
dropLiveSession();
|
|
3775
3818
|
}
|
|
3819
|
+
if (LEGACY_SESSION_KEY !== SESSION_KEY) clearSessionPersist(LEGACY_SESSION_KEY);
|
|
3776
3820
|
}
|
|
3777
3821
|
events.on("session-expired", () => dropLiveSession());
|
|
3778
3822
|
async function passwordSetup() {
|
|
@@ -3995,11 +4039,12 @@ async function createDecaneConnect(config) {
|
|
|
3995
4039
|
}
|
|
3996
4040
|
async function firstTimeSetup(userId, jwt) {
|
|
3997
4041
|
prewarmAttestation(teeUrl);
|
|
3998
|
-
let unlockMethod;
|
|
3999
|
-
let wrappingKey;
|
|
4042
|
+
let unlockMethod = "password";
|
|
4043
|
+
let wrappingKey = null;
|
|
4000
4044
|
let meta = {};
|
|
4001
4045
|
let unlockTokenKey = null;
|
|
4002
|
-
if (
|
|
4046
|
+
if (deferDeviceProtection) {
|
|
4047
|
+
} else if (isPasskeySupported()) {
|
|
4003
4048
|
const prfSalt = generateRandomBytes(32);
|
|
4004
4049
|
try {
|
|
4005
4050
|
const { credentialId, prfOutput } = await registerWebAuthnCredential({ api, jwt, rpId, rpName, prfSalt });
|
|
@@ -4040,32 +4085,37 @@ async function createDecaneConnect(config) {
|
|
|
4040
4085
|
} finally {
|
|
4041
4086
|
zeroize(master);
|
|
4042
4087
|
}
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4088
|
+
let wrappedDeviceShare = null;
|
|
4089
|
+
let iv = null;
|
|
4090
|
+
if (wrappingKey) {
|
|
4091
|
+
iv = generateRandomBytes(12);
|
|
4092
|
+
wrappedDeviceShare = await aesGcmEncrypt(
|
|
4093
|
+
wrappingKey,
|
|
4094
|
+
shareSet.device,
|
|
4095
|
+
iv
|
|
4096
|
+
);
|
|
4097
|
+
await storage.putShare({
|
|
4098
|
+
userId,
|
|
4099
|
+
wrappedDeviceShare,
|
|
4100
|
+
iv,
|
|
4101
|
+
unlockMethod,
|
|
4102
|
+
credentialId: meta.credentialId ? b64uToBuffer(meta.credentialId) : void 0,
|
|
4103
|
+
prfSalt: meta.prfSalt ? b64uToBuffer(meta.prfSalt) : void 0,
|
|
4104
|
+
pinSalt: meta.pinSalt ? b64uToBuffer(meta.pinSalt) : void 0,
|
|
4105
|
+
pinIterations: meta.pinIterations,
|
|
4106
|
+
passwordSalt: meta.passwordSalt ? b64uToBuffer(meta.passwordSalt) : void 0,
|
|
4107
|
+
passwordIterations: meta.passwordIterations,
|
|
4108
|
+
version: 1
|
|
4109
|
+
});
|
|
4110
|
+
if (unlockTokenKey) await attachUnlockToken(userId, jwt, unlockTokenKey);
|
|
4111
|
+
}
|
|
4063
4112
|
const serverIv = generateRandomBytes(12);
|
|
4064
4113
|
await withDeadline(api.putShare(jwt, {
|
|
4065
4114
|
ciphertext: shareSet.server,
|
|
4066
4115
|
iv: serverIv,
|
|
4067
4116
|
wrappedShareMeta: {
|
|
4068
|
-
|
|
4117
|
+
// The server records this on the wallet_created event and nothing else.
|
|
4118
|
+
unlockMethod: deferDeviceProtection ? "deferred" : unlockMethod
|
|
4069
4119
|
// credential IDs, prfSalt, pinSalt stay on-device — never sent to server
|
|
4070
4120
|
},
|
|
4071
4121
|
evmAddress,
|
|
@@ -4074,7 +4124,7 @@ async function createDecaneConnect(config) {
|
|
|
4074
4124
|
}), remainingBudget(), "storing your wallet");
|
|
4075
4125
|
zeroize(shareSet.server);
|
|
4076
4126
|
const addresses = { evm: evmAddress, solana: solanaAddress, tron: tronAddress };
|
|
4077
|
-
if (unlockMethod === "passkey" && meta.credentialId && meta.prfSalt) {
|
|
4127
|
+
if (unlockMethod === "passkey" && meta.credentialId && meta.prfSalt && wrappedDeviceShare && iv) {
|
|
4078
4128
|
try {
|
|
4079
4129
|
await api.putRecoveryBackup(jwt, {
|
|
4080
4130
|
wrappedDeviceShare,
|
|
@@ -4157,7 +4207,7 @@ async function createDecaneConnect(config) {
|
|
|
4157
4207
|
const tee = new TeeClient(teeUrl);
|
|
4158
4208
|
const provisioned = await tee.provisionDeviceShare(jwt);
|
|
4159
4209
|
if (provisioned) {
|
|
4160
|
-
await persistProvisionedShare(userId, jwt, provisioned);
|
|
4210
|
+
if (!deferDeviceProtection) await persistProvisionedShare(userId, jwt, provisioned);
|
|
4161
4211
|
let addrs;
|
|
4162
4212
|
try {
|
|
4163
4213
|
addrs = await session.start(provisioned, jwt, recordedAddresses);
|
|
@@ -4201,7 +4251,7 @@ async function createDecaneConnect(config) {
|
|
|
4201
4251
|
});
|
|
4202
4252
|
deviceShare = recovered.deviceShare;
|
|
4203
4253
|
joinedViaPasskeySync = recovered.flow === "passkey-sync";
|
|
4204
|
-
if (!await storage.getShare(userId) && isPasskeySupported()) {
|
|
4254
|
+
if (!deferDeviceProtection && !await storage.getShare(userId) && isPasskeySupported()) {
|
|
4205
4255
|
await registerPasskeyAndBackup(userId, jwt, deviceShare);
|
|
4206
4256
|
}
|
|
4207
4257
|
} else {
|
|
@@ -4484,6 +4534,27 @@ async function createDecaneConnect(config) {
|
|
|
4484
4534
|
const result = await api.authExternal(token, opts?.providerId);
|
|
4485
4535
|
return handleAuthResult(result);
|
|
4486
4536
|
},
|
|
4537
|
+
async connectWithAccessToken(token) {
|
|
4538
|
+
const claims = decodeAccessToken(token);
|
|
4539
|
+
if (!claims) throw new InvalidAccessTokenError("not a Decane access token");
|
|
4540
|
+
if (claims.expiresAt <= Date.now() + 5e3) throw new InvalidAccessTokenError("it has expired");
|
|
4541
|
+
const raw = await api.getAddresses(token);
|
|
4542
|
+
if (!raw.evm || !raw.solana) throw new InvalidAccessTokenError("this account holds no wallet yet");
|
|
4543
|
+
const addresses = { evm: raw.evm, solana: raw.solana, tron: raw.tron ?? evmToTronAddress2(raw.evm) };
|
|
4544
|
+
if (session.isActive()) session.end();
|
|
4545
|
+
auth = { jwt: token, userId: claims.userId, addresses };
|
|
4546
|
+
persisted = { userId: claims.userId, addresses };
|
|
4547
|
+
savePersisted(PERSIST_KEY, persisted);
|
|
4548
|
+
events.emit("connected");
|
|
4549
|
+
persistLiveSession();
|
|
4550
|
+
scheduleAccessTokenExpiry(token, claims.expiresAt);
|
|
4551
|
+
const stored = await storage.getShare(claims.userId);
|
|
4552
|
+
return {
|
|
4553
|
+
addresses,
|
|
4554
|
+
isNewUser: false,
|
|
4555
|
+
...stored?.profile ? { profile: stored.profile } : {}
|
|
4556
|
+
};
|
|
4557
|
+
},
|
|
4487
4558
|
async connectWithEmail(email) {
|
|
4488
4559
|
await startEmailAuth(api, email);
|
|
4489
4560
|
return { codeRequired: true };
|
|
@@ -4672,6 +4743,24 @@ async function createDecaneConnect(config) {
|
|
|
4672
4743
|
zeroize(deviceShare);
|
|
4673
4744
|
}
|
|
4674
4745
|
},
|
|
4746
|
+
async deviceProtected() {
|
|
4747
|
+
if (!auth) return false;
|
|
4748
|
+
return await storage.getShare(auth.userId) !== null;
|
|
4749
|
+
},
|
|
4750
|
+
async protectDevice() {
|
|
4751
|
+
if (!auth) throw new ReconnectRequiredError();
|
|
4752
|
+
if (await storage.getShare(auth.userId)) return true;
|
|
4753
|
+
if (!serverAssistedRecovery) throw new NewDeviceError();
|
|
4754
|
+
const tee = new TeeClient(teeUrl);
|
|
4755
|
+
const provisioned = await tee.provisionDeviceShare(auth.jwt);
|
|
4756
|
+
if (!provisioned) throw new NewDeviceError();
|
|
4757
|
+
try {
|
|
4758
|
+
await persistProvisionedShare(auth.userId, auth.jwt, provisioned);
|
|
4759
|
+
} finally {
|
|
4760
|
+
zeroize(provisioned);
|
|
4761
|
+
}
|
|
4762
|
+
return await storage.getShare(auth.userId) !== null;
|
|
4763
|
+
},
|
|
4675
4764
|
async unlock() {
|
|
4676
4765
|
if (!auth) {
|
|
4677
4766
|
const candidate = await passkeyLoginCandidate();
|
|
@@ -7301,6 +7390,7 @@ function DecaneKit({ config, children }) {
|
|
|
7301
7390
|
chains,
|
|
7302
7391
|
rpcUrls,
|
|
7303
7392
|
requireAssertionPerSignature,
|
|
7393
|
+
deferDeviceProtection,
|
|
7304
7394
|
// Recovery callbacks. Forwarding these is what makes recovery
|
|
7305
7395
|
// configurable at all from <DecaneKit>; before, they were silently
|
|
7306
7396
|
// dropped and the headless client was constructed without them.
|
|
@@ -7321,6 +7411,7 @@ function DecaneKit({ config, children }) {
|
|
|
7321
7411
|
promptPin,
|
|
7322
7412
|
promptUnlockPassword,
|
|
7323
7413
|
requireAssertionPerSignature,
|
|
7414
|
+
deferDeviceProtection,
|
|
7324
7415
|
offerRecoveryAtSignup,
|
|
7325
7416
|
onRecoveryShareOffer,
|
|
7326
7417
|
onRecoveryFileReady,
|
|
@@ -7456,6 +7547,18 @@ function DecaneKit({ config, children }) {
|
|
|
7456
7547
|
throw e;
|
|
7457
7548
|
}
|
|
7458
7549
|
}, [clearPhase]);
|
|
7550
|
+
const connectWithAccessToken = useCallback3(async (token) => {
|
|
7551
|
+
const sdk = socialRef.current;
|
|
7552
|
+
if (!sdk) throw new Error("Social sign-in not configured");
|
|
7553
|
+
try {
|
|
7554
|
+
const result = await sdk.connectWithAccessToken(token);
|
|
7555
|
+
applyResult(result);
|
|
7556
|
+
setSelectorOpen(false);
|
|
7557
|
+
} catch (e) {
|
|
7558
|
+
clearPhase();
|
|
7559
|
+
throw e;
|
|
7560
|
+
}
|
|
7561
|
+
}, [clearPhase]);
|
|
7459
7562
|
const customAuthConfig = config?.social?.customAuth;
|
|
7460
7563
|
const connectWithCustomAuth = useCallback3(async () => {
|
|
7461
7564
|
if (!customAuthConfig) throw new Error("Custom auth not configured");
|
|
@@ -7567,6 +7670,16 @@ function DecaneKit({ config, children }) {
|
|
|
7567
7670
|
if (!sdk) throw new Error("Social wallet not connected");
|
|
7568
7671
|
return sdk.addPasskey();
|
|
7569
7672
|
}, []);
|
|
7673
|
+
const socialDeviceProtected = useCallback3(async () => {
|
|
7674
|
+
const sdk = socialRef.current;
|
|
7675
|
+
if (!sdk) return false;
|
|
7676
|
+
return sdk.deviceProtected();
|
|
7677
|
+
}, []);
|
|
7678
|
+
const socialProtectDevice = useCallback3(async () => {
|
|
7679
|
+
const sdk = socialRef.current;
|
|
7680
|
+
if (!sdk) throw new Error("Social wallet not connected");
|
|
7681
|
+
return sdk.protectDevice();
|
|
7682
|
+
}, []);
|
|
7570
7683
|
const socialSetUnlockPassword = useCallback3(async (password) => {
|
|
7571
7684
|
const sdk = socialRef.current;
|
|
7572
7685
|
if (!sdk) throw new Error("Social wallet not connected");
|
|
@@ -7638,6 +7751,7 @@ function DecaneKit({ config, children }) {
|
|
|
7638
7751
|
connectWithPhone,
|
|
7639
7752
|
verifyPhoneCode: verifyPhoneCode2,
|
|
7640
7753
|
connectWithToken,
|
|
7754
|
+
connectWithAccessToken,
|
|
7641
7755
|
customAuthLabel: customAuthConfig?.label,
|
|
7642
7756
|
connectWithCustomAuth: customAuthConfig ? connectWithCustomAuth : void 0,
|
|
7643
7757
|
socialUnlock,
|
|
@@ -7659,6 +7773,8 @@ function DecaneKit({ config, children }) {
|
|
|
7659
7773
|
socialHasRecoveryShare,
|
|
7660
7774
|
socialHasPasskey,
|
|
7661
7775
|
socialAddPasskey,
|
|
7776
|
+
socialDeviceProtected,
|
|
7777
|
+
socialProtectDevice,
|
|
7662
7778
|
socialSetUnlockPassword,
|
|
7663
7779
|
socialCanUnlockWithPassword,
|
|
7664
7780
|
socialForgetLastUser,
|
|
@@ -7751,6 +7867,7 @@ function useSocialAuth() {
|
|
|
7751
7867
|
connectWithPhone,
|
|
7752
7868
|
verifyPhoneCode: verifyPhoneCode2,
|
|
7753
7869
|
connectWithToken,
|
|
7870
|
+
connectWithAccessToken,
|
|
7754
7871
|
customAuthLabel,
|
|
7755
7872
|
connectWithCustomAuth,
|
|
7756
7873
|
signInWithPasskey: ctxSignInWithPasskey,
|
|
@@ -7859,6 +7976,18 @@ function useSocialAuth() {
|
|
|
7859
7976
|
setTokenLoading(false);
|
|
7860
7977
|
}
|
|
7861
7978
|
}, [connectWithToken]);
|
|
7979
|
+
const signInWithAccessToken = useCallback4(async (token) => {
|
|
7980
|
+
setTokenLoading(true);
|
|
7981
|
+
setError(null);
|
|
7982
|
+
try {
|
|
7983
|
+
await connectWithAccessToken(token);
|
|
7984
|
+
} catch (e) {
|
|
7985
|
+
setError(e.message);
|
|
7986
|
+
throw e;
|
|
7987
|
+
} finally {
|
|
7988
|
+
setTokenLoading(false);
|
|
7989
|
+
}
|
|
7990
|
+
}, [connectWithAccessToken]);
|
|
7862
7991
|
const signInWithCustomAuth = useCallback4(async () => {
|
|
7863
7992
|
if (!connectWithCustomAuth) throw new Error("Custom auth not configured");
|
|
7864
7993
|
setCustomLoading(true);
|
|
@@ -7941,6 +8070,7 @@ function useSocialAuth() {
|
|
|
7941
8070
|
sendPhoneCode,
|
|
7942
8071
|
confirmPhoneCode,
|
|
7943
8072
|
signInWithToken,
|
|
8073
|
+
signInWithAccessToken,
|
|
7944
8074
|
signInWithCustomAuth: connectWithCustomAuth ? signInWithCustomAuth : void 0,
|
|
7945
8075
|
signInWithPasskey,
|
|
7946
8076
|
unlock,
|
|
@@ -7969,6 +8099,8 @@ function useSocialWallet() {
|
|
|
7969
8099
|
socialHasRecoveryShare,
|
|
7970
8100
|
socialHasPasskey,
|
|
7971
8101
|
socialAddPasskey,
|
|
8102
|
+
socialDeviceProtected,
|
|
8103
|
+
socialProtectDevice,
|
|
7972
8104
|
socialSetUnlockPassword,
|
|
7973
8105
|
socialCanUnlockWithPassword,
|
|
7974
8106
|
socialForgetLastUser,
|
|
@@ -8071,6 +8203,16 @@ function useSocialWallet() {
|
|
|
8071
8203
|
throw e;
|
|
8072
8204
|
}
|
|
8073
8205
|
}, [socialAddPasskey]);
|
|
8206
|
+
const deviceProtected = useCallback4(() => run(() => socialDeviceProtected()), [socialDeviceProtected]);
|
|
8207
|
+
const protectDevice = useCallback4(async () => {
|
|
8208
|
+
setError(null);
|
|
8209
|
+
try {
|
|
8210
|
+
return await socialProtectDevice();
|
|
8211
|
+
} catch (e) {
|
|
8212
|
+
setError(e.message);
|
|
8213
|
+
throw e;
|
|
8214
|
+
}
|
|
8215
|
+
}, [socialProtectDevice]);
|
|
8074
8216
|
const setUnlockPassword = useCallback4(async (password) => {
|
|
8075
8217
|
setError(null);
|
|
8076
8218
|
try {
|
|
@@ -8159,6 +8301,10 @@ function useSocialWallet() {
|
|
|
8159
8301
|
// Passkey management for THIS device
|
|
8160
8302
|
hasPasskey,
|
|
8161
8303
|
addPasskey,
|
|
8304
|
+
// Deferred protection (deferDeviceProtection): whether this device holds
|
|
8305
|
+
// a wrapped share, and the call that stores one — passkey or password.
|
|
8306
|
+
deviceProtected,
|
|
8307
|
+
protectDevice,
|
|
8162
8308
|
// "Unlock with your password": setUnlockPassword needs a live session;
|
|
8163
8309
|
// canUnlockWithPassword and unlockWithPassword are the signed-out pair that
|
|
8164
8310
|
// open one without an identity provider or a passkey.
|
|
@@ -8473,6 +8619,7 @@ export {
|
|
|
8473
8619
|
DecaneMark,
|
|
8474
8620
|
DecaneWordmark,
|
|
8475
8621
|
ExportNotAuthorizedError,
|
|
8622
|
+
InvalidAccessTokenError,
|
|
8476
8623
|
InvalidApiKeyError,
|
|
8477
8624
|
InvalidPinError,
|
|
8478
8625
|
InvalidRecoveryFileError,
|