decane-connect-kit 2.21.0 → 2.22.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 CHANGED
@@ -3689,6 +3689,29 @@ function clearPersisted(key) {
3689
3689
  } catch {
3690
3690
  }
3691
3691
  }
3692
+ function makeLastUserKey(apiKey) {
3693
+ return `${makePersistKey(apiKey)}:last-user`;
3694
+ }
3695
+ function loadLastUser(key) {
3696
+ try {
3697
+ const raw = typeof localStorage !== "undefined" ? localStorage.getItem(key) : null;
3698
+ return raw ? JSON.parse(raw).userId ?? null : null;
3699
+ } catch {
3700
+ return null;
3701
+ }
3702
+ }
3703
+ function saveLastUser(key, userId) {
3704
+ try {
3705
+ localStorage.setItem(key, JSON.stringify({ userId }));
3706
+ } catch {
3707
+ }
3708
+ }
3709
+ function clearLastUser(key) {
3710
+ try {
3711
+ localStorage.removeItem(key);
3712
+ } catch {
3713
+ }
3714
+ }
3692
3715
  function sessionPersistKey(apiKey) {
3693
3716
  return `decane:sess:${apiKey.slice(0, 20)}`;
3694
3717
  }
@@ -3727,6 +3750,7 @@ async function createDecaneConnect(config) {
3727
3750
  const rpId = config.rpId ?? (typeof window !== "undefined" ? window.location.hostname : "localhost");
3728
3751
  const rpName = config.rpName ?? "Decane Connect";
3729
3752
  const PERSIST_KEY = makePersistKey(config.apiKey);
3753
+ const LAST_USER_KEY = makeLastUserKey(config.apiKey);
3730
3754
  const teeUrl = config.teeUrl ?? DEFAULT_TEE_URL;
3731
3755
  const events = new EventEmitter();
3732
3756
  const api = new ApiClient(baseUrl, config.apiKey, config.appId);
@@ -3739,6 +3763,7 @@ async function createDecaneConnect(config) {
3739
3763
  );
3740
3764
  let auth = null;
3741
3765
  let persisted = loadPersisted(PERSIST_KEY);
3766
+ let lastUserId = loadLastUser(LAST_USER_KEY);
3742
3767
  let ethProvider = null;
3743
3768
  const persistSession = config.persistSession !== false;
3744
3769
  const serverAssistedRecovery = true;
@@ -3884,6 +3909,10 @@ async function createDecaneConnect(config) {
3884
3909
  const stored = await storage.getShare(persisted.userId);
3885
3910
  return hasPasswordUnlock(stored) ? stored : null;
3886
3911
  }
3912
+ if (lastUserId) {
3913
+ const stored = await storage.getShare(lastUserId);
3914
+ return hasPasswordUnlock(stored) ? stored : null;
3915
+ }
3887
3916
  const candidates = (await storage.listShares()).filter(hasPasswordUnlock);
3888
3917
  return candidates.length === 1 ? candidates[0] : null;
3889
3918
  }
