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 +58 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +58 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -398,6 +398,14 @@ interface DecaneConnect {
|
|
|
398
398
|
setUnlockPassword(password: string): Promise<void>;
|
|
399
399
|
/** True when this device can open a session from a password alone. */
|
|
400
400
|
canUnlockWithPassword(): Promise<boolean>;
|
|
401
|
+
/**
|
|
402
|
+
* "Use a different account." disconnect() keeps one fact about the account
|
|
403
|
+
* that signed out — its userId — so canSignInWithPasskey() and
|
|
404
|
+
* canUnlockWithPassword() can offer that account's own way back in even
|
|
405
|
+
* when several accounts are enrolled on this browser. This drops it. The
|
|
406
|
+
* device shares themselves are untouched.
|
|
407
|
+
*/
|
|
408
|
+
forgetLastUser(): void;
|
|
401
409
|
/** Open a session from the password alone — no provider, no passkey. */
|
|
402
410
|
unlockWithPassword(password: string): Promise<ConnectResult>;
|
|
403
411
|
/** Turn the password path off, revoking the token account-wide. */
|
|
@@ -1444,6 +1452,7 @@ declare function useSocialWallet(): {
|
|
|
1444
1452
|
canUnlockWithPassword: () => Promise<boolean>;
|
|
1445
1453
|
unlockWithPassword: (password: string) => Promise<void>;
|
|
1446
1454
|
removeUnlockPassword: () => Promise<void>;
|
|
1455
|
+
forgetLastUser: () => void;
|
|
1447
1456
|
rotateShares: (opts: {
|
|
1448
1457
|
password: string;
|
|
1449
1458
|
passwordHint?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -398,6 +398,14 @@ interface DecaneConnect {
|
|
|
398
398
|
setUnlockPassword(password: string): Promise<void>;
|
|
399
399
|
/** True when this device can open a session from a password alone. */
|
|
400
400
|
canUnlockWithPassword(): Promise<boolean>;
|
|
401
|
+
/**
|
|
402
|
+
* "Use a different account." disconnect() keeps one fact about the account
|
|
403
|
+
* that signed out — its userId — so canSignInWithPasskey() and
|
|
404
|
+
* canUnlockWithPassword() can offer that account's own way back in even
|
|
405
|
+
* when several accounts are enrolled on this browser. This drops it. The
|
|
406
|
+
* device shares themselves are untouched.
|
|
407
|
+
*/
|
|
408
|
+
forgetLastUser(): void;
|
|
401
409
|
/** Open a session from the password alone — no provider, no passkey. */
|
|
402
410
|
unlockWithPassword(password: string): Promise<ConnectResult>;
|
|
403
411
|
/** Turn the password path off, revoking the token account-wide. */
|
|
@@ -1444,6 +1452,7 @@ declare function useSocialWallet(): {
|
|
|
1444
1452
|
canUnlockWithPassword: () => Promise<boolean>;
|
|
1445
1453
|
unlockWithPassword: (password: string) => Promise<void>;
|
|
1446
1454
|
removeUnlockPassword: () => Promise<void>;
|
|
1455
|
+
forgetLastUser: () => void;
|
|
1447
1456
|
rotateShares: (opts: {
|
|
1448
1457
|
password: string;
|
|
1449
1458
|
passwordHint?: string;
|
package/dist/index.js
CHANGED
|
@@ -3607,6 +3607,29 @@ function clearPersisted(key) {
|
|
|
3607
3607
|
} catch {
|
|
3608
3608
|
}
|
|
3609
3609
|
}
|
|
3610
|
+
function makeLastUserKey(apiKey) {
|
|
3611
|
+
return `${makePersistKey(apiKey)}:last-user`;
|
|
3612
|
+
}
|
|
3613
|
+
function loadLastUser(key) {
|
|
3614
|
+
try {
|
|
3615
|
+
const raw = typeof localStorage !== "undefined" ? localStorage.getItem(key) : null;
|
|
3616
|
+
return raw ? JSON.parse(raw).userId ?? null : null;
|
|
3617
|
+
} catch {
|
|
3618
|
+
return null;
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
function saveLastUser(key, userId) {
|
|
3622
|
+
try {
|
|
3623
|
+
localStorage.setItem(key, JSON.stringify({ userId }));
|
|
3624
|
+
} catch {
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
function clearLastUser(key) {
|
|
3628
|
+
try {
|
|
3629
|
+
localStorage.removeItem(key);
|
|
3630
|
+
} catch {
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3610
3633
|
function sessionPersistKey(apiKey) {
|
|
3611
3634
|
return `decane:sess:${apiKey.slice(0, 20)}`;
|
|
3612
3635
|
}
|
|
@@ -3645,6 +3668,7 @@ async function createDecaneConnect(config) {
|
|
|
3645
3668
|
const rpId = config.rpId ?? (typeof window !== "undefined" ? window.location.hostname : "localhost");
|
|
3646
3669
|
const rpName = config.rpName ?? "Decane Connect";
|
|
3647
3670
|
const PERSIST_KEY = makePersistKey(config.apiKey);
|
|
3671
|
+
const LAST_USER_KEY = makeLastUserKey(config.apiKey);
|
|
3648
3672
|
const teeUrl = config.teeUrl ?? DEFAULT_TEE_URL;
|
|
3649
3673
|
const events = new EventEmitter();
|
|
3650
3674
|
const api = new ApiClient(baseUrl, config.apiKey, config.appId);
|
|
@@ -3657,6 +3681,7 @@ async function createDecaneConnect(config) {
|
|
|
3657
3681
|
);
|
|
3658
3682
|
let auth = null;
|
|
3659
3683
|
let persisted = loadPersisted(PERSIST_KEY);
|
|
3684
|
+
let lastUserId = loadLastUser(LAST_USER_KEY);
|
|
3660
3685
|
let ethProvider = null;
|
|
3661
3686
|
const persistSession = config.persistSession !== false;
|
|
3662
3687
|
const serverAssistedRecovery = true;
|
|
@@ -3802,6 +3827,10 @@ async function createDecaneConnect(config) {
|
|
|
3802
3827
|
const stored = await storage.getShare(persisted.userId);
|
|
3803
3828
|
return hasPasswordUnlock(stored) ? stored : null;
|
|
3804
3829
|
}
|
|
3830
|
+
if (lastUserId) {
|
|
3831
|
+
const stored = await storage.getShare(lastUserId);
|
|
3832
|
+
return hasPasswordUnlock(stored) ? stored : null;
|
|
3833
|
+
}
|
|
3805
3834
|
const candidates = (await storage.listShares()).filter(hasPasswordUnlock);
|
|
3806
3835
|
return candidates.length === 1 ? candidates[0] : null;
|
|
3807
3836
|
}
|
|
@@ -4255,14 +4284,16 @@ async function createDecaneConnect(config) {
|
|
|
4255
4284
|
async function passkeyDeviceCandidate() {
|
|
4256
4285
|
if (!isPasskeySupported()) return null;
|
|
4257
4286
|
if (persisted?.userId) return passkeyLoginCandidate();
|
|
4287
|
+
if (lastUserId) return usablePasskeyShare(await storage.getShare(lastUserId));
|
|
4258
4288
|
const candidates = (await storage.listShares()).map(usablePasskeyShare).filter(Boolean);
|
|
4259
4289
|
return candidates.length === 1 ? candidates[0] : null;
|
|
4260
4290
|
}
|
|
4261
4291
|
async function canOfferPasskey() {
|
|
4262
4292
|
if (!isPasskeySupported()) return false;
|
|
4263
4293
|
if (await passkeyDeviceCandidate()) return true;
|
|
4264
|
-
|
|
4265
|
-
|
|
4294
|
+
const known = persisted?.userId ?? lastUserId;
|
|
4295
|
+
if (!known) return false;
|
|
4296
|
+
return await storage.getShare(known) == null;
|
|
4266
4297
|
}
|
|
4267
4298
|
async function rememberProfile(userId, profile) {
|
|
4268
4299
|
const incoming = Object.fromEntries(Object.entries(profile).filter(([, v]) => v));
|
|
@@ -4475,8 +4506,9 @@ async function createDecaneConnect(config) {
|
|
|
4475
4506
|
async signInWithPasskey() {
|
|
4476
4507
|
const candidate = await passkeyDeviceCandidate();
|
|
4477
4508
|
if (candidate) return passkeyLogin(candidate);
|
|
4478
|
-
|
|
4479
|
-
|
|
4509
|
+
const known = persisted?.userId ?? lastUserId;
|
|
4510
|
+
if (isPasskeySupported() && known && await storage.getShare(known) == null) {
|
|
4511
|
+
return passkeyLoginWithoutShare(known);
|
|
4480
4512
|
}
|
|
4481
4513
|
throw new NewDeviceError();
|
|
4482
4514
|
},
|
|
@@ -4816,12 +4848,21 @@ async function createDecaneConnect(config) {
|
|
|
4816
4848
|
await api.revoke(auth.jwt).catch(() => {
|
|
4817
4849
|
});
|
|
4818
4850
|
}
|
|
4851
|
+
const leaving = auth?.userId ?? persisted?.userId ?? null;
|
|
4852
|
+
if (leaving) {
|
|
4853
|
+
lastUserId = leaving;
|
|
4854
|
+
saveLastUser(LAST_USER_KEY, leaving);
|
|
4855
|
+
}
|
|
4819
4856
|
auth = null;
|
|
4820
4857
|
persisted = null;
|
|
4821
4858
|
clearPersisted(PERSIST_KEY);
|
|
4822
4859
|
dropLiveSession();
|
|
4823
4860
|
events.emit("disconnected");
|
|
4824
4861
|
},
|
|
4862
|
+
forgetLastUser() {
|
|
4863
|
+
lastUserId = null;
|
|
4864
|
+
clearLastUser(LAST_USER_KEY);
|
|
4865
|
+
},
|
|
4825
4866
|
getAddresses() {
|
|
4826
4867
|
return auth?.addresses ?? persisted?.addresses ?? null;
|
|
4827
4868
|
},
|
|
@@ -7536,6 +7577,14 @@ function DecaneKit({ config, children }) {
|
|
|
7536
7577
|
if (!sdk) return false;
|
|
7537
7578
|
return sdk.canUnlockWithPassword();
|
|
7538
7579
|
}, []);
|
|
7580
|
+
const socialForgetLastUser = useCallback3(() => {
|
|
7581
|
+
socialRef.current?.forgetLastUser();
|
|
7582
|
+
const sdk = socialRef.current;
|
|
7583
|
+
if (sdk) {
|
|
7584
|
+
sdk.canSignInWithPasskey().then((can) => setSocialAuth((p) => ({ ...p, canUsePasskey: can }))).catch(() => {
|
|
7585
|
+
});
|
|
7586
|
+
}
|
|
7587
|
+
}, []);
|
|
7539
7588
|
const socialUnlockWithPassword = useCallback3(async (password) => {
|
|
7540
7589
|
const sdk = socialRef.current;
|
|
7541
7590
|
if (!sdk) throw new Error("Social wallet not connected");
|
|
@@ -7612,6 +7661,7 @@ function DecaneKit({ config, children }) {
|
|
|
7612
7661
|
socialAddPasskey,
|
|
7613
7662
|
socialSetUnlockPassword,
|
|
7614
7663
|
socialCanUnlockWithPassword,
|
|
7664
|
+
socialForgetLastUser,
|
|
7615
7665
|
socialUnlockWithPassword,
|
|
7616
7666
|
socialRemoveUnlockPassword,
|
|
7617
7667
|
socialShouldPromptRecovery,
|
|
@@ -7921,6 +7971,7 @@ function useSocialWallet() {
|
|
|
7921
7971
|
socialAddPasskey,
|
|
7922
7972
|
socialSetUnlockPassword,
|
|
7923
7973
|
socialCanUnlockWithPassword,
|
|
7974
|
+
socialForgetLastUser,
|
|
7924
7975
|
socialUnlockWithPassword,
|
|
7925
7976
|
socialRemoveUnlockPassword,
|
|
7926
7977
|
socialShouldPromptRecovery,
|
|
@@ -8029,6 +8080,7 @@ function useSocialWallet() {
|
|
|
8029
8080
|
throw e;
|
|
8030
8081
|
}
|
|
8031
8082
|
}, [socialSetUnlockPassword]);
|
|
8083
|
+
const forgetLastUser = useCallback4(() => socialForgetLastUser(), [socialForgetLastUser]);
|
|
8032
8084
|
const canUnlockWithPassword = useCallback4(
|
|
8033
8085
|
() => socialCanUnlockWithPassword(),
|
|
8034
8086
|
[socialCanUnlockWithPassword]
|
|
@@ -8114,6 +8166,8 @@ function useSocialWallet() {
|
|
|
8114
8166
|
canUnlockWithPassword,
|
|
8115
8167
|
unlockWithPassword,
|
|
8116
8168
|
removeUnlockPassword,
|
|
8169
|
+
// "Use a different account": stop offering the account that signed out.
|
|
8170
|
+
forgetLastUser,
|
|
8117
8171
|
// Recovery (2-of-3 Shamir share set)
|
|
8118
8172
|
rotateShares,
|
|
8119
8173
|
exportPortableBackup,
|