@dexterai/connect 0.8.0 → 0.10.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) {
|
|
@@ -344,6 +347,17 @@ function onStorageEvent(e) {
|
|
|
344
347
|
}
|
|
345
348
|
var ACTIVE_WALLET_STORAGE_KEY = ACTIVE_HANDLE_KEY;
|
|
346
349
|
|
|
350
|
+
// src/phase.ts
|
|
351
|
+
var PHASE_LABEL = {
|
|
352
|
+
challenge: "Preparing\u2026",
|
|
353
|
+
passkey: "Waiting for your passkey\u2026",
|
|
354
|
+
verifying: "Verifying\u2026",
|
|
355
|
+
finalizing: "Finishing\u2026"
|
|
356
|
+
};
|
|
357
|
+
function ceremonyPhaseLabel(phase) {
|
|
358
|
+
return PHASE_LABEL[phase];
|
|
359
|
+
}
|
|
360
|
+
|
|
347
361
|
// src/signals.ts
|
|
348
362
|
function pkc() {
|
|
349
363
|
if (typeof window === "undefined") return null;
|
|
@@ -420,6 +434,7 @@ export {
|
|
|
420
434
|
forgetWallet,
|
|
421
435
|
subscribe,
|
|
422
436
|
ACTIVE_WALLET_STORAGE_KEY,
|
|
437
|
+
ceremonyPhaseLabel,
|
|
423
438
|
passkeySignalSupport,
|
|
424
439
|
renamePasskey,
|
|
425
440
|
prunePasskey,
|
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. */
|
|
@@ -99,4 +102,12 @@ interface CreateWalletResult {
|
|
|
99
102
|
*/
|
|
100
103
|
declare function createWallet(config?: CreateWalletConfig): Promise<CreateWalletResult>;
|
|
101
104
|
|
|
102
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Human-readable label for a ceremony phase — the live "connecting step" copy.
|
|
107
|
+
* ONE source of truth so sign-in (SignInWithDexter) and create (consumer setup
|
|
108
|
+
* flows) show identical wording. Consumers surfacing createWallet's `onPhase`
|
|
109
|
+
* should use this instead of hand-rolling their own strings (Rule #7).
|
|
110
|
+
*/
|
|
111
|
+
declare function ceremonyPhaseLabel(phase: CeremonyPhase): string;
|
|
112
|
+
|
|
113
|
+
export { type AnonChallengeResult, type AnonServerPolicy, CeremonyPhase, ConnectVault, type CreateWalletConfig, type CreateWalletResult, DexterConnectConfig, SignInResult, ceremonyPhaseLabel, createAnonServerPolicy, createPasskeySigner, createWallet, passkeyLogin };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ConnectError,
|
|
4
4
|
base64urlToBytes,
|
|
5
5
|
bytesToBase64url,
|
|
6
|
+
ceremonyPhaseLabel,
|
|
6
7
|
createAnonServerPolicy,
|
|
7
8
|
createPasskeySigner,
|
|
8
9
|
ejectActiveWallet,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
subscribe,
|
|
19
20
|
switchWallet,
|
|
20
21
|
syncAcceptedPasskeys
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-ZHJ557FI.js";
|
|
22
23
|
|
|
23
24
|
// src/enroll.ts
|
|
24
25
|
var DEFAULT_API_BASE = "https://api.dexter.cash";
|
|
@@ -31,9 +32,13 @@ async function createWallet(config = {}) {
|
|
|
31
32
|
const apiBase = (config.apiBase ?? DEFAULT_API_BASE).replace(/\/$/, "");
|
|
32
33
|
const rpId = config.rpId ?? DEFAULT_RP_ID;
|
|
33
34
|
const name = config.name && config.name.trim() || DEFAULT_WALLET_NAME;
|
|
35
|
+
config.onPhase?.("challenge");
|
|
34
36
|
const options = await fetchEnrollChallenge(apiBase);
|
|
37
|
+
config.onPhase?.("passkey");
|
|
35
38
|
const credential = await createCredential(options, name, rpId);
|
|
39
|
+
config.onPhase?.("verifying");
|
|
36
40
|
const enrolled = await submitEnrollComplete(apiBase, credential);
|
|
41
|
+
config.onPhase?.("finalizing");
|
|
37
42
|
const init = await initializeVault(apiBase, enrolled.userHandle, enrolled.credentialId);
|
|
38
43
|
setActiveHandle(enrolled.userHandle, name, enrolled.credentialId);
|
|
39
44
|
return {
|
|
@@ -148,6 +153,7 @@ async function readErrorCode(res) {
|
|
|
148
153
|
export {
|
|
149
154
|
ACTIVE_WALLET_STORAGE_KEY,
|
|
150
155
|
ConnectError,
|
|
156
|
+
ceremonyPhaseLabel,
|
|
151
157
|
createAnonServerPolicy,
|
|
152
158
|
createPasskeySigner,
|
|
153
159
|
createWallet,
|
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,
|
|
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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConnectError,
|
|
3
|
+
ceremonyPhaseLabel,
|
|
3
4
|
createPasskeySigner,
|
|
4
5
|
ejectActiveWallet,
|
|
5
6
|
getActiveHandle,
|
|
@@ -12,7 +13,7 @@ import {
|
|
|
12
13
|
setActiveHandle,
|
|
13
14
|
subscribe,
|
|
14
15
|
switchWallet
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ZHJ557FI.js";
|
|
16
17
|
|
|
17
18
|
// src/useSignInWithDexter.ts
|
|
18
19
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
@@ -59,6 +60,7 @@ var DEFAULT_RPC = "https://api.dexter.cash/proxy/helius/rpc";
|
|
|
59
60
|
function useSignInWithDexter(config = {}) {
|
|
60
61
|
const { apiBase, rpcUrl = DEFAULT_RPC } = config;
|
|
61
62
|
const [status, setStatus] = useState("idle");
|
|
63
|
+
const [phase, setPhase] = useState(null);
|
|
62
64
|
const [session, setSession] = useState(null);
|
|
63
65
|
const [vault, setVault] = useState(null);
|
|
64
66
|
const [usdcBalance, setUsdcBalance] = useState(null);
|
|
@@ -70,17 +72,20 @@ function useSignInWithDexter(config = {}) {
|
|
|
70
72
|
}, [vault, rpcUrl]);
|
|
71
73
|
const signIn = useCallback(async () => {
|
|
72
74
|
setError(null);
|
|
75
|
+
setPhase(null);
|
|
73
76
|
setStatus("pending");
|
|
74
77
|
try {
|
|
75
|
-
const result = await passkeyLogin(apiBase ? { apiBase } : {});
|
|
78
|
+
const result = await passkeyLogin(apiBase ? { apiBase } : {}, setPhase);
|
|
76
79
|
setSession(result.session);
|
|
77
80
|
setVault(result.vault ?? null);
|
|
78
81
|
setStatus("done");
|
|
82
|
+
setPhase(null);
|
|
79
83
|
return result;
|
|
80
84
|
} catch (err) {
|
|
81
85
|
const e = err instanceof ConnectError ? err : new ConnectError("sign_in_failed", String(err));
|
|
82
86
|
setError(e);
|
|
83
87
|
setStatus("error");
|
|
88
|
+
setPhase(null);
|
|
84
89
|
throw e;
|
|
85
90
|
}
|
|
86
91
|
}, [apiBase]);
|
|
@@ -100,6 +105,7 @@ function useSignInWithDexter(config = {}) {
|
|
|
100
105
|
}, [refreshBalance]);
|
|
101
106
|
return {
|
|
102
107
|
status,
|
|
108
|
+
phase,
|
|
103
109
|
isVaultConnected: status === "done" && vault !== null,
|
|
104
110
|
signIn,
|
|
105
111
|
disconnect,
|
|
@@ -263,6 +269,7 @@ function SignInWithDexter(props) {
|
|
|
263
269
|
DexterButton,
|
|
264
270
|
{
|
|
265
271
|
loading: c.status === "pending",
|
|
272
|
+
loadingLabel: c.phase ? ceremonyPhaseLabel(c.phase) : "Connecting\u2026",
|
|
266
273
|
variant,
|
|
267
274
|
block,
|
|
268
275
|
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
|
|
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 };
|