@@ -4337,14 +4366,16 @@ async function createDecaneConnect(config) {
4337
4366
  async function passkeyDeviceCandidate() {
4338
4367
  if (!isPasskeySupported()) return null;
4339
4368
  if (persisted?.userId) return passkeyLoginCandidate();
4369
+ if (lastUserId) return usablePasskeyShare(await storage.getShare(lastUserId));
4340
4370
  const candidates = (await storage.listShares()).map(usablePasskeyShare).filter(Boolean);
4341
4371
  return candidates.length === 1 ? candidates[0] : null;
4342
4372
  }
4343
4373
  async function canOfferPasskey() {
4344
4374
  if (!isPasskeySupported()) return false;
4345
4375
  if (await passkeyDeviceCandidate()) return true;
4346
- if (!persisted?.userId) return false;
4347
- return await storage.getShare(persisted.userId) == null;
4376
+ const known = persisted?.userId ?? lastUserId;
4377
+ if (!known) return false;
4378
+ return await storage.getShare(known) == null;
4348
4379
  }
4349
4380
  async function rememberProfile(userId, profile) {
4350
4381
  const incoming = Object.fromEntries(Object.entries(profile).filter(([, v]) => v));
@@ -4557,8 +4588,9 @@ async function createDecaneConnect(config) {
4557
4588
  async signInWithPasskey() {
4558
4589
  const candidate = await passkeyDeviceCandidate();
4559
4590
  if (candidate) return passkeyLogin(candidate);
4560
- if (isPasskeySupported() && persisted?.userId && await storage.getShare(persisted.userId) == null) {
4561
- return passkeyLoginWithoutShare(persisted.userId);
4591
+ const known = persisted?.userId ?? lastUserId;
4592
+ if (isPasskeySupported() && known && await storage.getShare(known) == null) {
4593
+ return passkeyLoginWithoutShare(known);
4562
4594
  }
4563
4595
  throw new NewDeviceError();
4564
4596
  },
@@ -4898,12 +4930,21 @@ async function createDecaneConnect(config) {
4898
4930
  await api.revoke(auth.jwt).catch(() => {
4899
4931
  });
4900
4932
  }
4933
+ const leaving = auth?.userId ?? persisted?.userId ?? null;
4934
+ if (leaving) {
4935
+ lastUserId = leaving;
4936
+ saveLastUser(LAST_USER_KEY, leaving);
4937
+ }
4901
4938
  auth = null;
4902
4939
  persisted = null;
4903
4940
  clearPersisted(PERSIST_KEY);
4904
4941
  dropLiveSession();
4905
4942
  events.emit("disconnected");
4906
4943
  },
4944
+ forgetLastUser() {
4945
+ lastUserId = null;
4946
+ clearLastUser(LAST_USER_KEY);
4947
+ },
4907
4948
  getAddresses() {
4908
4949
  return auth?.addresses ?? persisted?.addresses ?? null;
4909
4950
  },
@@ -7611,6 +7652,14 @@ function DecaneKit({ config, children }) {
7611
7652
  if (!sdk) return false;
7612
7653
  return sdk.canUnlockWithPassword();
7613
7654
  }, []);
7655
+ const socialForgetLastUser = (0, import_react5.useCallback)(() => {
7656
+ socialRef.current?.forgetLastUser();
7657
+ const sdk = socialRef.current;
7658
+ if (sdk) {
7659
+ sdk.canSignInWithPasskey().then((can) => setSocialAuth((p) => ({ ...p, canUsePasskey: can }))).catch(() => {
7660
+ });
7661
+ }
7662
+ }, []);
7614
7663
  const socialUnlockWithPassword = (0, import_react5.useCallback)(async (password) => {
7615
7664
  const sdk = socialRef.current;
7616
7665
  if (!sdk) throw new Error("Social wallet not connected");
@@ -7687,6 +7736,7 @@ function DecaneKit({ config, children }) {
7687
7736
  socialAddPasskey,
7688
7737
  socialSetUnlockPassword,
7689
7738
  socialCanUnlockWithPassword,
7739
+ socialForgetLastUser,
7690
7740
  socialUnlockWithPassword,
7691
7741
  socialRemoveUnlockPassword,
7692
7742
  socialShouldPromptRecovery,
@@ -7996,6 +8046,7 @@ function useSocialWallet() {
7996
8046
  socialAddPasskey,
7997
8047
  socialSetUnlockPassword,
7998
8048
  socialCanUnlockWithPassword,
8049
+ socialForgetLastUser,
7999
8050
  socialUnlockWithPassword,
8000
8051
  socialRemoveUnlockPassword,
8001
8052
  socialShouldPromptRecovery,
@@ -8104,6 +8155,7 @@ function useSocialWallet() {
8104
8155
  throw e;
8105
8156
  }
8106
8157
  }, [socialSetUnlockPassword]);
8158
+ const forgetLastUser = (0, import_react6.useCallback)(() => socialForgetLastUser(), [socialForgetLastUser]);
8107
8159
  const canUnlockWithPassword = (0, import_react6.useCallback)(
8108
8160
  () => socialCanUnlockWithPassword(),
8109
8161
  [socialCanUnlockWithPassword]
@@ -8189,6 +8241,8 @@ function useSocialWallet() {
8189
8241
  canUnlockWithPassword,
8190
8242
  unlockWithPassword,
8191
8243
  removeUnlockPassword,
8244
+ // "Use a different account": stop offering the account that signed out.
8245
+ forgetLastUser,
8192
8246
  // Recovery (2-of-3 Shamir share set)
8193
8247
  rotateShares,
8194
8248
  exportPortableBackup,