@dexterai/connect 0.2.0 → 0.4.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/{chunk-46P7XAAI.js → chunk-2V6EGIHV.js} +190 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +29 -3
- package/dist/react.d.ts +32 -2
- package/dist/react.js +56 -2
- package/dist/signals-CkBFwCNw.d.ts +142 -0
- package/package.json +1 -1
- package/dist/types---RcNI2Y.d.ts +0 -45
|
@@ -228,9 +228,198 @@ function createPasskeySigner(vault, apiBase, opts = {}) {
|
|
|
228
228
|
});
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
+
// src/walletStore.ts
|
|
232
|
+
var ACTIVE_HANDLE_KEY = "dexter:passkey:userHandle";
|
|
233
|
+
var ROSTER_KEY = "dexter:passkey:wallets";
|
|
234
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
235
|
+
function hasStorage() {
|
|
236
|
+
try {
|
|
237
|
+
return typeof window !== "undefined" && !!window.localStorage;
|
|
238
|
+
} catch {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function readRoster() {
|
|
243
|
+
if (!hasStorage()) return [];
|
|
244
|
+
try {
|
|
245
|
+
const raw = window.localStorage.getItem(ROSTER_KEY);
|
|
246
|
+
if (!raw) return [];
|
|
247
|
+
const parsed = JSON.parse(raw);
|
|
248
|
+
if (!Array.isArray(parsed)) return [];
|
|
249
|
+
return parsed.filter(
|
|
250
|
+
(w) => !!w && typeof w === "object" && typeof w.handle === "string"
|
|
251
|
+
);
|
|
252
|
+
} catch {
|
|
253
|
+
return [];
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function writeRoster(wallets) {
|
|
257
|
+
if (!hasStorage()) return;
|
|
258
|
+
try {
|
|
259
|
+
window.localStorage.setItem(ROSTER_KEY, JSON.stringify(wallets));
|
|
260
|
+
} catch {
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function emit() {
|
|
264
|
+
for (const l of listeners) {
|
|
265
|
+
try {
|
|
266
|
+
l();
|
|
267
|
+
} catch {
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function getActiveHandle() {
|
|
272
|
+
if (!hasStorage()) return null;
|
|
273
|
+
try {
|
|
274
|
+
return window.localStorage.getItem(ACTIVE_HANDLE_KEY);
|
|
275
|
+
} catch {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
function setActiveHandle(handle, label, credentialId) {
|
|
280
|
+
if (!hasStorage() || !handle) return;
|
|
281
|
+
try {
|
|
282
|
+
window.localStorage.setItem(ACTIVE_HANDLE_KEY, handle);
|
|
283
|
+
} catch {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const roster = readRoster();
|
|
287
|
+
const existing = roster.find((w) => w.handle === handle);
|
|
288
|
+
const now = Date.now();
|
|
289
|
+
if (existing) {
|
|
290
|
+
existing.lastUsedAt = now;
|
|
291
|
+
if (label !== void 0) existing.label = label;
|
|
292
|
+
if (credentialId !== void 0) existing.credentialId = credentialId;
|
|
293
|
+
} else {
|
|
294
|
+
roster.push({ handle, label, credentialId, lastUsedAt: now });
|
|
295
|
+
}
|
|
296
|
+
writeRoster(roster);
|
|
297
|
+
emit();
|
|
298
|
+
}
|
|
299
|
+
function getCredentialId(handle) {
|
|
300
|
+
return readRoster().find((w) => w.handle === handle)?.credentialId;
|
|
301
|
+
}
|
|
302
|
+
function ejectActiveWallet(opts) {
|
|
303
|
+
if (!hasStorage()) return;
|
|
304
|
+
const current = getActiveHandle();
|
|
305
|
+
try {
|
|
306
|
+
window.localStorage.removeItem(ACTIVE_HANDLE_KEY);
|
|
307
|
+
} catch {
|
|
308
|
+
}
|
|
309
|
+
if (opts?.forget && current) {
|
|
310
|
+
writeRoster(readRoster().filter((w) => w.handle !== current));
|
|
311
|
+
}
|
|
312
|
+
emit();
|
|
313
|
+
}
|
|
314
|
+
function listWallets() {
|
|
315
|
+
return readRoster().sort((a, b) => (b.lastUsedAt ?? 0) - (a.lastUsedAt ?? 0));
|
|
316
|
+
}
|
|
317
|
+
function switchWallet(handle) {
|
|
318
|
+
if (!readRoster().some((w) => w.handle === handle)) return false;
|
|
319
|
+
setActiveHandle(handle);
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
function forgetWallet(handle) {
|
|
323
|
+
if (getActiveHandle() === handle) {
|
|
324
|
+
ejectActiveWallet({ forget: true });
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
writeRoster(readRoster().filter((w) => w.handle !== handle));
|
|
328
|
+
emit();
|
|
329
|
+
}
|
|
330
|
+
function subscribe(listener) {
|
|
331
|
+
listeners.add(listener);
|
|
332
|
+
if (hasStorage() && listeners.size === 1) {
|
|
333
|
+
window.addEventListener("storage", onStorageEvent);
|
|
334
|
+
}
|
|
335
|
+
return () => {
|
|
336
|
+
listeners.delete(listener);
|
|
337
|
+
if (hasStorage() && listeners.size === 0) {
|
|
338
|
+
window.removeEventListener("storage", onStorageEvent);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function onStorageEvent(e) {
|
|
343
|
+
if (e.key === ACTIVE_HANDLE_KEY || e.key === ROSTER_KEY || e.key === null) emit();
|
|
344
|
+
}
|
|
345
|
+
var ACTIVE_WALLET_STORAGE_KEY = ACTIVE_HANDLE_KEY;
|
|
346
|
+
|
|
347
|
+
// src/signals.ts
|
|
348
|
+
function pkc() {
|
|
349
|
+
if (typeof window === "undefined") return null;
|
|
350
|
+
const g = globalThis.PublicKeyCredential;
|
|
351
|
+
return g ?? null;
|
|
352
|
+
}
|
|
353
|
+
function defaultRpId() {
|
|
354
|
+
return typeof window !== "undefined" ? window.location.hostname : "";
|
|
355
|
+
}
|
|
356
|
+
function passkeySignalSupport() {
|
|
357
|
+
const p = pkc();
|
|
358
|
+
return {
|
|
359
|
+
rename: typeof p?.signalCurrentUserDetails === "function",
|
|
360
|
+
prune: typeof p?.signalUnknownCredential === "function",
|
|
361
|
+
syncAccepted: typeof p?.signalAllAcceptedCredentials === "function"
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
async function renamePasskey(args) {
|
|
365
|
+
const p = pkc();
|
|
366
|
+
if (typeof p?.signalCurrentUserDetails !== "function") return false;
|
|
367
|
+
try {
|
|
368
|
+
await p.signalCurrentUserDetails({
|
|
369
|
+
rpId: args.rpId ?? defaultRpId(),
|
|
370
|
+
userId: args.userId,
|
|
371
|
+
name: args.name,
|
|
372
|
+
displayName: args.displayName ?? args.name
|
|
373
|
+
});
|
|
374
|
+
return true;
|
|
375
|
+
} catch {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
async function prunePasskey(args) {
|
|
380
|
+
const p = pkc();
|
|
381
|
+
if (typeof p?.signalUnknownCredential !== "function") return false;
|
|
382
|
+
try {
|
|
383
|
+
await p.signalUnknownCredential({
|
|
384
|
+
rpId: args.rpId ?? defaultRpId(),
|
|
385
|
+
credentialId: args.credentialId
|
|
386
|
+
});
|
|
387
|
+
return true;
|
|
388
|
+
} catch {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
async function syncAcceptedPasskeys(args) {
|
|
393
|
+
const p = pkc();
|
|
394
|
+
if (typeof p?.signalAllAcceptedCredentials !== "function") return false;
|
|
395
|
+
try {
|
|
396
|
+
await p.signalAllAcceptedCredentials({
|
|
397
|
+
rpId: args.rpId ?? defaultRpId(),
|
|
398
|
+
userId: args.userId,
|
|
399
|
+
allAcceptedCredentialIds: args.acceptedCredentialIds
|
|
400
|
+
});
|
|
401
|
+
return true;
|
|
402
|
+
} catch {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
231
407
|
export {
|
|
232
408
|
ConnectError,
|
|
233
409
|
passkeyLogin,
|
|
234
410
|
createAnonServerPolicy,
|
|
235
|
-
createPasskeySigner
|
|
411
|
+
createPasskeySigner,
|
|
412
|
+
getActiveHandle,
|
|
413
|
+
setActiveHandle,
|
|
414
|
+
getCredentialId,
|
|
415
|
+
ejectActiveWallet,
|
|
416
|
+
listWallets,
|
|
417
|
+
switchWallet,
|
|
418
|
+
forgetWallet,
|
|
419
|
+
subscribe,
|
|
420
|
+
ACTIVE_WALLET_STORAGE_KEY,
|
|
421
|
+
passkeySignalSupport,
|
|
422
|
+
renamePasskey,
|
|
423
|
+
prunePasskey,
|
|
424
|
+
syncAcceptedPasskeys
|
|
236
425
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as DexterConnectConfig, S as SignInResult, C as ConnectVault } from './
|
|
2
|
-
export { a as ConnectError, P as PasskeyLoginTokens } from './
|
|
1
|
+
import { D as DexterConnectConfig, S as SignInResult, C as ConnectVault } from './signals-CkBFwCNw.js';
|
|
2
|
+
export { A as ACTIVE_WALLET_STORAGE_KEY, a as ConnectError, P as PasskeyLoginTokens, b as PasskeySignalSupport, c as StoredWallet, e as ejectActiveWallet, f as forgetWallet, g as getActiveHandle, d as getCredentialId, l as listWallets, p as passkeySignalSupport, h as prunePasskey, r as renamePasskey, s as setActiveHandle, i as subscribeWallet, j as switchWallet, k as syncAcceptedPasskeys } from './signals-CkBFwCNw.js';
|
|
3
3
|
import { DexterApiBrowserPasskeySigner } from '@dexterai/vault/signers/browser';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,38 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ACTIVE_WALLET_STORAGE_KEY,
|
|
2
3
|
ConnectError,
|
|
3
4
|
createAnonServerPolicy,
|
|
4
5
|
createPasskeySigner,
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
ejectActiveWallet,
|
|
7
|
+
forgetWallet,
|
|
8
|
+
getActiveHandle,
|
|
9
|
+
getCredentialId,
|
|
10
|
+
listWallets,
|
|
11
|
+
passkeyLogin,
|
|
12
|
+
passkeySignalSupport,
|
|
13
|
+
prunePasskey,
|
|
14
|
+
renamePasskey,
|
|
15
|
+
setActiveHandle,
|
|
16
|
+
subscribe,
|
|
17
|
+
switchWallet,
|
|
18
|
+
syncAcceptedPasskeys
|
|
19
|
+
} from "./chunk-2V6EGIHV.js";
|
|
7
20
|
export {
|
|
21
|
+
ACTIVE_WALLET_STORAGE_KEY,
|
|
8
22
|
ConnectError,
|
|
9
23
|
createAnonServerPolicy,
|
|
10
24
|
createPasskeySigner,
|
|
11
|
-
|
|
25
|
+
ejectActiveWallet,
|
|
26
|
+
forgetWallet,
|
|
27
|
+
getActiveHandle,
|
|
28
|
+
getCredentialId,
|
|
29
|
+
listWallets,
|
|
30
|
+
passkeyLogin,
|
|
31
|
+
passkeySignalSupport,
|
|
32
|
+
prunePasskey,
|
|
33
|
+
renamePasskey,
|
|
34
|
+
setActiveHandle,
|
|
35
|
+
subscribe as subscribeWallet,
|
|
36
|
+
switchWallet,
|
|
37
|
+
syncAcceptedPasskeys
|
|
12
38
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DexterApiBrowserPasskeySigner } from '@dexterai/vault/signers/browser';
|
|
2
|
-
import { S as SignInResult, P as PasskeyLoginTokens, C as ConnectVault, a as ConnectError } from './
|
|
2
|
+
import { S as SignInResult, P as PasskeyLoginTokens, C as ConnectVault, a as ConnectError, c as StoredWallet, b as PasskeySignalSupport } from './signals-CkBFwCNw.js';
|
|
3
3
|
import { ReactElement } from 'react';
|
|
4
4
|
|
|
5
5
|
type ConnectStatus = 'idle' | 'pending' | 'done' | 'error';
|
|
@@ -64,4 +64,34 @@ interface SignInWithDexterProps extends UseSignInWithDexterConfig {
|
|
|
64
64
|
*/
|
|
65
65
|
declare function SignInWithDexter(props: SignInWithDexterProps): ReactElement | null;
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
interface UseDexterWallet {
|
|
68
|
+
/** Active wallet handle, or null if this browser has no active wallet. */
|
|
69
|
+
activeHandle: string | null;
|
|
70
|
+
/** Known wallets on this browser, most-recently-used first. */
|
|
71
|
+
wallets: StoredWallet[];
|
|
72
|
+
/** What the WebAuthn Signal API supports in THIS browser (rename / prune). */
|
|
73
|
+
support: PasskeySignalSupport;
|
|
74
|
+
/**
|
|
75
|
+
* Eject the active wallet — "switch / start fresh". Clears the local binding
|
|
76
|
+
* and, where supported, prunes the old passkey from the OS manager so it
|
|
77
|
+
* disappears from the user's list. `{ forget: true }` also drops it from the
|
|
78
|
+
* roster.
|
|
79
|
+
*/
|
|
80
|
+
eject: (opts?: {
|
|
81
|
+
forget?: boolean;
|
|
82
|
+
}) => void;
|
|
83
|
+
/** Switch the active wallet to a known handle. No-op if unknown. */
|
|
84
|
+
switchTo: (handle: string) => boolean;
|
|
85
|
+
/** Record/activate a handle (after enroll or recover). Prefer over writing
|
|
86
|
+
* localStorage by hand so the roster + subscribers stay correct. */
|
|
87
|
+
setActive: (handle: string, label?: string, credentialId?: string) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Rename the ACTIVE passkey in the OS keychain (post-creation). Returns true
|
|
90
|
+
* if the browser supported it and the signal fired; false otherwise (the
|
|
91
|
+
* keychain entry is then just left as-is).
|
|
92
|
+
*/
|
|
93
|
+
rename: (name: string, displayName?: string) => Promise<boolean>;
|
|
94
|
+
}
|
|
95
|
+
declare function useDexterWallet(): UseDexterWallet;
|
|
96
|
+
|
|
97
|
+
export { type ConnectStatus, SignInWithDexter, type SignInWithDexterProps, type UseDexterWallet, type UseSignInWithDexter, type UseSignInWithDexterConfig, useDexterWallet, useSignInWithDexter };
|
package/dist/react.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConnectError,
|
|
3
3
|
createPasskeySigner,
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
ejectActiveWallet,
|
|
5
|
+
getActiveHandle,
|
|
6
|
+
getCredentialId,
|
|
7
|
+
listWallets,
|
|
8
|
+
passkeyLogin,
|
|
9
|
+
passkeySignalSupport,
|
|
10
|
+
prunePasskey,
|
|
11
|
+
renamePasskey,
|
|
12
|
+
setActiveHandle,
|
|
13
|
+
subscribe,
|
|
14
|
+
switchWallet
|
|
15
|
+
} from "./chunk-2V6EGIHV.js";
|
|
6
16
|
|
|
7
17
|
// src/useSignInWithDexter.ts
|
|
8
18
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
@@ -198,7 +208,51 @@ var DISCONNECT = {
|
|
|
198
208
|
lineHeight: 1,
|
|
199
209
|
opacity: 0.6
|
|
200
210
|
};
|
|
211
|
+
|
|
212
|
+
// src/useDexterWallet.ts
|
|
213
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
214
|
+
var NO_SUPPORT = { rename: false, prune: false, syncAccepted: false };
|
|
215
|
+
function useDexterWallet() {
|
|
216
|
+
const [activeHandle, setHandle] = useState2(() => getActiveHandle());
|
|
217
|
+
const [wallets, setWallets] = useState2(() => listWallets());
|
|
218
|
+
const [support, setSupport] = useState2(NO_SUPPORT);
|
|
219
|
+
useEffect2(() => {
|
|
220
|
+
const sync = () => {
|
|
221
|
+
setHandle(getActiveHandle());
|
|
222
|
+
setWallets(listWallets());
|
|
223
|
+
};
|
|
224
|
+
setSupport(passkeySignalSupport());
|
|
225
|
+
sync();
|
|
226
|
+
return subscribe(sync);
|
|
227
|
+
}, []);
|
|
228
|
+
const eject = useCallback2((opts) => {
|
|
229
|
+
const handle = getActiveHandle();
|
|
230
|
+
const credentialId = handle ? getCredentialId(handle) : void 0;
|
|
231
|
+
ejectActiveWallet(opts);
|
|
232
|
+
if (credentialId) void prunePasskey({ credentialId });
|
|
233
|
+
}, []);
|
|
234
|
+
const rename = useCallback2(async (name, displayName) => {
|
|
235
|
+
const handle = getActiveHandle();
|
|
236
|
+
if (!handle) return false;
|
|
237
|
+
const ok = await renamePasskey({ userId: handle, name, displayName });
|
|
238
|
+
if (ok) setActiveHandle(handle, name);
|
|
239
|
+
return ok;
|
|
240
|
+
}, []);
|
|
241
|
+
return {
|
|
242
|
+
activeHandle,
|
|
243
|
+
wallets,
|
|
244
|
+
support,
|
|
245
|
+
eject,
|
|
246
|
+
switchTo: useCallback2((handle) => switchWallet(handle), []),
|
|
247
|
+
setActive: useCallback2(
|
|
248
|
+
(handle, label, credentialId) => setActiveHandle(handle, label, credentialId),
|
|
249
|
+
[]
|
|
250
|
+
),
|
|
251
|
+
rename
|
|
252
|
+
};
|
|
253
|
+
}
|
|
201
254
|
export {
|
|
202
255
|
SignInWithDexter,
|
|
256
|
+
useDexterWallet,
|
|
203
257
|
useSignInWithDexter
|
|
204
258
|
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/** Supabase session tokens returned by dexter-api's passkey-login (camelCase). */
|
|
2
|
+
interface PasskeyLoginTokens {
|
|
3
|
+
accessToken: string;
|
|
4
|
+
refreshToken: string;
|
|
5
|
+
expiresAt: number;
|
|
6
|
+
expiresIn: number;
|
|
7
|
+
tokenType: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Vault identity, returned ALONGSIDE the session by passkey-login once
|
|
11
|
+
* vault-review ships the dexter-api change (ASK 1). Optional until then —
|
|
12
|
+
* the connector degrades to session-only. Consumers that open x402 tabs
|
|
13
|
+
* (dexter-agents) need `vaultPda` + `publicKey` to build a passkey signer.
|
|
14
|
+
*/
|
|
15
|
+
interface ConnectVault {
|
|
16
|
+
vaultPda: string;
|
|
17
|
+
/** Swig state address, base58 — the user-facing Dexter Wallet address. */
|
|
18
|
+
swigAddress: string;
|
|
19
|
+
/** v2 swig wallet PDA (deposit address); null until the swig is deployed. */
|
|
20
|
+
receiveAddress: string | null;
|
|
21
|
+
/** Swig wallet's USDC ATA, base58 (for the connected-chip balance read);
|
|
22
|
+
* null until the swig is deployed. Server-resolved (off-curve-safe). */
|
|
23
|
+
usdcAta: string | null;
|
|
24
|
+
/** base64 33-byte SEC1 compressed P-256 authority pubkey (for the signer). */
|
|
25
|
+
publicKey: string;
|
|
26
|
+
userHandle: string;
|
|
27
|
+
credentialId: string;
|
|
28
|
+
}
|
|
29
|
+
/** Result of a completed "Sign in with Dexter" ceremony. */
|
|
30
|
+
interface SignInResult {
|
|
31
|
+
session: PasskeyLoginTokens;
|
|
32
|
+
/** Present once vault-review ships the vault-in-login change. */
|
|
33
|
+
vault?: ConnectVault;
|
|
34
|
+
}
|
|
35
|
+
interface DexterConnectConfig {
|
|
36
|
+
/** dexter-api base. Default https://api.dexter.cash. */
|
|
37
|
+
apiBase?: string;
|
|
38
|
+
}
|
|
39
|
+
/** Typed error whose `code` is the server's snake_case error string. */
|
|
40
|
+
declare class ConnectError extends Error {
|
|
41
|
+
readonly code: string;
|
|
42
|
+
constructor(code: string, message?: string);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** A wallet this browser knows about. `handle` is the identity; the rest is UX. */
|
|
46
|
+
interface StoredWallet {
|
|
47
|
+
/** base64url 16-byte user handle — the vault identity. */
|
|
48
|
+
handle: string;
|
|
49
|
+
/** Human label for switch UIs (e.g. an email, or "Dexter Wallet"). */
|
|
50
|
+
label?: string;
|
|
51
|
+
/** base64url credential id — enables the WebAuthn Signal API to prune this
|
|
52
|
+
* passkey from the OS manager on eject (see ./signals). */
|
|
53
|
+
credentialId?: string;
|
|
54
|
+
/** Epoch ms of last activation — for ordering the switcher. */
|
|
55
|
+
lastUsedAt?: number;
|
|
56
|
+
}
|
|
57
|
+
type Listener = () => void;
|
|
58
|
+
/** The active wallet handle, or null if this browser has no active wallet. */
|
|
59
|
+
declare function getActiveHandle(): string | null;
|
|
60
|
+
/**
|
|
61
|
+
* Set the active wallet handle (e.g. after enroll or recover), upserting it into
|
|
62
|
+
* the roster with a fresh `lastUsedAt`. Idempotent. Fires subscribers.
|
|
63
|
+
*/
|
|
64
|
+
declare function setActiveHandle(handle: string, label?: string, credentialId?: string): void;
|
|
65
|
+
/** Look up a known wallet's stored credentialId (for Signal-API prune on eject). */
|
|
66
|
+
declare function getCredentialId(handle: string): string | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* EJECT — clear the active wallet so the browser is no longer bound to it. This
|
|
69
|
+
* is "switch / start fresh / sign out of this wallet". The wallet stays in the
|
|
70
|
+
* roster (so the user can switch back) unless `forget` is true. After eject,
|
|
71
|
+
* `getActiveHandle()` is null and the next enroll/recover starts clean. Fires
|
|
72
|
+
* subscribers. This is the function whose absence WAS the welded-wallet bug.
|
|
73
|
+
*/
|
|
74
|
+
declare function ejectActiveWallet(opts?: {
|
|
75
|
+
forget?: boolean;
|
|
76
|
+
}): void;
|
|
77
|
+
/** Every wallet this browser knows about, most-recently-used first. */
|
|
78
|
+
declare function listWallets(): StoredWallet[];
|
|
79
|
+
/**
|
|
80
|
+
* Switch the active wallet to a handle ALREADY in the roster. Returns false (and
|
|
81
|
+
* does nothing) if the handle is unknown — switching is only ever to a wallet
|
|
82
|
+
* this browser has seen, never to an arbitrary string.
|
|
83
|
+
*/
|
|
84
|
+
declare function switchWallet(handle: string): boolean;
|
|
85
|
+
/** Remove a wallet from the roster entirely; clears active if it was active. */
|
|
86
|
+
declare function forgetWallet(handle: string): void;
|
|
87
|
+
/**
|
|
88
|
+
* Subscribe to active-wallet/roster changes. Returns an unsubscribe fn. Also
|
|
89
|
+
* wires the cross-tab `storage` event once, so ejecting in one tab updates the
|
|
90
|
+
* others. The React hook (`useDexterWallet`) is a thin wrapper over this.
|
|
91
|
+
*/
|
|
92
|
+
declare function subscribe(listener: Listener): () => void;
|
|
93
|
+
/** Exposed for consumers that must reference the canonical key (migrations,
|
|
94
|
+
* tests). Prefer the accessors above — do NOT read localStorage by hand. */
|
|
95
|
+
declare const ACTIVE_WALLET_STORAGE_KEY = "dexter:passkey:userHandle";
|
|
96
|
+
|
|
97
|
+
interface PasskeySignalSupport {
|
|
98
|
+
/** signalCurrentUserDetails — rename a passkey post-creation. */
|
|
99
|
+
rename: boolean;
|
|
100
|
+
/** signalUnknownCredential — remove one stale passkey from the manager. */
|
|
101
|
+
prune: boolean;
|
|
102
|
+
/** signalAllAcceptedCredentials — reconcile the full valid set. */
|
|
103
|
+
syncAccepted: boolean;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* What the CURRENT browser supports, by direct feature-detection. Instant, no
|
|
107
|
+
* network, no UA sniffing — tells you exactly what will light up on THIS device
|
|
108
|
+
* (e.g. call once on Branch's iPhone to learn its Safari's status).
|
|
109
|
+
*/
|
|
110
|
+
declare function passkeySignalSupport(): PasskeySignalSupport;
|
|
111
|
+
/**
|
|
112
|
+
* Rename a passkey in the OS keychain AFTER creation. `userId` is the base64url
|
|
113
|
+
* user handle; `rpId` defaults to the current host. Returns true if the signal
|
|
114
|
+
* fired, false if unsupported/failed (caller treats false as "left as-is").
|
|
115
|
+
*/
|
|
116
|
+
declare function renamePasskey(args: {
|
|
117
|
+
userId: string;
|
|
118
|
+
name: string;
|
|
119
|
+
displayName?: string;
|
|
120
|
+
rpId?: string;
|
|
121
|
+
}): Promise<boolean>;
|
|
122
|
+
/**
|
|
123
|
+
* Tell the OS manager a credential is gone so it removes that passkey from the
|
|
124
|
+
* user's list — the welded-old-wallet auto-cleanup. `credentialId` is base64url.
|
|
125
|
+
* Returns true if fired, false if unsupported/failed.
|
|
126
|
+
*/
|
|
127
|
+
declare function prunePasskey(args: {
|
|
128
|
+
credentialId: string;
|
|
129
|
+
rpId?: string;
|
|
130
|
+
}): Promise<boolean>;
|
|
131
|
+
/**
|
|
132
|
+
* Declare the FULL set of still-valid credential IDs for a user; the manager
|
|
133
|
+
* prunes anything not listed. Use after sign-in or eject to reconcile in one
|
|
134
|
+
* shot (pass `[]` to clear all of a user's passkeys). Returns true if fired.
|
|
135
|
+
*/
|
|
136
|
+
declare function syncAcceptedPasskeys(args: {
|
|
137
|
+
userId: string;
|
|
138
|
+
acceptedCredentialIds: string[];
|
|
139
|
+
rpId?: string;
|
|
140
|
+
}): Promise<boolean>;
|
|
141
|
+
|
|
142
|
+
export { ACTIVE_WALLET_STORAGE_KEY as A, type ConnectVault as C, type DexterConnectConfig as D, type PasskeyLoginTokens as P, type SignInResult as S, ConnectError as a, type PasskeySignalSupport as b, type StoredWallet as c, getCredentialId as d, ejectActiveWallet as e, forgetWallet as f, getActiveHandle as g, prunePasskey as h, subscribe as i, switchWallet as j, syncAcceptedPasskeys as k, listWallets as l, passkeySignalSupport as p, renamePasskey as r, setActiveHandle as s };
|
package/package.json
CHANGED
package/dist/types---RcNI2Y.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/** Supabase session tokens returned by dexter-api's passkey-login (camelCase). */
|
|
2
|
-
interface PasskeyLoginTokens {
|
|
3
|
-
accessToken: string;
|
|
4
|
-
refreshToken: string;
|
|
5
|
-
expiresAt: number;
|
|
6
|
-
expiresIn: number;
|
|
7
|
-
tokenType: string;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Vault identity, returned ALONGSIDE the session by passkey-login once
|
|
11
|
-
* vault-review ships the dexter-api change (ASK 1). Optional until then —
|
|
12
|
-
* the connector degrades to session-only. Consumers that open x402 tabs
|
|
13
|
-
* (dexter-agents) need `vaultPda` + `publicKey` to build a passkey signer.
|
|
14
|
-
*/
|
|
15
|
-
interface ConnectVault {
|
|
16
|
-
vaultPda: string;
|
|
17
|
-
/** Swig state address, base58 — the user-facing Dexter Wallet address. */
|
|
18
|
-
swigAddress: string;
|
|
19
|
-
/** v2 swig wallet PDA (deposit address); null until the swig is deployed. */
|
|
20
|
-
receiveAddress: string | null;
|
|
21
|
-
/** Swig wallet's USDC ATA, base58 (for the connected-chip balance read);
|
|
22
|
-
* null until the swig is deployed. Server-resolved (off-curve-safe). */
|
|
23
|
-
usdcAta: string | null;
|
|
24
|
-
/** base64 33-byte SEC1 compressed P-256 authority pubkey (for the signer). */
|
|
25
|
-
publicKey: string;
|
|
26
|
-
userHandle: string;
|
|
27
|
-
credentialId: string;
|
|
28
|
-
}
|
|
29
|
-
/** Result of a completed "Sign in with Dexter" ceremony. */
|
|
30
|
-
interface SignInResult {
|
|
31
|
-
session: PasskeyLoginTokens;
|
|
32
|
-
/** Present once vault-review ships the vault-in-login change. */
|
|
33
|
-
vault?: ConnectVault;
|
|
34
|
-
}
|
|
35
|
-
interface DexterConnectConfig {
|
|
36
|
-
/** dexter-api base. Default https://api.dexter.cash. */
|
|
37
|
-
apiBase?: string;
|
|
38
|
-
}
|
|
39
|
-
/** Typed error whose `code` is the server's snake_case error string. */
|
|
40
|
-
declare class ConnectError extends Error {
|
|
41
|
-
readonly code: string;
|
|
42
|
-
constructor(code: string, message?: string);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export { type ConnectVault as C, type DexterConnectConfig as D, type PasskeyLoginTokens as P, type SignInResult as S, ConnectError as a };
|