@dexterai/connect 0.7.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,
|
|
2
|
-
export { A as ACTIVE_WALLET_STORAGE_KEY,
|
|
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-
|
|
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,6 +1,6 @@
|
|
|
1
1
|
import { DexterApiBrowserPasskeySigner } from '@dexterai/vault/signers/browser';
|
|
2
|
-
import { S as SignInResult, P as PasskeyLoginTokens,
|
|
3
|
-
import { ReactElement } from 'react';
|
|
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
|
+
import { ReactElement, ReactNode } from 'react';
|
|
4
4
|
|
|
5
5
|
type ConnectStatus = 'idle' | 'pending' | 'done' | 'error';
|
|
6
6
|
interface UseSignInWithDexterConfig {
|
|
@@ -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). */
|
|
@@ -48,24 +51,49 @@ interface SignInWithDexterProps extends UseSignInWithDexterConfig {
|
|
|
48
51
|
onError?: (error: ConnectError) => void;
|
|
49
52
|
/** Button label when signed out. Default "Sign in with Dexter". */
|
|
50
53
|
label?: string;
|
|
51
|
-
/**
|
|
54
|
+
/** 'primary' = filled ember (default), 'secondary' = outline. */
|
|
52
55
|
variant?: 'primary' | 'secondary';
|
|
56
|
+
/** Full-width button. */
|
|
57
|
+
block?: boolean;
|
|
53
58
|
/** Extra className composed after the brand classes. Prefer overriding the
|
|
54
|
-
* `--dx-*` CSS variables for theming
|
|
59
|
+
* `--dx-*` CSS variables for theming. */
|
|
55
60
|
className?: string;
|
|
56
|
-
/** Render the built-in connected chip (wallet + balance). Default true.
|
|
57
|
-
* Set false to render nothing once connected (consumer renders its own UI). */
|
|
61
|
+
/** Render the built-in connected chip (wallet + balance). Default true. */
|
|
58
62
|
showConnectedChip?: boolean;
|
|
59
63
|
}
|
|
60
64
|
/**
|
|
61
|
-
* Turnkey "Sign in with Dexter" element. Signed out → the branded
|
|
65
|
+
* Turnkey "Sign in with Dexter" element. Signed out → the branded DexterButton
|
|
62
66
|
* (hover / focus / active / loading states, themeable via --dx-* CSS vars);
|
|
63
67
|
* signed in → a compact chip with the Dexter Wallet address + USD available.
|
|
64
|
-
* Wraps useSignInWithDexter;
|
|
65
|
-
*
|
|
68
|
+
* Wraps useSignInWithDexter; for the wallet CREATE flow use <DexterButton>
|
|
69
|
+
* wired to your create action. Brand voice: no emojis, "unlock" banned.
|
|
66
70
|
*/
|
|
67
71
|
declare function SignInWithDexter(props: SignInWithDexterProps): ReactElement | null;
|
|
68
72
|
|
|
73
|
+
/** The Dexter passkey mark — the brand glyph carried on the branded button. */
|
|
74
|
+
declare function DexterMark(): ReactElement;
|
|
75
|
+
interface DexterButtonProps {
|
|
76
|
+
/** Button content (e.g. "Sign in with Dexter", "Create your Dexter Wallet"). */
|
|
77
|
+
children?: ReactNode;
|
|
78
|
+
/** Loading state: shows the animated spinner + `loadingLabel`, disables click. */
|
|
79
|
+
loading?: boolean;
|
|
80
|
+
/** Label shown next to the spinner while loading. Default "Connecting…". */
|
|
81
|
+
loadingLabel?: string;
|
|
82
|
+
/** 'primary' = filled ember (default), 'secondary' = outline. */
|
|
83
|
+
variant?: 'primary' | 'secondary';
|
|
84
|
+
/** Full-width (fills its container). */
|
|
85
|
+
block?: boolean;
|
|
86
|
+
/** Render the Dexter mark before the children. Default true. */
|
|
87
|
+
withMark?: boolean;
|
|
88
|
+
onClick?: () => void;
|
|
89
|
+
disabled?: boolean;
|
|
90
|
+
/** Extra className composed after the brand classes. */
|
|
91
|
+
className?: string;
|
|
92
|
+
type?: 'button' | 'submit';
|
|
93
|
+
}
|
|
94
|
+
/** The branded Dexter button. Wire it to any action via `onClick`. */
|
|
95
|
+
declare function DexterButton(props: DexterButtonProps): ReactElement;
|
|
96
|
+
|
|
69
97
|
interface UseDexterWallet {
|
|
70
98
|
/** Active wallet handle, or null if this browser has no active wallet. */
|
|
71
99
|
activeHandle: string | null;
|
|
@@ -96,4 +124,4 @@ interface UseDexterWallet {
|
|
|
96
124
|
}
|
|
97
125
|
declare function useDexterWallet(): UseDexterWallet;
|
|
98
126
|
|
|
99
|
-
export { type ConnectStatus, SignInWithDexter, type SignInWithDexterProps, type UseDexterWallet, type UseSignInWithDexter, type UseSignInWithDexterConfig, useDexterWallet, useSignInWithDexter };
|
|
127
|
+
export { type ConnectStatus, DexterButton, type DexterButtonProps, DexterMark, SignInWithDexter, type SignInWithDexterProps, type UseDexterWallet, type UseSignInWithDexter, type UseSignInWithDexterConfig, useDexterWallet, useSignInWithDexter };
|
package/dist/react.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
setActiveHandle,
|
|
13
13
|
subscribe,
|
|
14
14
|
switchWallet
|
|
15
|
-
} from "./chunk-
|
|
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,
|
|
@@ -116,6 +121,9 @@ function useSignInWithDexter(config = {}) {
|
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
// src/SignInWithDexter.tsx
|
|
124
|
+
import { useEffect as useEffect3 } from "react";
|
|
125
|
+
|
|
126
|
+
// src/DexterButton.tsx
|
|
119
127
|
import { useEffect as useEffect2 } from "react";
|
|
120
128
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
121
129
|
var STYLE_ID = "dexter-connect-button-styles";
|
|
@@ -139,6 +147,7 @@ var BUTTON_CSS = `
|
|
|
139
147
|
.dx-btn:disabled{ cursor:default; filter:saturate(.85) brightness(.98); }
|
|
140
148
|
.dx-btn--secondary{ background:transparent; color:var(--dx-ember); box-shadow:none; border-color:color-mix(in srgb,var(--dx-ember) 45%,transparent); }
|
|
141
149
|
.dx-btn--secondary:hover{ background:color-mix(in srgb,var(--dx-ember) 9%,transparent); filter:none; box-shadow:none; }
|
|
150
|
+
.dx-btn--block{ width:100%; }
|
|
142
151
|
.dx-btn__mark{ flex-shrink:0; }
|
|
143
152
|
.dx-btn__spin{ width:15px; height:15px; flex-shrink:0; border-radius:50%;
|
|
144
153
|
border:2px solid color-mix(in srgb,currentColor 30%,transparent); border-top-color:currentColor;
|
|
@@ -152,7 +161,7 @@ var BUTTON_CSS = `
|
|
|
152
161
|
.dx-chip__x{ margin-left:2px; border:none; background:transparent; color:inherit; cursor:pointer; font-size:16px; line-height:1; opacity:.6; }
|
|
153
162
|
.dx-chip__x:hover{ opacity:1; }
|
|
154
163
|
`;
|
|
155
|
-
function
|
|
164
|
+
function ensureDexterButtonStyles() {
|
|
156
165
|
if (typeof document === "undefined") return;
|
|
157
166
|
if (document.getElementById(STYLE_ID)) return;
|
|
158
167
|
const el = document.createElement("style");
|
|
@@ -160,16 +169,10 @@ function ensureStyles() {
|
|
|
160
169
|
el.textContent = BUTTON_CSS;
|
|
161
170
|
document.head.appendChild(el);
|
|
162
171
|
}
|
|
163
|
-
|
|
172
|
+
ensureDexterButtonStyles();
|
|
164
173
|
function cx(...parts) {
|
|
165
174
|
return parts.filter(Boolean).join(" ");
|
|
166
175
|
}
|
|
167
|
-
function shortAddress(addr) {
|
|
168
|
-
return addr.length > 10 ? `${addr.slice(0, 4)}\u2026${addr.slice(-4)}` : addr;
|
|
169
|
-
}
|
|
170
|
-
function formatUsd(n) {
|
|
171
|
-
return n.toLocaleString("en-US", { style: "currency", currency: "USD" });
|
|
172
|
-
}
|
|
173
176
|
function DexterMark() {
|
|
174
177
|
return /* @__PURE__ */ jsxs(
|
|
175
178
|
"svg",
|
|
@@ -188,17 +191,65 @@ function DexterMark() {
|
|
|
188
191
|
}
|
|
189
192
|
);
|
|
190
193
|
}
|
|
194
|
+
function DexterButton(props) {
|
|
195
|
+
const {
|
|
196
|
+
children,
|
|
197
|
+
loading = false,
|
|
198
|
+
loadingLabel = "Connecting\u2026",
|
|
199
|
+
variant = "primary",
|
|
200
|
+
block = false,
|
|
201
|
+
withMark = true,
|
|
202
|
+
onClick,
|
|
203
|
+
disabled = false,
|
|
204
|
+
className,
|
|
205
|
+
type = "button"
|
|
206
|
+
} = props;
|
|
207
|
+
useEffect2(ensureDexterButtonStyles, []);
|
|
208
|
+
return /* @__PURE__ */ jsx(
|
|
209
|
+
"button",
|
|
210
|
+
{
|
|
211
|
+
type,
|
|
212
|
+
className: cx("dx-btn", variant === "secondary" && "dx-btn--secondary", block && "dx-btn--block", className),
|
|
213
|
+
onClick,
|
|
214
|
+
disabled: disabled || loading,
|
|
215
|
+
"aria-busy": loading,
|
|
216
|
+
children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
217
|
+
/* @__PURE__ */ jsx("span", { className: "dx-btn__spin", "aria-hidden": true }),
|
|
218
|
+
/* @__PURE__ */ jsx("span", { className: "dx-btn__doing", children: loadingLabel })
|
|
219
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
220
|
+
withMark && /* @__PURE__ */ jsx(DexterMark, {}),
|
|
221
|
+
children
|
|
222
|
+
] })
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/SignInWithDexter.tsx
|
|
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
|
+
};
|
|
235
|
+
function shortAddress(addr) {
|
|
236
|
+
return addr.length > 10 ? `${addr.slice(0, 4)}\u2026${addr.slice(-4)}` : addr;
|
|
237
|
+
}
|
|
238
|
+
function formatUsd(n) {
|
|
239
|
+
return n.toLocaleString("en-US", { style: "currency", currency: "USD" });
|
|
240
|
+
}
|
|
191
241
|
function SignInWithDexter(props) {
|
|
192
242
|
const {
|
|
193
243
|
onSuccess,
|
|
194
244
|
onError,
|
|
195
245
|
label = "Sign in with Dexter",
|
|
196
246
|
variant = "primary",
|
|
247
|
+
block = false,
|
|
197
248
|
className,
|
|
198
249
|
showConnectedChip = true,
|
|
199
250
|
...config
|
|
200
251
|
} = props;
|
|
201
|
-
|
|
252
|
+
useEffect3(ensureDexterButtonStyles, []);
|
|
202
253
|
const c = useSignInWithDexter(config);
|
|
203
254
|
const handleClick = async () => {
|
|
204
255
|
try {
|
|
@@ -209,44 +260,38 @@ function SignInWithDexter(props) {
|
|
|
209
260
|
};
|
|
210
261
|
if (c.isVaultConnected) {
|
|
211
262
|
if (!showConnectedChip) return null;
|
|
212
|
-
return /* @__PURE__ */
|
|
213
|
-
/* @__PURE__ */
|
|
214
|
-
/* @__PURE__ */
|
|
215
|
-
c.usdcBalance !== null && /* @__PURE__ */
|
|
263
|
+
return /* @__PURE__ */ jsxs2("span", { className: cx("dx-chip", className), children: [
|
|
264
|
+
/* @__PURE__ */ jsx2("span", { className: "dx-chip__dot", "aria-hidden": true }),
|
|
265
|
+
/* @__PURE__ */ jsx2("span", { children: c.vaultAddress ? shortAddress(c.vaultAddress) : "Connected" }),
|
|
266
|
+
c.usdcBalance !== null && /* @__PURE__ */ jsxs2("span", { className: "dx-chip__bal", children: [
|
|
216
267
|
formatUsd(c.usdcBalance),
|
|
217
268
|
" available"
|
|
218
269
|
] }),
|
|
219
|
-
/* @__PURE__ */
|
|
270
|
+
/* @__PURE__ */ jsx2("button", { type: "button", className: "dx-chip__x", onClick: c.disconnect, "aria-label": "Disconnect", children: "\xD7" })
|
|
220
271
|
] });
|
|
221
272
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
"button",
|
|
273
|
+
return /* @__PURE__ */ jsx2(
|
|
274
|
+
DexterButton,
|
|
225
275
|
{
|
|
226
|
-
|
|
227
|
-
|
|
276
|
+
loading: c.status === "pending",
|
|
277
|
+
loadingLabel: c.phase ? PHASE_LABEL[c.phase] : "Connecting\u2026",
|
|
278
|
+
variant,
|
|
279
|
+
block,
|
|
280
|
+
className,
|
|
228
281
|
onClick: handleClick,
|
|
229
|
-
|
|
230
|
-
"aria-busy": pending,
|
|
231
|
-
children: pending ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
232
|
-
/* @__PURE__ */ jsx("span", { className: "dx-btn__spin", "aria-hidden": true }),
|
|
233
|
-
/* @__PURE__ */ jsx("span", { className: "dx-btn__doing", children: "Connecting\u2026" })
|
|
234
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
235
|
-
/* @__PURE__ */ jsx(DexterMark, {}),
|
|
236
|
-
label
|
|
237
|
-
] })
|
|
282
|
+
children: label
|
|
238
283
|
}
|
|
239
284
|
);
|
|
240
285
|
}
|
|
241
286
|
|
|
242
287
|
// src/useDexterWallet.ts
|
|
243
|
-
import { useCallback as useCallback2, useEffect as
|
|
288
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useState as useState2 } from "react";
|
|
244
289
|
var NO_SUPPORT = { rename: false, prune: false, syncAccepted: false };
|
|
245
290
|
function useDexterWallet() {
|
|
246
291
|
const [activeHandle, setHandle] = useState2(() => getActiveHandle());
|
|
247
292
|
const [wallets, setWallets] = useState2(() => listWallets());
|
|
248
293
|
const [support, setSupport] = useState2(NO_SUPPORT);
|
|
249
|
-
|
|
294
|
+
useEffect4(() => {
|
|
250
295
|
const sync = () => {
|
|
251
296
|
setHandle(getActiveHandle());
|
|
252
297
|
setWallets(listWallets());
|
|
@@ -282,6 +327,8 @@ function useDexterWallet() {
|
|
|
282
327
|
};
|
|
283
328
|
}
|
|
284
329
|
export {
|
|
330
|
+
DexterButton,
|
|
331
|
+
DexterMark,
|
|
285
332
|
SignInWithDexter,
|
|
286
333
|
useDexterWallet,
|
|
287
334
|
useSignInWithDexter
|
|
@@ -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
|
|
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 };
|