@dexterai/connect 0.3.0 → 0.5.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.
@@ -276,7 +276,7 @@ function getActiveHandle() {
276
276
  return null;
277
277
  }
278
278
  }
279
- function setActiveHandle(handle, label) {
279
+ function setActiveHandle(handle, label, credentialId) {
280
280
  if (!hasStorage() || !handle) return;
281
281
  try {
282
282
  window.localStorage.setItem(ACTIVE_HANDLE_KEY, handle);
@@ -289,12 +289,16 @@ function setActiveHandle(handle, label) {
289
289
  if (existing) {
290
290
  existing.lastUsedAt = now;
291
291
  if (label !== void 0) existing.label = label;
292
+ if (credentialId !== void 0) existing.credentialId = credentialId;
292
293
  } else {
293
- roster.push({ handle, label, lastUsedAt: now });
294
+ roster.push({ handle, label, credentialId, lastUsedAt: now });
294
295
  }
295
296
  writeRoster(roster);
296
297
  emit();
297
298
  }
299
+ function getCredentialId(handle) {
300
+ return readRoster().find((w) => w.handle === handle)?.credentialId;
301
+ }
298
302
  function ejectActiveWallet(opts) {
299
303
  if (!hasStorage()) return;
300
304
  const current = getActiveHandle();
@@ -340,17 +344,84 @@ function onStorageEvent(e) {
340
344
  }
341
345
  var ACTIVE_WALLET_STORAGE_KEY = ACTIVE_HANDLE_KEY;
342
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
+
343
407
  export {
344
408
  ConnectError,
409
+ base64urlToBytes,
410
+ bytesToBase64url,
345
411
  passkeyLogin,
346
412
  createAnonServerPolicy,
347
413
  createPasskeySigner,
348
414
  getActiveHandle,
349
415
  setActiveHandle,
416
+ getCredentialId,
350
417
  ejectActiveWallet,
351
418
  listWallets,
352
419
  switchWallet,
353
420
  forgetWallet,
354
421
  subscribe,
355
- ACTIVE_WALLET_STORAGE_KEY
422
+ ACTIVE_WALLET_STORAGE_KEY,
423
+ passkeySignalSupport,
424
+ renamePasskey,
425
+ prunePasskey,
426
+ syncAcceptedPasskeys
356
427
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as DexterConnectConfig, S as SignInResult, C as ConnectVault } from './walletStore-CWXhXuzK.js';
2
- export { A as ACTIVE_WALLET_STORAGE_KEY, a as ConnectError, P as PasskeyLoginTokens, b as StoredWallet, e as ejectActiveWallet, f as forgetWallet, g as getActiveHandle, l as listWallets, s as setActiveHandle, c as subscribeWallet, d as switchWallet } from './walletStore-CWXhXuzK.js';
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
  /**
@@ -76,4 +76,27 @@ declare function createPasskeySigner(vault: ConnectVault, apiBase?: string, opts
76
76
  __assertion?: AssertionLike;
77
77
  }): DexterApiBrowserPasskeySigner;
78
78
 
79
- export { type AnonChallengeResult, type AnonServerPolicy, ConnectVault, DexterConnectConfig, SignInResult, createAnonServerPolicy, createPasskeySigner, passkeyLogin };
79
+ interface CreateWalletConfig extends DexterConnectConfig {
80
+ /** Label for the passkey in the OS keychain AND the wallet roster. Set at
81
+ * creation — the only moment naming is guaranteed to stick. Default "Dexter Wallet". */
82
+ name?: string;
83
+ /** RP id for the new credential. Default "dexter.cash". */
84
+ rpId?: string;
85
+ }
86
+ interface CreateWalletResult {
87
+ /** Server-minted 16-byte user handle, base64url — the vault identity. */
88
+ handle: string;
89
+ /** base64url credential id of the new passkey. */
90
+ credentialId: string;
91
+ /** The freshly initialized vault (swig not yet deployed; deploys lazily). */
92
+ vault: ConnectVault;
93
+ }
94
+ /**
95
+ * Mint a brand-new Dexter wallet (passkey + vault) and make it the active wallet.
96
+ *
97
+ * One passkey approval. Throws ConnectError on any failed leg (the `code` is the
98
+ * server's error string, or webauthn_failed / no_credential for the ceremony).
99
+ */
100
+ declare function createWallet(config?: CreateWalletConfig): Promise<CreateWalletResult>;
101
+
102
+ export { type AnonChallengeResult, type AnonServerPolicy, ConnectVault, type CreateWalletConfig, type CreateWalletResult, DexterConnectConfig, SignInResult, createAnonServerPolicy, createPasskeySigner, createWallet, passkeyLogin };
package/dist/index.js CHANGED
@@ -1,28 +1,167 @@
1
1
  import {
2
2
  ACTIVE_WALLET_STORAGE_KEY,
3
3
  ConnectError,
4
+ base64urlToBytes,
5
+ bytesToBase64url,
4
6
  createAnonServerPolicy,
5
7
  createPasskeySigner,
6
8
  ejectActiveWallet,
7
9
  forgetWallet,
8
10
  getActiveHandle,
11
+ getCredentialId,
9
12
  listWallets,
10
13
  passkeyLogin,
14
+ passkeySignalSupport,
15
+ prunePasskey,
16
+ renamePasskey,
11
17
  setActiveHandle,
12
18
  subscribe,
13
- switchWallet
14
- } from "./chunk-HFG2GUFX.js";
19
+ switchWallet,
20
+ syncAcceptedPasskeys
21
+ } from "./chunk-LYIBVWRG.js";
22
+
23
+ // src/enroll.ts
24
+ var DEFAULT_API_BASE = "https://api.dexter.cash";
25
+ var DEFAULT_RP_ID = "dexter.cash";
26
+ var DEFAULT_WALLET_NAME = "Dexter Wallet";
27
+ async function createWallet(config = {}) {
28
+ if (typeof navigator === "undefined" || !navigator.credentials) {
29
+ throw new ConnectError("webauthn_unsupported", "WebAuthn unavailable in this environment");
30
+ }
31
+ const apiBase = (config.apiBase ?? DEFAULT_API_BASE).replace(/\/$/, "");
32
+ const rpId = config.rpId ?? DEFAULT_RP_ID;
33
+ const name = config.name && config.name.trim() || DEFAULT_WALLET_NAME;
34
+ const options = await fetchEnrollChallenge(apiBase);
35
+ const credential = await createCredential(options, name, rpId);
36
+ const enrolled = await submitEnrollComplete(apiBase, credential);
37
+ const init = await initializeVault(apiBase, enrolled.userHandle, enrolled.credentialId);
38
+ setActiveHandle(enrolled.userHandle, name, enrolled.credentialId);
39
+ return {
40
+ handle: enrolled.userHandle,
41
+ credentialId: enrolled.credentialId,
42
+ vault: {
43
+ vaultPda: init.vaultPda,
44
+ swigAddress: init.swigStateAddress,
45
+ // FAIL SAFE: never invent a receive address — null until the server returns
46
+ // one (depositing to the config PDA would strand funds).
47
+ receiveAddress: init.receiveAddress ?? null,
48
+ usdcAta: null,
49
+ // swig not deployed yet (counterfactual pattern)
50
+ publicKey: enrolled.publicKey,
51
+ userHandle: enrolled.userHandle,
52
+ credentialId: enrolled.credentialId
53
+ }
54
+ };
55
+ }
56
+ async function fetchEnrollChallenge(apiBase) {
57
+ const res = await fetch(`${apiBase}/api/passkey-anon/enroll/challenge`, {
58
+ method: "POST",
59
+ headers: { "content-type": "application/json" },
60
+ body: "{}"
61
+ });
62
+ if (!res.ok) throw new ConnectError("enroll_challenge_failed", `enroll/challenge ${res.status}`);
63
+ const data = await res.json();
64
+ if (!data?.options?.challenge) {
65
+ throw new ConnectError("enroll_challenge_malformed", "no creation options in response");
66
+ }
67
+ return data.options;
68
+ }
69
+ async function createCredential(options, name, rpId) {
70
+ let credential;
71
+ try {
72
+ credential = await navigator.credentials.create({
73
+ publicKey: buildCreationOptions(options, name, rpId)
74
+ });
75
+ } catch (err) {
76
+ throw new ConnectError("webauthn_failed", err instanceof Error ? err.message : String(err));
77
+ }
78
+ if (!credential || credential.type !== "public-key") {
79
+ throw new ConnectError("no_credential", "authenticator returned no credential");
80
+ }
81
+ return credential;
82
+ }
83
+ async function submitEnrollComplete(apiBase, credential) {
84
+ const attestation = credential.response;
85
+ const credentialJson = {
86
+ id: credential.id,
87
+ rawId: bytesToBase64url(new Uint8Array(credential.rawId)),
88
+ type: credential.type,
89
+ response: {
90
+ attestationObject: bytesToBase64url(new Uint8Array(attestation.attestationObject)),
91
+ clientDataJSON: bytesToBase64url(new Uint8Array(attestation.clientDataJSON)),
92
+ transports: typeof attestation.getTransports === "function" ? attestation.getTransports() : []
93
+ },
94
+ clientExtensionResults: credential.getClientExtensionResults?.() ?? {},
95
+ authenticatorAttachment: credential.authenticatorAttachment ?? null
96
+ };
97
+ const res = await fetch(`${apiBase}/api/passkey-anon/enroll/complete`, {
98
+ method: "POST",
99
+ headers: { "content-type": "application/json" },
100
+ body: JSON.stringify({ credential: credentialJson })
101
+ });
102
+ if (!res.ok) throw new ConnectError(await readErrorCode(res), `enroll/complete ${res.status}`);
103
+ return await res.json();
104
+ }
105
+ async function initializeVault(apiBase, userHandle, credentialId) {
106
+ const res = await fetch(`${apiBase}/api/passkey-vault-anon/initialize`, {
107
+ method: "POST",
108
+ headers: { "content-type": "application/json" },
109
+ body: JSON.stringify({ userHandle, credentialId, coolingOffSeconds: 0 })
110
+ });
111
+ if (!res.ok) throw new ConnectError(await readErrorCode(res), `initialize ${res.status}`);
112
+ return await res.json();
113
+ }
114
+ function toBuf(b64url) {
115
+ return base64urlToBytes(b64url).buffer.slice(0);
116
+ }
117
+ function buildCreationOptions(o, name, rpId) {
118
+ return {
119
+ // rp.name = the site shown in the keychain; user.name/displayName = the
120
+ // wallet label the user sees. We override the server's user.name (a raw,
121
+ // unreadable handle) with the chosen wallet name.
122
+ rp: { id: o.rp.id ?? rpId, name: "Dexter" },
123
+ user: {
124
+ id: toBuf(o.user.id),
125
+ name,
126
+ displayName: name
127
+ },
128
+ challenge: toBuf(o.challenge),
129
+ pubKeyCredParams: o.pubKeyCredParams,
130
+ timeout: o.timeout,
131
+ excludeCredentials: o.excludeCredentials?.map((c) => ({
132
+ id: toBuf(c.id),
133
+ type: c.type,
134
+ transports: c.transports
135
+ })),
136
+ authenticatorSelection: o.authenticatorSelection,
137
+ attestation: o.attestation
138
+ };
139
+ }
140
+ async function readErrorCode(res) {
141
+ try {
142
+ const body = await res.json();
143
+ if (body?.error) return body.error;
144
+ } catch {
145
+ }
146
+ return `http_${res.status}`;
147
+ }
15
148
  export {
16
149
  ACTIVE_WALLET_STORAGE_KEY,
17
150
  ConnectError,
18
151
  createAnonServerPolicy,
19
152
  createPasskeySigner,
153
+ createWallet,
20
154
  ejectActiveWallet,
21
155
  forgetWallet,
22
156
  getActiveHandle,
157
+ getCredentialId,
23
158
  listWallets,
24
159
  passkeyLogin,
160
+ passkeySignalSupport,
161
+ prunePasskey,
162
+ renamePasskey,
25
163
  setActiveHandle,
26
164
  subscribe as subscribeWallet,
27
- switchWallet
165
+ switchWallet,
166
+ syncAcceptedPasskeys
28
167
  };
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, b as StoredWallet } from './walletStore-CWXhXuzK.js';
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';
@@ -69,19 +69,28 @@ interface UseDexterWallet {
69
69
  activeHandle: string | null;
70
70
  /** Known wallets on this browser, most-recently-used first. */
71
71
  wallets: StoredWallet[];
72
+ /** What the WebAuthn Signal API supports in THIS browser (rename / prune). */
73
+ support: PasskeySignalSupport;
72
74
  /**
73
- * Eject the active wallet — "switch / start fresh / sign out of this wallet".
74
- * The browser is no longer bound to it; the next enroll/recover starts clean.
75
- * Pass `{ forget: true }` to also drop it from the roster.
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.
76
79
  */
77
80
  eject: (opts?: {
78
81
  forget?: boolean;
79
82
  }) => void;
80
83
  /** Switch the active wallet to a known handle. No-op if unknown. */
81
84
  switchTo: (handle: string) => boolean;
82
- /** Record/activate a handle (after enroll or recover). Prefer this over
83
- * hand-writing localStorage so the roster + subscribers stay correct. */
84
- setActive: (handle: string, label?: string) => void;
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>;
85
94
  }
86
95
  declare function useDexterWallet(): UseDexterWallet;
87
96
 
package/dist/react.js CHANGED
@@ -3,12 +3,16 @@ import {
3
3
  createPasskeySigner,
4
4
  ejectActiveWallet,
5
5
  getActiveHandle,
6
+ getCredentialId,
6
7
  listWallets,
7
8
  passkeyLogin,
9
+ passkeySignalSupport,
10
+ prunePasskey,
11
+ renamePasskey,
8
12
  setActiveHandle,
9
13
  subscribe,
10
14
  switchWallet
11
- } from "./chunk-HFG2GUFX.js";
15
+ } from "./chunk-LYIBVWRG.js";
12
16
 
