decane-connect-kit 2.29.2 → 2.30.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
@@ -431,6 +431,31 @@ interface DecaneConnect {
431
431
  connectWithToken(token: string, opts?: {
432
432
  providerId?: string;
433
433
  }): Promise<ConnectResult>;
434
+ /**
435
+ * Attach a login from your own auth system to the account that is signed in
436
+ * now, so that login opens this same wallet from then on. The usual case:
437
+ * someone signed up by email adds a phone number your backend verified, and
438
+ * can then sign in with either. Needs a signed-in session.
439
+ *
440
+ * The token must be fresh (it carries `exp` and `iat`, and was issued in the
441
+ * last ten minutes). A login that already opens a different account throws
442
+ * LoginInUseError: accounts are never merged. Linking one that is already
443
+ * on this account is a no-op (`alreadyLinked: true`). Since 2.30.0.
444
+ */
445
+ linkWithToken(token: string, opts?: {
446
+ providerId?: string;
447
+ }): Promise<{
448
+ alreadyLinked: boolean;
449
+ id?: string;
450
+ }>;
451
+ /** The logins linked to the signed-in account with linkWithToken(). Since 2.30.0. */
452
+ listLinkedLogins(): Promise<LinkedLogin[]>;
453
+ /**
454
+ * Remove a linked login, for "change my number": sign in, unlink the old one,
455
+ * link the new one. The login the account was created with cannot be removed.
456
+ * Since 2.30.0.
457
+ */
458
+ unlinkLogin(id: string): Promise<void>;
434
459
  /**
435
460
  * Adopt a Decane access token another app of the same project handed over
436
461
  * (in a URL, say): signed in at once, unlocked on the first signature.
@@ -700,6 +725,16 @@ interface AuthResult {
700
725
  */
701
726
  providerSubject?: string;
702
727
  }
728
+ /** A login attached to an account with linkWithToken(). */
729
+ interface LinkedLogin {
730
+ id: string;
731
+ providerId: string | null;
732
+ /** The provider's name as set in the dashboard, e.g. "World Street phone". */
733
+ providerName: string | null;
734
+ /** Masked, for display: never the full identifier. */
735
+ identifier: string | null;
736
+ linkedAt: string;
737
+ }
703
738
 
