@dexterai/connect 0.8.0 → 0.9.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.
@@ -63,10 +63,13 @@ function derInteger(component) {
63
63
  // src/relay.ts
64
64
  var DEFAULT_API_BASE = "https://api.dexter.cash";
65
65
  var ANON_SIGN_BASE = "/api/passkey-anon/sign";
66
- async function passkeyLogin(config = {}) {
66
+ async function passkeyLogin(config = {}, onPhase) {
67
67
  const apiBase = (config.apiBase ?? DEFAULT_API_BASE).replace(/\/$/, "");
68
+ onPhase?.("challenge");
68
69
  const options = await fetchLoginChallenge(apiBase);
70
+ onPhase?.("passkey");
69
71
  const credential = await getAssertion(options);
72
+ onPhase?.("verifying");
70
73
  return submitLogin(apiBase, credential);
71
74
  }
72
75
  async function fetchLoginChallenge(apiBase) {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
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';
1
+ import { D as DexterConnectConfig, C as CeremonyPhase, S as SignInResult, a as ConnectVault } from './signals-CXkNJfIo.js';
2
+ export { A as ACTIVE_WALLET_STORAGE_KEY, b as ConnectError, P as PasskeyLoginTokens, c as PasskeySignalSupport, d as StoredWallet, e as ejectActiveWallet, f as forgetWallet, g as getActiveHandle, h as getCredentialId, l as listWallets, p as passkeySignalSupport, i as prunePasskey, r as renamePasskey, s as setActiveHandle, j as subscribeWallet, k as switchWallet, m as syncAcceptedPasskeys } from './signals-CXkNJfIo.js';
3
3
  import { DexterApiBrowserPasskeySigner } from '@dexterai/vault/signers/browser';
4
4
 
5
5
  /**
@@ -15,7 +15,7 @@ import { DexterApiBrowserPasskeySigner } from '@dexterai/vault/signers/browser';
15
15
  * Relays to dexter-api's ANON router — a first-time third-party user has no
16
16
  * Supabase session, so the Supabase-gated router would 401.
17
17
  */
18
- declare function passkeyLogin(config?: DexterConnectConfig): Promise<SignInResult>;
18
+ declare function passkeyLogin(config?: DexterConnectConfig, onPhase?: (phase: CeremonyPhase) => void): Promise<SignInResult>;
19
19
 
20
20
  /** What `issueChallenge` returns to the SDK signer. */
21
21
  interface AnonChallengeResult {
@@ -82,6 +82,9 @@ interface CreateWalletConfig extends DexterConnectConfig {
82
82
  name?: string;
83
83
  /** RP id for the new credential. Default "dexter.cash". */
84
84
  rpId?: string;
85
+ /** Called as the ceremony progresses, for live "connecting steps" UI:
86
+ * challenge → passkey → verifying → finalizing. */
87
+ onPhase?: (phase: CeremonyPhase) => void;
85
88
  }
86
89
  interface CreateWalletResult {
87
90
  /** Server-minted 16-byte user handle, base64url — the vault identity. */
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  subscribe,
19
19
  switchWallet,
20
20
  syncAcceptedPasskeys
21
- } from "./chunk-LYIBVWRG.js";
21
+ } from "./chunk-W5ISTMTY.js";
22
22
 
23
23
  // src/enroll.ts
24
24
  var DEFAULT_API_BASE = "https://api.dexter.cash";
@@ -31,9 +31,13 @@ async function createWallet(config = {}) {
31
31
  const apiBase = (config.apiBase ?? DEFAULT_API_BASE).replace(/\/$/, "");
32
32
  const rpId = config.rpId ?? DEFAULT_RP_ID;
33
33
  const name = config.name && config.name.trim() || DEFAULT_WALLET_NAME;
34
+ config.onPhase?.("challenge");
34
35
  const options = await fetchEnrollChallenge(apiBase);
36
+ config.onPhase?.("passkey");
35
37
  const credential = await createCredential(options, name, rpId);
38
+ config.onPhase?.("verifying");
36
39
  const enrolled = await submitEnrollComplete(apiBase, credential);
40
+ config.onPhase?.("finalizing");
37
41
  const init = await initializeVault(apiBase, enrolled.userHandle, enrolled.credentialId);
38
42
  setActiveHandle(enrolled.userHandle, name, enrolled.credentialId);
39
43
  return {
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, c as StoredWallet, b as PasskeySignalSupport } from './signals-CkBFwCNw.js';
2
+ import { C as CeremonyPhase, S as SignInResult, P as PasskeyLoginTokens, a as ConnectVault, b as ConnectError, d as StoredWallet, c as PasskeySignalSupport } from './signals-CXkNJfIo.js';
3
3
  import { ReactElement, ReactNode } from 'react';
4
4
 
5
5
  type ConnectStatus = 'idle' | 'pending' | 'done' | 'error';
@@ -11,6 +11,9 @@ interface UseSignInWithDexterConfig {
11
11
  }
12
12
  interface UseSignInWithDexter {
13
13
  status: ConnectStatus;
14
+ /** Live ceremony phase while status==='pending' (challenge → passkey →
15
+ * verifying); null otherwise. Drives the button's "connecting steps". */
16
+ phase: CeremonyPhase | null;
14
17
  isVaultConnected: boolean;
15
18
  /** Run the ceremony. Resolves with the result; throws ConnectError on failure
16
19
  * (error is also captured in `error` + `status==='error'` for declarative UI). */
package/dist/react.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  setActiveHandle,
13
13
  subscribe,
14
14
  switchWallet
15
- } from "./chunk-LYIBVWRG.js";
15
+ } from "./chunk-W5ISTMTY.js";
16
16
 
17
17
  // src/useSignInWithDexter.ts
18
18
  import { useCallback, useEffect, useMemo, useState } from "react";
@@ -59,6 +59,7 @@ var DEFAULT_RPC = "https://api.dexter.cash/proxy/helius/rpc";
59
59
  function useSignInWithDexter(config = {}) {
60
60
  const { apiBase, rpcUrl = DEFAULT_RPC } = config;
61
61
  const [status, setStatus] = useState("idle");
62
+ const [phase, setPhase] = useState(null);
62
63
  const [session, setSession] = useState(null);
63
64
  const [vault, setVault] = useState(null);
64
65
  const [usdcBalance, setUsdcBalance] = useState(null);
@@ -70,17 +71,20 @@ function useSignInWithDexter(config = {}) {
70
71
  }, [vault, rpcUrl]);
71
72
  const signIn = useCallback(async () => {
72
73
  setError(null);
74
+ setPhase(null);
73
75
  setStatus("pending");
74
76
  try {
75
- const result = await passkeyLogin(apiBase ? { apiBase } : {});
77
+ const result = await passkeyLogin(apiBase ? { apiBase } : {}, setPhase);
76
78
  setSession(result.session);
77
79
  setVault(result.vault ?? null);
78
80
  setStatus("done");
81
+ setPhase(null);
79
82
  return result;
80
83
  } catch (err) {
81
84
  const e = err instanceof ConnectError ? err : new ConnectError("sign_in_failed", String(err));
82
85
  setError(e);
83
86
  setStatus("error");
87
+ setPhase(null);
84
88
  throw e;
85
89
  }
86
90
  }, [apiBase]);
@@ -100,6 +104,7 @@ function useSignInWithDexter(config = {}) {
100
104
  }, [refreshBalance]);
101
105
  return {
102
106
  status,
107
+ phase,
103
108
  isVaultConnected: status === "done" && vault !== null,
104
109
  signIn,
105
110
  disconnect,
@@ -221,6 +226,12 @@ function DexterButton(props) {
221
226
 
222
227
  // src/SignInWithDexter.tsx
223
228
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
229
+ var PHASE_LABEL = {
230
+ challenge: "Preparing\u2026",
231
+ passkey: "Waiting for your passkey\u2026",
232
+ verifying: "Verifying\u2026",
233
+ finalizing: "Finishing\u2026"
234
+ };
224
235
  function shortAddress(addr) {
225
236
  return addr.length > 10 ? `${addr.slice(0, 4)}\u2026${addr.slice(-4)}` : addr;
226
237
  }
@@ -263,6 +274,7 @@ function SignInWithDexter(props) {
263
274
  DexterButton,
264
275
  {
265
276
  loading: c.status === "pending",
277
+ loadingLabel: c.phase ? PHASE_LABEL[c.phase] : "Connecting\u2026",
266
278
  variant,
267
279
  block,
268
280
  className,
@@ -32,6 +32,12 @@ interface SignInResult {
32
32
  /** Present once vault-review ships the vault-in-login change. */
33
33
  vault?: ConnectVault;
34
34
  }
35
+ /**
36
+ * Coarse ceremony phase, emitted as a sign-in/create ceremony progresses so the
37
+ * UI can show live "connecting steps" instead of one flat spinner:
38
+ * challenge → passkey (the OS prompt) → verifying → finalizing (create only).
39
+ */
40
+ type CeremonyPhase = 'challenge' | 'passkey' | 'verifying' | 'finalizing';
35
41
  interface DexterConnectConfig {
36
42
  /** dexter-api base. Default https://api.dexter.cash. */
37
43
  apiBase?: string;
@@ -139,4 +145,4 @@ declare function syncAcceptedPasskeys(args: {
139
145
  rpId?: string;
140
146
  }): Promise<boolean>;
141
147
 
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 };
148
+ export { ACTIVE_WALLET_STORAGE_KEY as A, type CeremonyPhase as C, type DexterConnectConfig as D, type PasskeyLoginTokens as P, type SignInResult as S, type ConnectVault as a, ConnectError as b, type PasskeySignalSupport as c, type StoredWallet as d, ejectActiveWallet as e, forgetWallet as f, getActiveHandle as g, getCredentialId as h, prunePasskey as i, subscribe as j, switchWallet as k, listWallets as l, syncAcceptedPasskeys as m, 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.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Sign in with Dexter — passkey connector. Composes @dexterai/vault.",
5
5
  "type": "module",
6
6
  "exports": {