13
17
  // src/useSignInWithDexter.ts
14
18
  import { useCallback, useEffect, useMemo, useState } from "react";
@@ -207,23 +211,44 @@ var DISCONNECT = {
207
211
 
208
212
  // src/useDexterWallet.ts
209
213
  import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
214
+ var NO_SUPPORT = { rename: false, prune: false, syncAccepted: false };
210
215
  function useDexterWallet() {
211
216
  const [activeHandle, setHandle] = useState2(() => getActiveHandle());
212
217
  const [wallets, setWallets] = useState2(() => listWallets());
218
+ const [support, setSupport] = useState2(NO_SUPPORT);
213
219
  useEffect2(() => {
214
220
  const sync = () => {
215
221
  setHandle(getActiveHandle());
216
222
  setWallets(listWallets());
217
223
  };
224
+ setSupport(passkeySignalSupport());
218
225
  sync();
219
226
  return subscribe(sync);
220
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
+ }, []);
221
241
  return {
222
242
  activeHandle,
223
243
  wallets,
224
- eject: useCallback2((opts) => ejectActiveWallet(opts), []),
244
+ support,
245
+ eject,
225
246
  switchTo: useCallback2((handle) => switchWallet(handle), []),
226
- setActive: useCallback2((handle, label) => setActiveHandle(handle, label), [])
247
+ setActive: useCallback2(
248
+ (handle, label, credentialId) => setActiveHandle(handle, label, credentialId),
249
+ []
250
+ ),
251
+ rename
227
252
  };
228
253
  }
229
254
  export {
@@ -48,6 +48,9 @@ interface StoredWallet {
48
48
  handle: string;
49
49
  /** Human label for switch UIs (e.g. an email, or "Dexter Wallet"). */
50
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;
51
54
  /** Epoch ms of last activation — for ordering the switcher. */
52
55
  lastUsedAt?: number;
53
56
  }
@@ -58,7 +61,9 @@ declare function getActiveHandle(): string | null;
58
61
  * Set the active wallet handle (e.g. after enroll or recover), upserting it into
59
62
  * the roster with a fresh `lastUsedAt`. Idempotent. Fires subscribers.
60
63
  */
61
- declare function setActiveHandle(handle: string, label?: string): void;
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;
62
67
  /**
63
68
  * EJECT — clear the active wallet so the browser is no longer bound to it. This
64
69
  * is "switch / start fresh / sign out of this wallet". The wallet stays in the
@@ -89,4 +94,49 @@ declare function subscribe(listener: Listener): () => void;
89
94
  * tests). Prefer the accessors above — do NOT read localStorage by hand. */
90
95
  declare const ACTIVE_WALLET_STORAGE_KEY = "dexter:passkey:userHandle";
91
96
 
92
- 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 StoredWallet as b, subscribe as c, switchWallet as d, ejectActiveWallet as e, forgetWallet as f, getActiveHandle as g, listWallets as l, setActiveHandle as s };
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexterai/connect",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Sign in with Dexter — passkey connector. Composes @dexterai/vault.",
5
5
  "type": "module",
6
6
  "exports": {