704
739
  declare class ApiClient {
705
740
  private readonly baseUrl;
@@ -782,6 +817,16 @@ declare class ApiClient {
782
817
  * provider configured.
783
818
  */
784
819
  authExternal(token: string, providerId?: string): Promise<AuthResult>;
820
+ /** Attach a login from the project's own provider to the signed-in account. */
821
+ linkExternal(jwt: string, token: string, providerId?: string): Promise<{
822
+ linked: true;
823
+ alreadyLinked: boolean;
824
+ id?: string;
825
+ }>;
826
+ listLinkedLogins(jwt: string): Promise<{
827
+ logins: LinkedLogin[];
828
+ }>;
829
+ unlinkLogin(jwt: string, id: string): Promise<void>;
785
830
  /**
786
831
  * Returns null when this user has no server-registered passkey, which is the
787
832
  * expected answer for wallets created before passkey sign-in existed or for
@@ -1292,6 +1337,14 @@ declare class ExportNotAuthorizedError extends DecaneConnectError {
1292
1337
  * The client discards what it generated and provisions instead; nothing for
1293
1338
  * the caller to do, which is why this never reaches them.
1294
1339
  */
1340
+ /**
1341
+ * linkWithToken(): that login already opens a different account (someone signed
1342
+ * up with that phone number on its own, say). Decane never merges two accounts,
1343
+ * because each is its own key and its own addresses, so it was not linked.
1344
+ */
1345
+ declare class LoginInUseError extends DecaneConnectError {
1346
+ constructor(message?: string);
1347
+ }
1295
1348
  declare class WalletExistsError extends DecaneConnectError {
1296
1349
  constructor();
1297
1350
  }
@@ -1597,6 +1650,14 @@ declare function useSocialAuth(): {
1597
1650
  providerId?: string;
1598
1651
  }) => Promise<void>;
1599
1652
  signInWithAccessToken: (token: string) => Promise<void>;
1653
+ linkWithToken: (token: string, opts?: {
1654
+ providerId?: string;
1655
+ }) => Promise<{
1656
+ alreadyLinked: boolean;
1657
+ id?: string;
1658
+ }>;
1659
+ listLinkedLogins: () => Promise<LinkedLogin[]>;
1660
+ unlinkLogin: (id: string) => Promise<void>;
1600
1661
  signInWithCustomAuth: (() => Promise<void>) | undefined;
1601
1662
  signInWithPasskey: () => Promise<void>;
1602
1663
  unlock: () => Promise<void>;
@@ -1772,4 +1833,4 @@ declare class WeakPasswordError extends Error {
1772
1833
  */
1773
1834
  declare function validateUnlockPassword(password: string): void;
1774
1835
 
1775
- 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, EnclaveHttpError, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidAccessTokenError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, type KingsChatTokens, MIN_PASSWORD_LENGTH, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPasswordNotConfiguredError, PromptPinNotConfiguredError, ProvisioningRateLimitedError, 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, WalletEnrolmentError, WalletExistsError, WalletSelector, WeakPasswordError, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, WrongUnlockPasswordError, createDecane, createDecaneConnect, createEthereumProvider, loginWithKingsChatPopup, startEmailAuth, useChainSwitch, useDecane, useEthereumProvider, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, validateUnlockPassword, verifyEmailCode };
1836
+ 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, EnclaveHttpError, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidAccessTokenError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, type KingsChatTokens, type LinkedLogin, LoginInUseError, MIN_PASSWORD_LENGTH, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPasswordNotConfiguredError, PromptPinNotConfiguredError, ProvisioningRateLimitedError, 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, WalletEnrolmentError, WalletExistsError, 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
@@ -431,6 +431,31 @@ interface DecaneConnect {
431
431
  connectWithToken(token: string, opts?: {
432
432
  providerId?: string;
433
433
  }): Promise<ConnectResult>;
434
+ /**
435
+ * Attach a login from your own auth system to the account that is signed in
436
+ * now, so that login opens this same wallet from then on. The usual case:
437
+ * someone signed up by email adds a phone number your backend verified, and
438
+ * can then sign in with either. Needs a signed-in session.
439
+ *
440
+ * The token must be fresh (it carries `exp` and `iat`, and was issued in the
441
+ * last ten minutes). A login that already opens a different account throws
442
+ * LoginInUseError: accounts are never merged. Linking one that is already
443
+ * on this account is a no-op (`alreadyLinked: true`). Since 2.30.0.
444
+ */
445
+ linkWithToken(token: string, opts?: {
446
+ providerId?: string;
447
+ }): Promise<{
448
+ alreadyLinked: boolean;
449
+ id?: string;
450
+ }>;
451
+ /** The logins linked to the signed-in account with linkWithToken(). Since 2.30.0. */
452
+ listLinkedLogins(): Promise<LinkedLogin[]>;
453
+ /**
454
+ * Remove a linked login, for "change my number": sign in, unlink the old one,
455
+ * link the new one. The login the account was created with cannot be removed.
456
+ * Since 2.30.0.
457
+ */
458
+ unlinkLogin(id: string): Promise<void>;
434
459
  /**
435
460
  * Adopt a Decane access token another app of the same project handed over
436
461
  * (in a URL, say): signed in at once, unlocked on the first signature.
@@ -700,6 +725,16 @@ interface AuthResult {
700
725
  */
701
726
  providerSubject?: string;
702
727
  }
728
+ /** A login attached to an account with linkWithToken(). */
729
+ interface LinkedLogin {
730
+ id: string;
731
+ providerId: string | null;
732
+ /** The provider's name as set in the dashboard, e.g. "World Street phone". */
733
+ providerName: string | null;
734
+ /** Masked, for display: never the full identifier. */
735
+ identifier: string | null;
736
+ linkedAt: string;
737
+ }
703
738
 
704
739
  declare class ApiClient {
705
740
  private readonly baseUrl;
@@ -782,6 +817,16 @@ declare class ApiClient {
782
817
  * provider configured.
783
818
  */
784
819
  authExternal(token: string, providerId?: string): Promise<AuthResult>;
820
+ /** Attach a login from the project's own provider to the signed-in account. */
821
+ linkExternal(jwt: string, token: string, providerId?: string): Promise<{
822
+ linked: true;
823
+ alreadyLinked: boolean;
824
+ id?: string;
825
+ }>;
826
+ listLinkedLogins(jwt: string): Promise<{
827
+ logins: LinkedLogin[];
828
+ }>;
829
+ unlinkLogin(jwt: string, id: string): Promise<void>;
785
830
  /**
786
831
  * Returns null when this user has no server-registered passkey, which is the
787
832
  * expected answer for wallets created before passkey sign-in existed or for
@@ -1292,6 +1337,14 @@ declare class ExportNotAuthorizedError extends DecaneConnectError {
1292
1337
  * The client discards what it generated and provisions instead; nothing for
1293
1338
  * the caller to do, which is why this never reaches them.
1294
1339
  */
1340
+ /**
1341
+ * linkWithToken(): that login already opens a different account (someone signed
1342
+ * up with that phone number on its own, say). Decane never merges two accounts,
1343
+ * because each is its own key and its own addresses, so it was not linked.
1344
+ */
1345
+ declare class LoginInUseError extends DecaneConnectError {
1346
+ constructor(message?: string);
1347
+ }
1295
1348
  declare class WalletExistsError extends DecaneConnectError {
1296
1349
  constructor();
1297
1350
  }
@@ -1597,6 +1650,14 @@ declare function useSocialAuth(): {
1597
1650
  providerId?: string;
1598
1651
  }) => Promise<void>;
1599
1652
  signInWithAccessToken: (token: string) => Promise<void>;
1653
+ linkWithToken: (token: string, opts?: {
1654
+ providerId?: string;
1655
+ }) => Promise<{
1656
+ alreadyLinked: boolean;
1657
+ id?: string;
1658
+ }>;
1659
+ listLinkedLogins: () => Promise<LinkedLogin[]>;
1660
+ unlinkLogin: (id: string) => Promise<void>;
1600
1661
  signInWithCustomAuth: (() => Promise<void>) | undefined;
1601
1662
  signInWithPasskey: () => Promise<void>;
1602
1663
  unlock: () => Promise<void>;
@@ -1772,4 +1833,4 @@ declare class WeakPasswordError extends Error {
1772
1833
  */
1773
1834
  declare function validateUnlockPassword(password: string): void;
1774
1835
 
1775
- 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, EnclaveHttpError, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidAccessTokenError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, type KingsChatTokens, MIN_PASSWORD_LENGTH, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPasswordNotConfiguredError, PromptPinNotConfiguredError, ProvisioningRateLimitedError, 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, WalletEnrolmentError, WalletExistsError, WalletSelector, WeakPasswordError, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, WrongUnlockPasswordError, createDecane, createDecaneConnect, createEthereumProvider, loginWithKingsChatPopup, startEmailAuth, useChainSwitch, useDecane, useEthereumProvider, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, validateUnlockPassword, verifyEmailCode };
1836
+ 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, EnclaveHttpError, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidAccessTokenError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, type KingsChatTokens, type LinkedLogin, LoginInUseError, MIN_PASSWORD_LENGTH, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPasswordNotConfiguredError, PromptPinNotConfiguredError, ProvisioningRateLimitedError, 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, WalletEnrolmentError, WalletExistsError, 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
@@ -20,6 +20,7 @@ __export(errors_exports, {
20
20
  InvalidApiKeyError: () => InvalidApiKeyError,
21
21
  InvalidPinError: () => InvalidPinError,
22
22
  InvalidRecoveryFileError: () => InvalidRecoveryFileError,
23
+ LoginInUseError: () => LoginInUseError,
23
24
  NetworkError: () => NetworkError,
24
25
  NewDeviceError: () => NewDeviceError,
25
26
  OriginNotAllowedError: () => OriginNotAllowedError,
@@ -42,7 +43,7 @@ __export(errors_exports, {
42
43
  WrongPasswordError: () => WrongPasswordError,
43
44
  WrongUnlockPasswordError: () => WrongUnlockPasswordError
44
45
  });
45
- 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, WalletExistsError, WalletEnrolmentError, ProvisioningRateLimitedError, EnclaveHttpError;
46
+ 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, LoginInUseError, WalletExistsError, WalletEnrolmentError, ProvisioningRateLimitedError, EnclaveHttpError;
46
47
  var init_errors = __esm({
47
48
  "src/social/errors.ts"() {
48
49
  "use strict";
@@ -191,6 +192,11 @@ var init_errors = __esm({
191
192
  super("EXPORT_NOT_AUTHORIZED", "Export requires a fresh security check", true);
192
193
  }
193
194
  };
195
+ LoginInUseError = class extends DecaneConnectError {
196
+ constructor(message = "That login already opens another account. It was not linked.") {
197
+ super("LOGIN_IN_USE", message);
198
+ }
199
+ };
194
200
  WalletExistsError = class extends DecaneConnectError {
195
201
  constructor() {
196
202
  super("WALLET_EXISTS", "This account already has a wallet; opening it instead.", true);
@@ -2031,7 +2037,9 @@ var ERROR_MAP = {
2031
2037
  // generic failure message.
2032
2038
  UNAUTHORIZED: ReconnectRequiredError,
2033
2039
  // A restorable wallet already exists: the client provisions instead of creating.
2034
- WALLET_EXISTS: WalletExistsError
2040
+ WALLET_EXISTS: WalletExistsError,
2041
+ // linkWithToken(): the login already opens another account.
2042
+ LOGIN_IN_USE: LoginInUseError
2035
2043
  };
2036
2044
  var REQUEST_TIMEOUT_MS = 3e4;
2037
2045
  var ApiClient = class {
@@ -2200,6 +2208,23 @@ var ApiClient = class {
2200
2208
  body: JSON.stringify(providerId ? { token, providerId } : { token })
2201
2209
  });
2202
2210
  }
2211
+ /** Attach a login from the project's own provider to the signed-in account. */
2212
+ async linkExternal(jwt, token, providerId) {
2213
+ return this._request("/auth/link/external", {
2214
+ method: "POST",
2215
+ headers: { Authorization: `Bearer ${jwt}` },
2216
+ body: JSON.stringify(providerId ? { token, providerId } : { token })
2217
+ });
2218
+ }
2219
+ async listLinkedLogins(jwt) {
2220
+ return this._request("/auth/link/external", { method: "GET", headers: { Authorization: `Bearer ${jwt}` } });
2221
+ }
2222
+ async unlinkLogin(jwt, id) {
2223
+ await this._request(`/auth/link/external/${encodeURIComponent(id)}`, {
2224
+ method: "DELETE",
2225
+ headers: { Authorization: `Bearer ${jwt}` }
2226
+ });
2227
+ }
2203
2228
  /**
2204
2229
  * Returns null when this user has no server-registered passkey, which is the
2205
2230
  * expected answer for wallets created before passkey sign-in existed or for
@@ -4872,6 +4897,20 @@ async function createDecaneConnect(config) {
4872
4897
  const result = await api.authExternal(token, opts?.providerId);
4873
4898
  return handleAuthResult(result);
4874
4899
  },
4900
+ async linkWithToken(token, opts) {
4901
+ if (!token) throw new CallSequenceError("linkWithToken requires a token");
4902
+ if (!auth) throw new ReconnectRequiredError();
4903
+ const result = await api.linkExternal(auth.jwt, token, opts?.providerId);
4904
+ return result.id ? { alreadyLinked: result.alreadyLinked, id: result.id } : { alreadyLinked: result.alreadyLinked };
4905
+ },
4906
+ async listLinkedLogins() {
4907
+ if (!auth) throw new ReconnectRequiredError();
4908
+ return (await api.listLinkedLogins(auth.jwt)).logins;
4909
+ },
4910
+ async unlinkLogin(id) {
4911
+ if (!auth) throw new ReconnectRequiredError();
4912
+ await api.unlinkLogin(auth.jwt, id);
4913
+ },
4875
4914
  async connectWithAccessToken(token) {
4876
4915
  const claims = decodeAccessToken(token);
4877
4916
  if (!claims) throw new InvalidAccessTokenError("not a Decane access token");
@@ -6960,6 +6999,21 @@ function DecaneKit({ config, children }) {
6960
6999
  throw e;
6961
7000
  }
6962
7001
  }, [clearPhase]);
7002
+ const linkWithToken = useCallback3(async (token, opts) => {
7003
+ const sdk = socialRef.current;
7004
+ if (!sdk) throw new Error("Social sign-in not configured");
7005
+ return sdk.linkWithToken(token, opts);
7006
+ }, []);
7007
+ const listLinkedLogins = useCallback3(async () => {
7008
+ const sdk = socialRef.current;
7009
+ if (!sdk) throw new Error("Social sign-in not configured");
7010
+ return sdk.listLinkedLogins();
7011
+ }, []);
7012
+ const unlinkLogin = useCallback3(async (id) => {
7013
+ const sdk = socialRef.current;
7014
+ if (!sdk) throw new Error("Social sign-in not configured");
7015
+ await sdk.unlinkLogin(id);
7016
+ }, []);
6963
7017
  const connectWithToken = useCallback3(async (token, opts) => {
6964
7018
  const sdk = socialRef.current;
6965
7019
  if (!sdk) throw new Error("Social sign-in not configured");
@@ -7177,6 +7231,9 @@ function DecaneKit({ config, children }) {
7177
7231
  verifyPhoneCode: verifyPhoneCode2,
7178
7232
  connectWithToken,
7179
7233
  connectWithAccessToken,
7234
+ linkWithToken,
7235
+ listLinkedLogins,
7236
+ unlinkLogin,
7180
7237
  customAuthLabel: customAuthConfig?.label,
7181
7238
  connectWithCustomAuth: customAuthConfig ? connectWithCustomAuth : void 0,
7182
7239
  socialUnlock,
@@ -7293,6 +7350,9 @@ function useSocialAuth() {
7293
7350
  verifyPhoneCode: verifyPhoneCode2,
7294
7351
  connectWithToken,
7295
7352
  connectWithAccessToken,
7353
+ linkWithToken,
7354
+ listLinkedLogins,
7355
+ unlinkLogin,
7296
7356
  customAuthLabel,
7297
7357
  connectWithCustomAuth,
7298
7358
  signInWithPasskey: ctxSignInWithPasskey,
@@ -7496,6 +7556,11 @@ function useSocialAuth() {
7496
7556
  confirmPhoneCode,
7497
7557
  signInWithToken,
7498
7558
  signInWithAccessToken,
7559
+ // Linked logins: while signed in, attach a login from your own auth (a
7560
+ // phone number your backend verified, say) so it opens this same wallet.
7561
+ linkWithToken,
7562
+ listLinkedLogins,
7563
+ unlinkLogin,
7499
7564
  signInWithCustomAuth: connectWithCustomAuth ? signInWithCustomAuth : void 0,
7500
7565
  signInWithPasskey,
7501
7566
  unlock,
@@ -8049,6 +8114,7 @@ export {
8049
8114
  InvalidApiKeyError,
8050
8115
  InvalidPinError,
8051
8116
  InvalidRecoveryFileError,
8117
+ LoginInUseError,
8052
8118
  MIN_PASSWORD_LENGTH,
8053
8119
  NetworkError,
8054
8120
  NewDeviceError,