@dexterai/connect 0.23.1 → 0.24.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-XTYNX5LX.js → chunk-KUAVEFWT.js} +9 -5
- package/dist/index.js +1 -1
- package/dist/react.js +167 -2
- package/package.json +1 -1
- package/dist/index.d.ts +0 -226
- package/dist/react.d.ts +0 -243
- package/dist/server.d.ts +0 -72
- package/dist/signals-CQ5AEzXY.d.ts +0 -285
- package/dist/worldid.d.ts +0 -61
|
@@ -252,7 +252,7 @@ async function createWallet(config = {}) {
|
|
|
252
252
|
name: config.name,
|
|
253
253
|
apiBase: config.apiBase
|
|
254
254
|
});
|
|
255
|
-
setActiveHandle(result.handle, config.name, result.credentialId);
|
|
255
|
+
setActiveHandle(result.handle, result.label ?? config.name, result.credentialId);
|
|
256
256
|
return result;
|
|
257
257
|
}
|
|
258
258
|
if (typeof navigator === "undefined" || !navigator.credentials) {
|
|
@@ -282,7 +282,8 @@ async function createWallet(config = {}) {
|
|
|
282
282
|
apiBase,
|
|
283
283
|
enrolled.userHandle,
|
|
284
284
|
enrolled.credentialId,
|
|
285
|
-
config.spendPolicy
|
|
285
|
+
config.spendPolicy,
|
|
286
|
+
config.name?.trim() || void 0
|
|
286
287
|
);
|
|
287
288
|
setActiveHandle(enrolled.userHandle, name, enrolled.credentialId);
|
|
288
289
|
return {
|
|
@@ -298,8 +299,10 @@ async function createWallet(config = {}) {
|
|
|
298
299
|
// swig not deployed yet (counterfactual pattern)
|
|
299
300
|
publicKey: enrolled.publicKey,
|
|
300
301
|
userHandle: enrolled.userHandle,
|
|
301
|
-
credentialId: enrolled.credentialId
|
|
302
|
-
|
|
302
|
+
credentialId: enrolled.credentialId,
|
|
303
|
+
walletLabel: init.walletLabel ?? config.name?.trim() ?? null
|
|
304
|
+
},
|
|
305
|
+
label: init.walletLabel ?? config.name?.trim() ?? null
|
|
303
306
|
};
|
|
304
307
|
}
|
|
305
308
|
async function fetchEnrollChallenge(apiBase) {
|
|
@@ -324,8 +327,9 @@ async function submitEnrollComplete(apiBase, response) {
|
|
|
324
327
|
if (!res.ok) throw new ConnectError(await readErrorCode(res), `enroll/complete ${res.status}`);
|
|
325
328
|
return await res.json();
|
|
326
329
|
}
|
|
327
|
-
async function initializeVault(apiBase, userHandle, credentialId, spendPolicy) {
|
|
330
|
+
async function initializeVault(apiBase, userHandle, credentialId, spendPolicy, label) {
|
|
328
331
|
const body = { userHandle, credentialId, coolingOffSeconds: 0 };
|
|
332
|
+
if (label) body.label = label;
|
|
329
333
|
if (spendPolicy) {
|
|
330
334
|
body.spendLimitAtomic = spendPolicy.spendLimitAtomic;
|
|
331
335
|
body.sessionTtlSeconds = SESSION_TTL_30D;
|
package/dist/index.js
CHANGED
package/dist/react.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
setActiveHandle,
|
|
18
18
|
subscribe,
|
|
19
19
|
switchWallet
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-KUAVEFWT.js";
|
|
21
21
|
import {
|
|
22
22
|
DexterButton,
|
|
23
23
|
DexterMark,
|
|
@@ -637,15 +637,180 @@ function CreateWalletPanel(props) {
|
|
|
637
637
|
)
|
|
638
638
|
] });
|
|
639
639
|
}
|
|
640
|
+
|
|
641
|
+
// src/AppInstallButtons.tsx
|
|
642
|
+
import { useEffect as useEffect8, useRef, useState as useState6 } from "react";
|
|
643
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
644
|
+
var STYLE_ID3 = "dexter-connect-appinstall-styles";
|
|
645
|
+
var APPINSTALL_CSS = `
|
|
646
|
+
.dx-appinstall{ display:flex; flex-wrap:wrap; gap:10px; }
|
|
647
|
+
.dx-appinstall--block{ flex-direction:column; }
|
|
648
|
+
.dx-appbtn{
|
|
649
|
+
display:inline-flex; align-items:center; gap:10px;
|
|
650
|
+
padding:10px 16px; border:1px solid var(--dx-appbtn-border, rgba(255,255,255,.14));
|
|
651
|
+
border-radius:var(--dx-radius,0px);
|
|
652
|
+
background:var(--dx-appbtn-bg, rgba(8,8,8,.55));
|
|
653
|
+
color:var(--dx-appbtn-fg, #f4ece0); font:inherit; font-weight:600; font-size:.84rem;
|
|
654
|
+
cursor:pointer; text-decoration:none; -webkit-tap-highlight-color:transparent;
|
|
655
|
+
transition:border-color .16s ease, background .16s ease, transform .16s ease;
|
|
656
|
+
}
|
|
657
|
+
.dx-appbtn:hover{ border-color:color-mix(in srgb,var(--dx-ember,#f26c18) 55%,transparent); transform:translateY(-1px); }
|
|
658
|
+
.dx-appbtn:active{ transform:translateY(0); }
|
|
659
|
+
.dx-appbtn:focus-visible{ outline:none; box-shadow:0 0 0 3px color-mix(in srgb,var(--dx-ember,#f26c18) 38%,transparent); }
|
|
660
|
+
.dx-appbtn--block{ width:100%; justify-content:flex-start; }
|
|
661
|
+
.dx-appbtn__logo{ width:18px; height:18px; display:block; flex:none; }
|
|
662
|
+
.dx-appbtn__copied{ color:var(--dx-ember,#f26c18); }
|
|
663
|
+
`;
|
|
664
|
+
function ensureAppInstallStyles() {
|
|
665
|
+
if (typeof document === "undefined") return;
|
|
666
|
+
if (document.getElementById(STYLE_ID3)) return;
|
|
667
|
+
const el = document.createElement("style");
|
|
668
|
+
el.id = STYLE_ID3;
|
|
669
|
+
el.textContent = APPINSTALL_CSS;
|
|
670
|
+
document.head.appendChild(el);
|
|
671
|
+
}
|
|
672
|
+
var CURSOR_MARK = "data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHdpZHRoPSI1MTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTUxMiAzMjUuNWMwIDcuMTI0IDAgMTQuMjQtLjA0MSAyMS4zNjQtLjAzNCA1Ljk5OS0uMTAzIDExLjk5OC0uMjY4IDE3Ljk5LS4zNTYgMTMuMDY4LTEuMTI0IDI2LjI0NS0zLjQ0OCAzOS4xNjktMi4zNTkgMTMuMTA5LTYuMjA1IDI1LjMwNi0xMi4yNjYgMzcuMjIyLTUuOTU4IDExLjcwMy0xMy43NDYgMjIuNDE5LTIzLjAyOSAzMS43MDktOS4yOSA5LjI5LTIwIDE3LjA3Mi0zMS43MSAyMy4wMy0xMS45MDkgNi4wNjEtMjQuMTEzIDkuOTA3LTM3LjIyMiAxMi4yNjYtMTIuOTIzIDIuMzI0LTI2LjEwMSAzLjA5Mi0zOS4xNjkgMy40NDgtNS45OTkuMTY1LTExLjk5MS4yMzMtMTcuOTkuMjY4LTcuMTIzLjA0OC0xNC4yNC4wNDEtMjEuMzY0LjA0MWgtMTM5Yy03LjEyNCAwLTE0LjI0IDAtMjEuMzY0LS4wNDEtNS45OTktLjAzNS0xMS45OTgtLjEwMy0xNy45OS0uMjY4LTEzLjA2OC0uMzU2LTI2LjI0NS0xLjEyNC0zOS4xNjktMy40NDgtMTMuMTA5LTIuMzU5LTI1LjMwNi02LjIwNS0zNy4yMjE5LTEyLjI2Ni0xMS43MDMzLTUuOTU4LTIyLjQxOTQtMTMuNzQ2LTMxLjcwOTUtMjMuMDMtOS4yOS05LjI5LTE3LjA3MTctMTkuOTk5LTIzLjAyOTYtMzEuNzA5LTYuMDYwOC0xMS45MDktOS45MDcwNy0yNC4xMTMtMTIuMjY1NTctMzcuMjIyLTIuMzI0MjItMTIuOTI0LTMuMDkyMS0yNi4xMDEtMy40NDg2MTgtMzkuMTY5LS4xNjQ1NDYtNS45OTktLjIzMzEwNzEtMTEuOTkxLS4yNjczODc2LTE3Ljk5LS4wMjc0MjQ0LTcuMTI0LS4wMjc0MjQ0LTE0LjI0LS4wMjc0MjQ0LTIxLjM2NHYtMTM5YzAtNy4xMjQgMC0xNC4yNC4wNDExMzY2LTIxLjM2NC4wMzQyODA1LTUuOTk5LjEwMjg0MTQtMTEuOTk4LjI2NzM4ODQtMTcuOTkuMzU2NTE3LTEzLjA2OCAxLjEyNDQwNS0yNi4yNDUgMy40NDg2MTUtMzkuMTY5IDIuMzU4NS0xMy4xMDkxIDYuMjA0NzgtMjUuMzA2MSAxMi4yNjU1Ni0zNy4yMjIgNS45NTgtMTEuNzAzNCAxMy43NDY1LTIyLjQxOTUgMjMuMDI5Ny0zMS43MDk1IDkuMjktOS4yOSAxOS45OTkyLTE3LjA3MTcgMzEuNzA5NC0yMy4wMjk2IDExLjkwOTEtNi4wNjA4NCAyNC4xMTI5LTkuOTA3MTEgMzcuMjIyMi0xMi4yNjU2MSAxMi45MjMtMi4zMjQyMiAyNi4xMDEtMy4wOTIxMDQgMzkuMTY5LTMuNDQ4NjIyIDUuOTk5LS4xNjQ1NDYgMTEuOTkxLS4yMzMxMDcgMTcuOTktLjI2NzM4NzUgNy4xMTctLjAzNDI4MDUgMTQuMjMzLS4wMzQyODA1IDIxLjM1Ny0uMDM0MjgwNWgxMzljNy4xMjQgMCAxNC4yNCAwIDIxLjM2NC4wNDExMzY2IDUuOTk5LjAzNDI4MDUgMTEuOTk4LjEwMjg0MTQgMTcuOTkuMjY3Mzg4NCAxMy4wNjguMzU2NTE3IDI2LjI0NSAxLjEyNDQwNSAzOS4xNjkgMy40NDg2MTUgMTMuMTA5IDIuMzU4NSAyNS4zMDYgNi4yMDQ3OCAzNy4yMjIgMTIuMjY1NTYgMTEuNzAzIDUuOTU4IDIyLjQxOSAxMy43NDY1IDMxLjcwOSAyMy4wMjk3IDkuMjkgOS4yOSAxNy4wNzIgMTkuOTk5MiAyMy4wMyAzMS43MDk0IDYuMDYxIDExLjkwOTEgOS45MDcgMjQuMTEyOSAxMi4yNjYgMzcuMjIyMiAyLjMyNCAxMi45MjMgMy4wOTIgMjYuMTAxIDMuNDQ4IDM5LjE2OS4xNjUgNS45OTkuMjMzIDExLjk5MS4yNjggMTcuOTkuMDQ4IDcuMTIzLjA0MSAxNC4yNC4wNDEgMjEuMzY0djEzOXoiIGZpbGw9IiMxNDEyMGIiLz48cGF0aCBkPSJtMTg2LjUgNGgxMzljNy4xMjUgMCAxNC4yMzEtLjAwMDA0IDIxLjM0MS4wNDEwMiA1Ljk4NS4wMzQyIDExLjk1Mi4xMDIyMSAxNy45MDMuMjY1NjJoLjAwMWMxMy4wMDMuMzU0NzUgMjUuOTQzIDEuMTE3MDkgMzguNTY5IDMuMzg3NyAxMi43NzUgMi4yOTgyNyAyNC41OTIgNi4wMzE0NiAzNi4xMTggMTEuODkzNTZ2LS4wMDFjMTAuOTc0IDUuNTg2NyAyMS4wNTIgMTIuODM4NCAyOS44NDggMjEuNDU3bC44NDcuODM3OWM4Ljk5MyA4Ljk5MyAxNi41MjUgMTkuMzU5NCAyMi4yOTIgMzAuNjkzNHYuMDAxYzUuNjc4IDExLjE1NzUgOS4zNiAyMi42MDIzIDExLjY3NCAzNC45MjA4bC4yMTkgMS4xOTVjMi4xMjkgMTEuODM3IDIuOTMyIDIzLjk1IDMuMzE2IDM2LjEzMmwuMDcyIDIuNDM4Yy4xNjQgNS45NTguMjMyIDExLjkxOS4yNjYgMTcuOTA0di4wMDRjLjA0OCA3LjEwNy4wNDEgMTQuMjA3LjA0MSAyMS4zMzd2MTI5LjM0NGwtLjAwNy0uMDA3djkuNjU2YzAgNy4xMjUgMCAxNC4yMzEtLjA0MSAyMS4zNDEtLjAzNCA1Ljk4NS0uMTAyIDExLjk1Mi0uMjY2IDE3LjkwM3YuMDAxYy0uMzU0IDEzLjAwMy0xLjExNyAyNS45NDMtMy4zODcgMzguNTY5LTIuMjI3IDEyLjM3Ni01LjggMjMuODUzLTExLjM1MSAzNS4wMzdsLS41NDMgMS4wOGMtNS43NjYgMTEuMzI3LTEzLjMwNiAyMS43MDEtMjIuMjkzIDMwLjY5NS04Ljk5MyA4Ljk5My0xOS4zNjEgMTYuNTI2LTMwLjY5NSAyMi4yOTMtMTEuNTE4IDUuODYxLTIzLjM0MiA5LjU5NS0zNi4xMTYgMTEuODkzLTExLjgzNyAyLjEyOS0yMy45NSAyLjkzMi0zNi4xMzIgMy4zMTZsLTIuNDM4LjA3MmMtNS45NTguMTY0LTExLjkxOS4yMzItMTcuOTA0LjI2NmgtLjAwNGMtNy4xMDcuMDQ4LTE0LjIwNy4wNDEtMjEuMzM3LjA0MWgtMTM5Yy03LjEyNSAwLTE0LjIzMSAwLTIxLjM0MS0uMDQxLTUuOTg1LS4wMzQtMTEuOTUyLS4xMDItMTcuOTAzLS4yNjZoLS4wMDFjLTEzLjAwMy0uMzU1LTI1Ljk0NC0xLjExNy0zOC41Ny0zLjM4OC0xMi43NzQyLTIuMjk4LTI0LjU5MTQtNi4wMzEtMzYuMTE2NS0xMS44OTNoLjAwMWMtMTAuOTc0LTUuNTg3LTIxLjA1MzQtMTIuODM3LTI5Ljg0OTYtMjEuNDU2bC0uODQ2Ny0uODM4Yy04LjcxMTgtOC43MTItMTYuMDUzMS0xOC43MTMtMjEuNzQ2MS0yOS42MzRsLS41NDU5LTEuMDYtLjU0MzktMS4wODFjLTUuMzcxLTEwLjgxNi04Ljg5MDUtMjEuOTE5LTExLjEyOTkxLTMzLjg0bC0uMjE5NzMtMS4xOTZjLTIuMjcwNjEtMTIuNjI2LTMuMDMyOTQtMjUuNTY2LTMuMzg3NjktMzguNTY5di0uMDAxYy0uMTYzNDEtNS45NTgtLjIzMTQyLTExLjkxOC0uMjY1NjMtMTcuOTAzLS4wMjczNi03LjExMi0uMDI3MzQtMTQuMjE5LS4wMjczNC0yMS4zNDF2LTEzOWMwLTcuMTI1LS4wMDAwNC0xNC4yMzEuMDQxMDItMjEuMzQxLjAzNDItNS45ODUuMTAyMjEtMTEuOTUyLjI2NTYyLTE3LjkwM3YtLjAwMWMuMzU0NzYtMTMuMDAzIDEuMTE3LTI1Ljk0NCAzLjM4NzctMzguNTcgMi4yOTgyOC0xMi43NzQ0IDYuMDMxNTYtMjQuNTkxNiAxMS44OTM1Ni0zNi4xMTY2bC0uMDAxLS4wMDFjNS43NjY2LTExLjMyNyAxMy4zMDczLTIxLjY5OTkgMjIuMjk0LTMwLjY5MzQgOC45OTMzLTguOTkzMyAxOS4zNjA3LTE2LjUyNjEgMzAuNjk1My0yMi4yOTI5IDExLjUxNzMtNS44NjE1IDIzLjM0MDYtOS41OTYxOSAzNi4xMTQ4LTExLjg5NDU4IDExLjgzNy0yLjEyODc3IDIzLjk1MS0yLjkzMDE2IDM2LjEzMy0zLjMxNDQ1bDIuNDM4LS4wNzIyN2M1Ljk1OC0uMTYzNDIgMTEuOTE5LS4yMzE0MiAxNy45MDQtLjI2NTYybC0uMDAxLS4wMDA5OGM3LjEwNC0uMDM0MjEgMTQuMjExLS4wMzMyIDIxLjMzNS0uMDMzMnoiIHN0cm9rZT0iI2VkZWNlYyIgc3Ryb2tlLW9wYWNpdHk9Ii4yIiBzdHJva2Utd2lkdGg9IjgiLz48cGF0aCBkPSJtNDE1LjAzNSAxNTYuMzUtMTUxLjUwMy04Ny40Njk1Yy00Ljg2NS0yLjgwOTQtMTAuODY4LTIuODA5NC0xNS43MzMgMGwtMTUxLjQ5NjkgODcuNDY5NWMtNC4wODk3IDIuMzYyLTYuNjE0NiA2LjcyOS02LjYxNDYgMTEuNDU5djE3Ni4zODNjMCA0LjczIDIuNTI0OSA5LjA5NyA2LjYxNDYgMTEuNDU4bDE1MS41MDM5IDg3LjQ3YzQuODY1IDIuODA5IDEwLjg2OCAyLjgwOSAxNS43MzMgMGwxNTEuNTA0LTg3LjQ3YzQuMDg5LTIuMzYxIDYuNjE0LTYuNzI4IDYuNjE0LTExLjQ1OHYtMTc2LjM4M2MwLTQuNzMtMi41MjUtOS4wOTctNi42MTQtMTEuNDU5em0tOS41MTYgMTguNTI4LTE0Ni4yNTUgMjUzLjMyYy0uOTg4IDEuNzA3LTMuNTk5IDEuMDEtMy41OTktLjk2N3YtMTY1Ljg3MmMwLTMuMzE0LTEuNzcxLTYuMzc5LTQuNjQ0LTguMDQ0bC0xNDMuNjQ1LTgyLjkzMmMtMS43MDctLjk4OC0xLjAxLTMuNTk5Ljk2OC0zLjU5OWgyOTIuNTA5YzQuMTU0IDAgNi43NSA0LjUwMyA0LjY3MyA4LjEwMWgtLjAwN3oiIGZpbGw9IiNlZGVjZWMiLz48L3N2Zz4=";
|
|
673
|
+
var VSCODE_MARK = "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPG1hc2sgaWQ9Im1hc2swIiBtYXNrLXR5cGU9ImFscGhhIiBtYXNrVW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNzAuOTExOSA5OS4zMTcxQzcyLjQ4NjkgOTkuOTMwNyA3NC4yODI4IDk5Ljg5MTQgNzUuODcyNSA5OS4xMjY0TDk2LjQ2MDggODkuMjE5N0M5OC42MjQyIDg4LjE3ODcgMTAwIDg1Ljk4OTIgMTAwIDgzLjU4NzJWMTYuNDEzM0MxMDAgMTQuMDExMyA5OC42MjQzIDExLjgyMTggOTYuNDYwOSAxMC43ODA4TDc1Ljg3MjUgMC44NzM3NTZDNzMuNzg2MiAtMC4xMzAxMjkgNzEuMzQ0NiAwLjExNTc2IDY5LjUxMzUgMS40NDY5NUM2OS4yNTIgMS42MzcxMSA2OS4wMDI4IDEuODQ5NDMgNjguNzY5IDIuMDgzNDFMMjkuMzU1MSAzOC4wNDE1TDEyLjE4NzIgMjUuMDA5NkMxMC41ODkgMjMuNzk2NSA4LjM1MzYzIDIzLjg5NTkgNi44NjkzMyAyNS4yNDYxTDEuMzYzMDMgMzAuMjU0OUMtMC40NTI1NTIgMzEuOTA2NCAtMC40NTQ2MzMgMzQuNzYyNyAxLjM1ODUzIDM2LjQxN0wxNi4yNDcxIDUwLjAwMDFMMS4zNTg1MyA2My41ODMyQy0wLjQ1NDYzMyA2NS4yMzc0IC0wLjQ1MjU1MiA2OC4wOTM4IDEuMzYzMDMgNjkuNzQ1M0w2Ljg2OTMzIDc0Ljc1NDFDOC4zNTM2MyA3Ni4xMDQzIDEwLjU4OSA3Ni4yMDM3IDEyLjE4NzIgNzQuOTkwNUwyOS4zNTUxIDYxLjk1ODdMNjguNzY5IDk3LjkxNjdDNjkuMzkyNSA5OC41NDA2IDcwLjEyNDYgOTkuMDEwNCA3MC45MTE5IDk5LjMxNzFaTTc1LjAxNTIgMjcuMjk4OUw0NS4xMDkxIDUwLjAwMDFMNzUuMDE1MiA3Mi43MDEyVjI3LjI5ODlaIiBmaWxsPSJ3aGl0ZSIvPgo8L21hc2s+CjxnIG1hc2s9InVybCgjbWFzazApIj4KPHBhdGggZD0iTTk2LjQ2MTQgMTAuNzk2Mkw3NS44NTY5IDAuODc1NTQyQzczLjQ3MTkgLTAuMjcyNzczIDcwLjYyMTcgMC4yMTE2MTEgNjguNzUgMi4wODMzM0wxLjI5ODU4IDYzLjU4MzJDLTAuNTE1NjkzIDY1LjIzNzMgLTAuNTEzNjA3IDY4LjA5MzcgMS4zMDMwOCA2OS43NDUyTDYuODEyNzIgNzQuNzU0QzguMjk3OTMgNzYuMTA0MiAxMC41MzQ3IDc2LjIwMzYgMTIuMTMzOCA3NC45OTA1TDkzLjM2MDkgMTMuMzY5OUM5Ni4wODYgMTEuMzAyNiAxMDAgMTMuMjQ2MiAxMDAgMTYuNjY2N1YxNi40Mjc1QzEwMCAxNC4wMjY1IDk4LjYyNDYgMTEuODM3OCA5Ni40NjE0IDEwLjc5NjJaIiBmaWxsPSIjMDA2NUE5Ii8+CjxnIGZpbHRlcj0idXJsKCNmaWx0ZXIwX2QpIj4KPHBhdGggZD0iTTk2LjQ2MTQgODkuMjAzOEw3NS44NTY5IDk5LjEyNDVDNzMuNDcxOSAxMDAuMjczIDcwLjYyMTcgOTkuNzg4NCA2OC43NSA5Ny45MTY3TDEuMjk4NTggMzYuNDE2OUMtMC41MTU2OTMgMzQuNzYyNyAtMC41MTM2MDcgMzEuOTA2MyAxLjMwMzA4IDMwLjI1NDhMNi44MTI3MiAyNS4yNDZDOC4yOTc5MyAyMy44OTU4IDEwLjUzNDcgMjMuNzk2NCAxMi4xMzM4IDI1LjAwOTVMOTMuMzYwOSA4Ni42MzAxQzk2LjA4NiA4OC42OTc0IDEwMCA4Ni43NTM4IDEwMCA4My4zMzM0VjgzLjU3MjZDMTAwIDg1Ljk3MzUgOTguNjI0NiA4OC4xNjIyIDk2LjQ2MTQgODkuMjAzOFoiIGZpbGw9IiMwMDdBQ0MiLz4KPC9nPgo8ZyBmaWx0ZXI9InVybCgjZmlsdGVyMV9kKSI+CjxwYXRoIGQ9Ik03NS44NTc4IDk5LjEyNjNDNzMuNDcyMSAxMDAuMjc0IDcwLjYyMTkgOTkuNzg4NSA2OC43NSA5Ny45MTY2QzcxLjA1NjQgMTAwLjIyMyA3NSA5OC41ODk1IDc1IDk1LjMyNzhWNC42NzIxM0M3NSAxLjQxMDM5IDcxLjA1NjQgLTAuMjIzMTA2IDY4Ljc1IDIuMDgzMjlDNzAuNjIxOSAwLjIxMTQwMiA3My40NzIxIC0wLjI3MzY2NiA3NS44NTc4IDAuODczNjMzTDk2LjQ1ODcgMTAuNzgwN0M5OC42MjM0IDExLjgyMTcgMTAwIDE0LjAxMTIgMTAwIDE2LjQxMzJWODMuNTg3MUMxMDAgODUuOTg5MSA5OC42MjM0IDg4LjE3ODYgOTYuNDU4NiA4OS4yMTk2TDc1Ljg1NzggOTkuMTI2M1oiIGZpbGw9IiMxRjlDRjAiLz4KPC9nPgo8ZyBzdHlsZT0ibWl4LWJsZW5kLW1vZGU6b3ZlcmxheSIgb3BhY2l0eT0iMC4yNSI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNzAuODUxMSA5OS4zMTcxQzcyLjQyNjEgOTkuOTMwNiA3NC4yMjIxIDk5Ljg5MTMgNzUuODExNyA5OS4xMjY0TDk2LjQgODkuMjE5N0M5OC41NjM0IDg4LjE3ODcgOTkuOTM5MiA4NS45ODkyIDk5LjkzOTIgODMuNTg3MVYxNi40MTMzQzk5LjkzOTIgMTQuMDExMiA5OC41NjM1IDExLjgyMTcgOTYuNDAwMSAxMC43ODA3TDc1LjgxMTcgMC44NzM2OTVDNzMuNzI1NSAtMC4xMzAxOSA3MS4yODM4IDAuMTE1Njk5IDY5LjQ1MjcgMS40NDY4OEM2OS4xOTEyIDEuNjM3MDUgNjguOTQyIDEuODQ5MzcgNjguNzA4MiAyLjA4MzM1TDI5LjI5NDMgMzguMDQxNEwxMi4xMjY0IDI1LjAwOTZDMTAuNTI4MyAyMy43OTY0IDguMjkyODUgMjMuODk1OSA2LjgwODU1IDI1LjI0NkwxLjMwMjI1IDMwLjI1NDhDLTAuNTEzMzM0IDMxLjkwNjQgLTAuNTE1NDE1IDM0Ljc2MjcgMS4yOTc3NSAzNi40MTY5TDE2LjE4NjMgNTBMMS4yOTc3NSA2My41ODMyQy0wLjUxNTQxNSA2NS4yMzc0IC0wLjUxMzMzNCA2OC4wOTM3IDEuMzAyMjUgNjkuNzQ1Mkw2LjgwODU1IDc0Ljc1NEM4LjI5Mjg1IDc2LjEwNDIgMTAuNTI4MyA3Ni4yMDM2IDEyLjEyNjQgNzQuOTkwNUwyOS4yOTQzIDYxLjk1ODZMNjguNzA4MiA5Ny45MTY3QzY5LjMzMTcgOTguNTQwNSA3MC4wNjM4IDk5LjAxMDQgNzAuODUxMSA5OS4zMTcxWk03NC45NTQ0IDI3LjI5ODlMNDUuMDQ4MyA1MEw3NC45NTQ0IDcyLjcwMTJWMjcuMjk4OVoiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcikiLz4KPC9nPgo8L2c+CjxkZWZzPgo8ZmlsdGVyIGlkPSJmaWx0ZXIwX2QiIHg9Ii04LjM5NDExIiB5PSIxNS44MjkxIiB3aWR0aD0iMTE2LjcyNyIgaGVpZ2h0PSI5Mi4yNDU2IiBmaWx0ZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIGNvbG9yLWludGVycG9sYXRpb24tZmlsdGVycz0ic1JHQiI+CjxmZUZsb29kIGZsb29kLW9wYWNpdHk9IjAiIHJlc3VsdD0iQmFja2dyb3VuZEltYWdlRml4Ii8+CjxmZUNvbG9yTWF0cml4IGluPSJTb3VyY2VBbHBoYSIgdHlwZT0ibWF0cml4IiB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDEyNyAwIi8+CjxmZU9mZnNldC8+CjxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjQuMTY2NjciLz4KPGZlQ29sb3JNYXRyaXggdHlwZT0ibWF0cml4IiB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuMjUgMCIvPgo8ZmVCbGVuZCBtb2RlPSJvdmVybGF5IiBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJlZmZlY3QxX2Ryb3BTaGFkb3ciLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJlZmZlY3QxX2Ryb3BTaGFkb3ciIHJlc3VsdD0ic2hhcGUiLz4KPC9maWx0ZXI+CjxmaWx0ZXIgaWQ9ImZpbHRlcjFfZCIgeD0iNjAuNDE2NyIgeT0iLTguMDc1NTgiIHdpZHRoPSI0Ny45MTY3IiBoZWlnaHQ9IjExNi4xNTEiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQ29sb3JNYXRyaXggaW49IlNvdXJjZUFscGhhIiB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMTI3IDAiLz4KPGZlT2Zmc2V0Lz4KPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iNC4xNjY2NyIvPgo8ZmVDb2xvck1hdHJpeCB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC4yNSAwIi8+CjxmZUJsZW5kIG1vZGU9Im92ZXJsYXkiIGluMj0iQmFja2dyb3VuZEltYWdlRml4IiByZXN1bHQ9ImVmZmVjdDFfZHJvcFNoYWRvdyIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDFfZHJvcFNoYWRvdyIgcmVzdWx0PSJzaGFwZSIvPgo8L2ZpbHRlcj4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyIiB4MT0iNDkuOTM5MiIgeTE9IjAuMjU3ODEyIiB4Mj0iNDkuOTM5MiIgeTI9Ijk5Ljc0MjMiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0id2hpdGUiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSJ3aGl0ZSIgc3RvcC1vcGFjaXR5PSIwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg==";
|
|
674
|
+
var HERMES_MARK = "data:image/png;base64,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";
|
|
675
|
+
var CLAUDE_MARK = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBjbGFzcz0idy1mdWxsIiBmaWxsPSJoc2woMTQuOCwgNjMuMSUsIDU5LjYlKSI+PHBhdGggZD0ibTE5LjYgNjYuNSAxOS43LTExIC4zLTEtLjMtLjVoLTFsLTMuMy0uMi0xMS4yLS4zTDE0IDUzbC05LjUtLjUtMi40LS41TDAgNDlsLjItMS41IDItMS4zIDIuOS4yIDYuMy41IDkuNS42IDYuOS40TDM4IDQ5LjFoMS42bC4yLS43LS41LS40LS40LS40TDI5IDQxbC0xMC42LTctNS42LTQuMS0zLTItMS41LTItLjYtNC4yIDIuNy0zIDMuNy4zLjkuMiAzLjcgMi45IDggNi4xTDM3IDM2bDEuNSAxLjIuNi0uNC4xLS4zLS43LTEuMUwzMyAyNWwtNi0xMC40LTIuNy00LjMtLjctMi42Yy0uMy0xLS40LTItLjQtM2wzLTQuMkwyOCAwbDQuMi42TDMzLjggMmwyLjYgNiA0LjEgOS4zTDQ3IDI5LjlsMiAzLjggMSAzLjQuMyAxaC43di0uNWwuNS03LjIgMS04LjcgMS0xMS4yLjMtMy4yIDEuNi0zLjggMy0yTDYxIDIuNmwyIDIuOS0uMyAxLjgtMS4xIDcuN0w1OSAyNy4xbC0xLjUgOC4yaC45bDEtMS4xIDQuMS01LjQgNi45LTguNiAzLTMuNUw3NyAxM2wyLjMtMS44aDQuM2wzLjEgNC43LTEuNCA0LjktNC40IDUuNi0zLjcgNC43LTUuMyA3LjEtMy4yIDUuNy4zLjRoLjdsMTItMi42IDYuNC0xLjEgNy42LTEuMyAzLjUgMS42LjQgMS42LTEuNCAzLjQtOC4yIDItOS42IDItMTQuMyAzLjMtLjIuMS4yLjMgNi40LjYgMi44LjJoNi44bDEyLjYgMSAzLjMgMiAxLjkgMi43LS4zIDItNS4xIDIuNi02LjgtMS42LTE2LTMuOC01LjQtMS4zaC0uOHYuNGw0LjYgNC41IDguMyA3LjVMODkgODAuMWwuNSAyLjQtMS4zIDItMS40LS4yLTkuMi03LTMuNi0zLTgtNi44aC0uNXYuN2wxLjggMi43IDkuOCAxNC43LjUgNC41LS43IDEuNC0yLjYgMS0yLjctLjYtNS44LTgtNi05LTQuNy04LjItLjUuNC0yLjkgMzAuMi0xLjMgMS41LTMgMS4yLTIuNS0yLTEuNC0zIDEuNC02LjIgMS42LTggMS4zLTYuNCAxLjItNy45LjctMi42di0uMkg0OUw0MyA3MmwtOSAxMi4zLTcuMiA3LjYtMS43LjctMy0xLjUuMy0yLjhMMjQgODZsMTAtMTIuOCA2LTcuOSA0LTQuNi0uMS0uNWgtLjNMMTcuMiA3Ny40bC00LjcuNi0yLTIgLjItMyAxLTEgOC01LjVaIj48L3BhdGg+PC9zdmc+";
|
|
676
|
+
var DEFAULT_MCP_URL = "https://open.dexter.cash/mcp";
|
|
677
|
+
var DEFAULT_NAME = "opendexter";
|
|
678
|
+
var ALL_APPS = ["cursor", "vscode", "hermes", "claude-code"];
|
|
679
|
+
function cursorInstallUrl(name, mcpUrl) {
|
|
680
|
+
const config = typeof btoa === "function" ? btoa(JSON.stringify({ url: mcpUrl })) : Buffer.from(JSON.stringify({ url: mcpUrl })).toString("base64");
|
|
681
|
+
return `cursor://anysphere.cursor-deeplink/mcp/install?name=${encodeURIComponent(name)}&config=${encodeURIComponent(config)}`;
|
|
682
|
+
}
|
|
683
|
+
function vscodeInstallUrl(name, mcpUrl) {
|
|
684
|
+
return `vscode:mcp/install?${encodeURIComponent(JSON.stringify({ name, type: "http", url: mcpUrl }))}`;
|
|
685
|
+
}
|
|
686
|
+
function hermesInstallCommand(name, mcpUrl) {
|
|
687
|
+
return `hermes mcp add ${name} --url ${mcpUrl} --auth oauth`;
|
|
688
|
+
}
|
|
689
|
+
function claudeCodeInstallCommand(name, mcpUrl) {
|
|
690
|
+
return `claude mcp add --transport http ${name} ${mcpUrl}`;
|
|
691
|
+
}
|
|
692
|
+
async function copyText(text) {
|
|
693
|
+
try {
|
|
694
|
+
await navigator.clipboard.writeText(text);
|
|
695
|
+
return true;
|
|
696
|
+
} catch {
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
function useCopied() {
|
|
701
|
+
const [copied, setCopied] = useState6(false);
|
|
702
|
+
const timer = useRef(null);
|
|
703
|
+
useEffect8(
|
|
704
|
+
() => () => {
|
|
705
|
+
if (timer.current) clearTimeout(timer.current);
|
|
706
|
+
},
|
|
707
|
+
[]
|
|
708
|
+
);
|
|
709
|
+
return [
|
|
710
|
+
copied,
|
|
711
|
+
() => {
|
|
712
|
+
setCopied(true);
|
|
713
|
+
if (timer.current) clearTimeout(timer.current);
|
|
714
|
+
timer.current = setTimeout(() => setCopied(false), 2600);
|
|
715
|
+
}
|
|
716
|
+
];
|
|
717
|
+
}
|
|
718
|
+
function appCx(block) {
|
|
719
|
+
return block ? "dx-appbtn dx-appbtn--block" : "dx-appbtn";
|
|
720
|
+
}
|
|
721
|
+
function AppInstallButtons(props) {
|
|
722
|
+
const {
|
|
723
|
+
mcpUrl = DEFAULT_MCP_URL,
|
|
724
|
+
serverName = DEFAULT_NAME,
|
|
725
|
+
apps = ALL_APPS,
|
|
726
|
+
block = false,
|
|
727
|
+
className,
|
|
728
|
+
onAction
|
|
729
|
+
} = props;
|
|
730
|
+
useEffect8(ensureAppInstallStyles, []);
|
|
731
|
+
const [hermesCopied, markHermes] = useCopied();
|
|
732
|
+
const [claudeCopied, markClaude] = useCopied();
|
|
733
|
+
const buttons = {
|
|
734
|
+
cursor: /* @__PURE__ */ jsxs6(
|
|
735
|
+
"a",
|
|
736
|
+
{
|
|
737
|
+
className: appCx(block),
|
|
738
|
+
href: cursorInstallUrl(serverName, mcpUrl),
|
|
739
|
+
onClick: () => onAction?.("cursor", "deeplink"),
|
|
740
|
+
children: [
|
|
741
|
+
/* @__PURE__ */ jsx6("img", { className: "dx-appbtn__logo", src: CURSOR_MARK, alt: "", "aria-hidden": true }),
|
|
742
|
+
"Add to Cursor"
|
|
743
|
+
]
|
|
744
|
+
},
|
|
745
|
+
"cursor"
|
|
746
|
+
),
|
|
747
|
+
vscode: /* @__PURE__ */ jsxs6(
|
|
748
|
+
"a",
|
|
749
|
+
{
|
|
750
|
+
className: appCx(block),
|
|
751
|
+
href: vscodeInstallUrl(serverName, mcpUrl),
|
|
752
|
+
onClick: () => onAction?.("vscode", "deeplink"),
|
|
753
|
+
children: [
|
|
754
|
+
/* @__PURE__ */ jsx6("img", { className: "dx-appbtn__logo", src: VSCODE_MARK, alt: "", "aria-hidden": true }),
|
|
755
|
+
"Add to VS Code"
|
|
756
|
+
]
|
|
757
|
+
},
|
|
758
|
+
"vscode"
|
|
759
|
+
),
|
|
760
|
+
hermes: /* @__PURE__ */ jsxs6(
|
|
761
|
+
"button",
|
|
762
|
+
{
|
|
763
|
+
type: "button",
|
|
764
|
+
className: appCx(block),
|
|
765
|
+
onClick: async () => {
|
|
766
|
+
if (await copyText(hermesInstallCommand(serverName, mcpUrl))) {
|
|
767
|
+
markHermes();
|
|
768
|
+
onAction?.("hermes", "copied");
|
|
769
|
+
}
|
|
770
|
+
window.location.href = `hermes://open/${encodeURIComponent(serverName)}`;
|
|
771
|
+
},
|
|
772
|
+
children: [
|
|
773
|
+
/* @__PURE__ */ jsx6("img", { className: "dx-appbtn__logo", src: HERMES_MARK, alt: "", "aria-hidden": true }),
|
|
774
|
+
hermesCopied ? /* @__PURE__ */ jsx6("span", { className: "dx-appbtn__copied", children: "Copied. Paste it in Hermes" }) : "Copy for Hermes"
|
|
775
|
+
]
|
|
776
|
+
},
|
|
777
|
+
"hermes"
|
|
778
|
+
),
|
|
779
|
+
"claude-code": /* @__PURE__ */ jsxs6(
|
|
780
|
+
"button",
|
|
781
|
+
{
|
|
782
|
+
type: "button",
|
|
783
|
+
className: appCx(block),
|
|
784
|
+
onClick: async () => {
|
|
785
|
+
if (await copyText(claudeCodeInstallCommand(serverName, mcpUrl))) {
|
|
786
|
+
markClaude();
|
|
787
|
+
onAction?.("claude-code", "copied");
|
|
788
|
+
}
|
|
789
|
+
},
|
|
790
|
+
children: [
|
|
791
|
+
/* @__PURE__ */ jsx6("img", { className: "dx-appbtn__logo", src: CLAUDE_MARK, alt: "", "aria-hidden": true }),
|
|
792
|
+
claudeCopied ? /* @__PURE__ */ jsx6("span", { className: "dx-appbtn__copied", children: "Copied. Run it in your terminal" }) : "Copy for Claude Code"
|
|
793
|
+
]
|
|
794
|
+
},
|
|
795
|
+
"claude-code"
|
|
796
|
+
)
|
|
797
|
+
};
|
|
798
|
+
return /* @__PURE__ */ jsx6("div", { className: ["dx-appinstall", block ? "dx-appinstall--block" : "", className ?? ""].filter(Boolean).join(" "), children: apps.map((app) => buttons[app] ?? null) });
|
|
799
|
+
}
|
|
640
800
|
export {
|
|
641
801
|
AllowanceChips,
|
|
802
|
+
AppInstallButtons,
|
|
642
803
|
CreateWalletPanel,
|
|
643
804
|
DexterButton,
|
|
644
805
|
DexterMark,
|
|
645
806
|
DexterWalletChip,
|
|
646
807
|
DexterWalletMenu,
|
|
647
808
|
SignInWithDexter,
|
|
809
|
+
claudeCodeInstallCommand,
|
|
810
|
+
cursorInstallUrl,
|
|
811
|
+
hermesInstallCommand,
|
|
648
812
|
useDexterWallet,
|
|
649
813
|
useIdentity,
|
|
650
|
-
useSignInWithDexter
|
|
814
|
+
useSignInWithDexter,
|
|
815
|
+
vscodeInstallUrl
|
|
651
816
|
};
|
package/package.json
CHANGED
package/dist/index.d.ts
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
import { S as SignInResult, C as CreateWalletResult, a as CreateWalletConfig, b as CeremonyPhase, D as DexterConnectConfig, c as ConnectVault, R as RecoverWalletConfig, d as RecoverOutcome, I as IdentityKind } from './signals-CQ5AEzXY.js';
|
|
2
|
-
export { A as ACTIVE_WALLET_STORAGE_KEY, e as ConnectError, f as IdentityInput, P as PasskeyLoginTokens, g as PasskeySignalSupport, h as RecoverVault, i as ResolvedIdentity, j as SESSION_TTL_30D, k as SpendPolicy, l as StoredWallet, m as authoredPolicy, n as createWallet, o as ejectActiveWallet, p as forgetWallet, q as getActiveHandle, r as getCredentialId, s as listWallets, t as passkeySignalSupport, u as prunePasskey, v as renamePasskey, w as resolveIdentity, x as setActiveHandle, y as subscribeWallet, z as switchWallet, B as syncAcceptedPasskeys, E as usdToAtomic } from './signals-CQ5AEzXY.js';
|
|
3
|
-
import { DexterApiBrowserPasskeySigner } from '@dexterai/vault/signers/browser';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* "Sign in with Dexter" — the discoverable-credential login ceremony.
|
|
7
|
-
*
|
|
8
|
-
* 1. POST /login-challenge → a server-issued challenge (no allow-list:
|
|
9
|
-
* the resident passkey itself identifies the user)
|
|
10
|
-
* 2. navigator.credentials.get over that challenge (no allowCredentials)
|
|
11
|
-
* 3. POST /passkey-login → the server resolves the credential + vault,
|
|
12
|
-
* verifies the assertion, and returns a Supabase session (+ the vault
|
|
13
|
-
* payload once vault-review ships the dexter-api change — ASK 1)
|
|
14
|
-
*
|
|
15
|
-
* Relays to dexter-api's ANON router — a first-time third-party user has no
|
|
16
|
-
* Supabase session, so the Supabase-gated router would 401.
|
|
17
|
-
*/
|
|
18
|
-
declare function passkeyLogin(config?: DexterConnectConfig, onPhase?: (phase: CeremonyPhase) => void): Promise<SignInResult>;
|
|
19
|
-
type ContinueResult = ({
|
|
20
|
-
kind: 'signin';
|
|
21
|
-
} & SignInResult) | ({
|
|
22
|
-
kind: 'create';
|
|
23
|
-
} & CreateWalletResult);
|
|
24
|
-
declare function continueWithDexter(config?: CreateWalletConfig, onPhase?: (phase: CeremonyPhase) => void): Promise<ContinueResult>;
|
|
25
|
-
|
|
26
|
-
/** What `issueChallenge` returns to the SDK signer. */
|
|
27
|
-
interface AnonChallengeResult {
|
|
28
|
-
/** Server-issued WebAuthn challenge (=== the supplied operationHash). */
|
|
29
|
-
challenge: Uint8Array;
|
|
30
|
-
/** Credential id the server resolved from the userHandle (allowCredentials[0]). */
|
|
31
|
-
credentialId: Uint8Array;
|
|
32
|
-
rpId?: string;
|
|
33
|
-
transports?: AuthenticatorTransport[];
|
|
34
|
-
}
|
|
35
|
-
/** The policy the SDK's guest `DexterApiBrowserPasskeySigner` consumes. */
|
|
36
|
-
interface AnonServerPolicy {
|
|
37
|
-
issueChallenge(args: {
|
|
38
|
-
userHandle: Uint8Array;
|
|
39
|
-
operationHash: Uint8Array;
|
|
40
|
-
}): Promise<AnonChallengeResult>;
|
|
41
|
-
verify(args: {
|
|
42
|
-
userHandle: Uint8Array;
|
|
43
|
-
credentialId: Uint8Array;
|
|
44
|
-
signature: Uint8Array;
|
|
45
|
-
clientDataJSON: Uint8Array;
|
|
46
|
-
authenticatorData: Uint8Array;
|
|
47
|
-
}): Promise<void>;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Build the anon ServerPolicy for a given dexter-api base.
|
|
51
|
-
*
|
|
52
|
-
* `issueChallenge` → POST /challenge { userHandle, operationHash } (both base64url).
|
|
53
|
-
* The server uses operationHash AS the WebAuthn challenge (replay binding +
|
|
54
|
-
* the on-chain webauthn.rs law: clientDataJSON.challenge === sha256(op)) and
|
|
55
|
-
* resolves the credential into options.allowCredentials[0].
|
|
56
|
-
* `verify` → POST /verify { credential, userHandle }. NOTE: the SDK hands us the
|
|
57
|
-
* COMPACT 64-byte signature; dexter-api's WebAuthn verifier wants DER, so we
|
|
58
|
-
* re-encode compact → DER here (compactSignatureToDer).
|
|
59
|
-
*/
|
|
60
|
-
declare function createAnonServerPolicy(apiBase?: string): AnonServerPolicy;
|
|
61
|
-
|
|
62
|
-
/** Test seam mirroring the SDK's injected-assertion shape (production omits it). */
|
|
63
|
-
type AssertionLike = {
|
|
64
|
-
credentialId: Uint8Array;
|
|
65
|
-
assertOver(challenge: Uint8Array): Promise<{
|
|
66
|
-
signature: Uint8Array;
|
|
67
|
-
clientDataJSON: Uint8Array;
|
|
68
|
-
authenticatorData: Uint8Array;
|
|
69
|
-
}>;
|
|
70
|
-
};
|
|
71
|
-
/**
|
|
72
|
-
* Construct the guest signer from a connected `ConnectVault`.
|
|
73
|
-
*
|
|
74
|
-
* `vault.publicKey` is base64 (33-byte SEC1 compressed P-256); `vault.userHandle`
|
|
75
|
-
* is base64url (server-minted). Both are decoded to the Uint8Arrays the SDK wants.
|
|
76
|
-
*
|
|
77
|
-
* @param vault the connected vault from useSignInWithDexter()
|
|
78
|
-
* @param apiBase dexter-api base (defaults to https://api.dexter.cash via the policy)
|
|
79
|
-
* @param opts.__assertion test-only injected assertion (skips real WebAuthn)
|
|
80
|
-
*/
|
|
81
|
-
declare function createPasskeySigner(vault: ConnectVault, apiBase?: string, opts?: {
|
|
82
|
-
__assertion?: AssertionLike;
|
|
83
|
-
}): DexterApiBrowserPasskeySigner;
|
|
84
|
-
|
|
85
|
-
declare function recoverWallet(config?: RecoverWalletConfig): Promise<RecoverOutcome>;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Human-readable label for a ceremony phase — the live "connecting step" copy.
|
|
89
|
-
* ONE source of truth so sign-in (SignInWithDexter) and create (consumer setup
|
|
90
|
-
* flows) show identical wording. Consumers surfacing createWallet's `onPhase`
|
|
91
|
-
* should use this instead of hand-rolling their own strings (Rule #7).
|
|
92
|
-
*/
|
|
93
|
-
declare function ceremonyPhaseLabel(phase: CeremonyPhase): string;
|
|
94
|
-
|
|
95
|
-
/** The automatic role-2 agent-spend rail. */
|
|
96
|
-
interface AutomaticAgentSpend {
|
|
97
|
-
/** true = agent-spend is ON (not revoked). Derived from revokedAt === null. */
|
|
98
|
-
active: boolean;
|
|
99
|
-
/** ISO timestamp the rail was revoked, or null when active. */
|
|
100
|
-
revokedAt: string | null;
|
|
101
|
-
/**
|
|
102
|
-
* On-chain role-2 arm state, decoded from authority.signer by the backend:
|
|
103
|
-
* true = armed (the rail is live and can spend)
|
|
104
|
-
* false = dormant (granted but not yet armed — arms on first pay)
|
|
105
|
-
* null = indeterminate (vault not activated, or a transient chain read failed)
|
|
106
|
-
* NEVER derived from liveSessionCount (that counts the wrong session model).
|
|
107
|
-
*/
|
|
108
|
-
armed: boolean | null;
|
|
109
|
-
spentTodayAtomic?: string;
|
|
110
|
-
dailyCapAtomic?: string;
|
|
111
|
-
perCallCapAtomic?: string;
|
|
112
|
-
lifetimeSpentAtomic?: string;
|
|
113
|
-
}
|
|
114
|
-
/** One explicit user-opened Tab (a V6 per-counterparty session). */
|
|
115
|
-
interface AgentSpendTab {
|
|
116
|
-
/** The session pubkey — the handle a Tab revoke targets. */
|
|
117
|
-
id: string;
|
|
118
|
-
/** The counterparty (agent/app) address this Tab authorizes. */
|
|
119
|
-
counterparty: string;
|
|
120
|
-
/** Display label: the Dexter-verified app name, else a shortened address. */
|
|
121
|
-
label: string;
|
|
122
|
-
/** Whether the Tab is currently live (not expired/spent-out/revoked). */
|
|
123
|
-
live: boolean;
|
|
124
|
-
/** Spent so far against this Tab's cap, atomic USDC (6dp) string. */
|
|
125
|
-
spentAtomic: string;
|
|
126
|
-
/** This Tab's spending cap, atomic USDC (6dp) string. */
|
|
127
|
-
capAtomic: string;
|
|
128
|
-
/** Unix seconds when the Tab expires. */
|
|
129
|
-
expiresAt: number;
|
|
130
|
-
}
|
|
131
|
-
/** The honest two-mode status: one balance, two separately-accounted rails. */
|
|
132
|
-
interface AgentSpendStatus {
|
|
133
|
-
/** Vault USDC balance, atomic (6dp) string — the ONE pool both rails draw. */
|
|
134
|
-
balanceAtomic: string | null;
|
|
135
|
-
/** The automatic role-2 rail. */
|
|
136
|
-
automatic: AutomaticAgentSpend;
|
|
137
|
-
/** The explicit Tabs. */
|
|
138
|
-
tabs: AgentSpendTab[];
|
|
139
|
-
}
|
|
140
|
-
/** The fields of GET /status the two-mode read consumes. */
|
|
141
|
-
interface RawAgentSpendStatus {
|
|
142
|
-
/** ISO timestamp when revoked, null when active. Top-level on /status. */
|
|
143
|
-
agentSpendRevokedAt?: string | null;
|
|
144
|
-
/** On-chain armed read (authority.signer). true/false/null. Top-level on /status. */
|
|
145
|
-
agentSpendArmed?: boolean | null;
|
|
146
|
-
/** On-chain block; usdcAtomic is the vault balance. */
|
|
147
|
-
onchain?: {
|
|
148
|
-
usdcAtomic?: string | null;
|
|
149
|
-
/** Present but DELIBERATELY UNUSED here — counts the wrong session model. */
|
|
150
|
-
liveSessionCount?: number;
|
|
151
|
-
} | null;
|
|
152
|
-
agentSpendDaily?: {
|
|
153
|
-
spentTodayAtomic?: string;
|
|
154
|
-
dailyCapAtomic?: string;
|
|
155
|
-
perCallCapAtomic?: string;
|
|
156
|
-
lifetimeSpentAtomic?: string;
|
|
157
|
-
} | null;
|
|
158
|
-
}
|
|
159
|
-
/** The fields of one GET /sessions row the Tabs rail consumes. */
|
|
160
|
-
interface RawAgentSpendSession {
|
|
161
|
-
sessionPubkey: string;
|
|
162
|
-
counterparty: string;
|
|
163
|
-
appName?: string | null;
|
|
164
|
-
live: boolean;
|
|
165
|
-
spent: string;
|
|
166
|
-
maxAmount: string;
|
|
167
|
-
expiresAt: number;
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Assemble the honest two-mode agent-spend status from the raw /status response
|
|
171
|
-
* and the raw /sessions rows. Pure: no fetch, no clock, no I/O.
|
|
172
|
-
*/
|
|
173
|
-
declare function assembleAgentSpendStatus(status: RawAgentSpendStatus, sessions?: RawAgentSpendSession[]): AgentSpendStatus;
|
|
174
|
-
/**
|
|
175
|
-
* The minimal identity the off/on switch needs: WHO is active + the wallet
|
|
176
|
-
* handle the anon router keys on. Structurally satisfied by connect's
|
|
177
|
-
* ResolvedIdentity (pass it straight through), or hand-build `{ kind, userHandle }`.
|
|
178
|
-
*/
|
|
179
|
-
interface AgentSpendIdentity {
|
|
180
|
-
/** Passkey-vault-first identity axis. Agent-spend is Dexter-Wallet-only. */
|
|
181
|
-
kind: IdentityKind;
|
|
182
|
-
/** The passkey-vault user handle the anon router addresses, or null. */
|
|
183
|
-
userHandle: string | null;
|
|
184
|
-
}
|
|
185
|
-
/** Typed error whose `code` is the server's snake_case error string. */
|
|
186
|
-
declare class AgentSpendError extends Error {
|
|
187
|
-
readonly code: string;
|
|
188
|
-
constructor(code: string, message?: string);
|
|
189
|
-
}
|
|
190
|
-
/** Map an AgentSpendError.code to plain, user-facing copy. */
|
|
191
|
-
declare function describeAgentSpendError(code: string): string;
|
|
192
|
-
interface RevokeAgentSpendResult {
|
|
193
|
-
revoked: boolean;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Revoke the AUTOMATIC role-2 agent-spend rail — the off-switch. Takes effect on
|
|
197
|
-
* the very next agent payment (the spend path reads agent_spend_revoked_at fresh
|
|
198
|
-
* per spend). Dexter-Wallet (anon-vault) only; `credentialId` (base64url) targets
|
|
199
|
-
* the biometric prompt.
|
|
200
|
-
*
|
|
201
|
-
* @param id WHO is active — must be the passkey-vault (Dexter Wallet).
|
|
202
|
-
* @param vaultPda The vault PDA, base58 string. Becomes the signed message.
|
|
203
|
-
* @param apiOrigin The dexter-api origin (e.g. https://api.dexter.cash). The
|
|
204
|
-
* caller owns env; connect reads none.
|
|
205
|
-
* @param credentialId The wallet's passkey credential id (base64url), to make
|
|
206
|
-
* the assertion a direct biometric, not an account picker.
|
|
207
|
-
*/
|
|
208
|
-
declare function revokeAgentSpend(id: AgentSpendIdentity, vaultPda: string, apiOrigin: string, credentialId?: string | null): Promise<RevokeAgentSpendResult>;
|
|
209
|
-
interface EnableAgentSpendResult {
|
|
210
|
-
enabled: boolean;
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Re-enable the AUTOMATIC role-2 agent-spend rail — the ON switch. Turning spend
|
|
214
|
-
* back ON is the dangerous direction, so it is a two-step, replay-protected nonce
|
|
215
|
-
* flow: fetch a server-minted nonce+expiry (inert until redeemed), sign
|
|
216
|
-
* enableAgentSpendMessage over those EXACT values as the WebAuthn challenge,
|
|
217
|
-
* submit. Dexter-Wallet (anon-vault) only.
|
|
218
|
-
*
|
|
219
|
-
* @param id WHO is active — must be the passkey-vault (Dexter Wallet).
|
|
220
|
-
* @param vaultPda The vault PDA, base58 string.
|
|
221
|
-
* @param apiOrigin The dexter-api origin (e.g. https://api.dexter.cash).
|
|
222
|
-
* @param credentialId The wallet's passkey credential id (base64url).
|
|
223
|
-
*/
|
|
224
|
-
declare function enableAgentSpend(id: AgentSpendIdentity, vaultPda: string, apiOrigin: string, credentialId?: string | null): Promise<EnableAgentSpendResult>;
|
|
225
|
-
|
|
226
|
-
export { AgentSpendError, type AgentSpendIdentity, type AgentSpendStatus, type AgentSpendTab, type AnonChallengeResult, type AnonServerPolicy, type AutomaticAgentSpend, CeremonyPhase, ConnectVault, type ContinueResult, CreateWalletConfig, CreateWalletResult, DexterConnectConfig, type EnableAgentSpendResult, IdentityKind, type RawAgentSpendSession, type RawAgentSpendStatus, RecoverOutcome, RecoverWalletConfig, type RevokeAgentSpendResult, SignInResult, assembleAgentSpendStatus, ceremonyPhaseLabel, continueWithDexter, createAnonServerPolicy, createPasskeySigner, describeAgentSpendError, enableAgentSpend, passkeyLogin, recoverWallet, revokeAgentSpend };
|
package/dist/react.d.ts
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { DexterApiBrowserPasskeySigner } from '@dexterai/vault/signers/browser';
|
|
2
|
-
import { b as CeremonyPhase, S as SignInResult, d as RecoverOutcome, P as PasskeyLoginTokens, c as ConnectVault, e as ConnectError, l as StoredWallet, g as PasskeySignalSupport, i as ResolvedIdentity, C as CreateWalletResult } from './signals-CQ5AEzXY.js';
|
|
3
|
-
export { h as RecoverVault } from './signals-CQ5AEzXY.js';
|
|
4
|
-
import { ReactElement, ButtonHTMLAttributes, ReactNode } from 'react';
|
|
5
|
-
|
|
6
|
-
type ConnectStatus = 'idle' | 'pending' | 'done' | 'error';
|
|
7
|
-
interface UseSignInWithDexterConfig {
|
|
8
|
-
/** dexter-api base. Default https://api.dexter.cash. */
|
|
9
|
-
apiBase?: string;
|
|
10
|
-
/** RPC for the connected-chip balance read. Default: Dexter's Helius proxy. */
|
|
11
|
-
rpcUrl?: string;
|
|
12
|
-
/** Ceremony transport (both verbs). 'auto' (default) = inline on dexter.cash,
|
|
13
|
-
* popup anywhere else. Exposed so tests/staging can force a leg —
|
|
14
|
-
* CreateWalletPanel already had this knob; the sign-in surface was the odd
|
|
15
|
-
* one out. */
|
|
16
|
-
transport?: 'auto' | 'popup' | 'inline';
|
|
17
|
-
/** Hosted ceremony page for the popup transport. Default dexter.cash/connect. */
|
|
18
|
-
connectHost?: string;
|
|
19
|
-
/** Chrome-149+ immediate UI mode for the wallet-only verb: instant fast-fail
|
|
20
|
-
* when this device holds no passkey. Ignored by signIn(). */
|
|
21
|
-
preferImmediate?: boolean;
|
|
22
|
-
}
|
|
23
|
-
interface UseSignInWithDexter {
|
|
24
|
-
status: ConnectStatus;
|
|
25
|
-
/** Live ceremony phase while status==='pending' (challenge → passkey →
|
|
26
|
-
* verifying); null otherwise. Drives the button's "connecting steps". */
|
|
27
|
-
phase: CeremonyPhase | null;
|
|
28
|
-
isVaultConnected: boolean;
|
|
29
|
-
/** Run the ceremony. Resolves with the result; throws ConnectError on failure
|
|
30
|
-
* (error is also captured in `error` + `status==='error'` for declarative UI). */
|
|
31
|
-
signIn: () => Promise<SignInResult>;
|
|
32
|
-
/** Wallet-only sign-in (P0c): re-points this browser at an existing wallet,
|
|
33
|
-
* mints NO session. Returns a discriminated outcome — cancel is a normal
|
|
34
|
-
* result, never a throw. Identity surfaces (useIdentity/useDexterWallet)
|
|
35
|
-
* light up via the wallet store; `session`/`vault` here stay null. Fire on
|
|
36
|
-
* tap only — never on mount (iOS gesture rule). */
|
|
37
|
-
recover: () => Promise<RecoverOutcome>;
|
|
38
|
-
/** Last recover outcome; null until recover() settles. */
|
|
39
|
-
recovered: RecoverOutcome | null;
|
|
40
|
-
disconnect: () => void;
|
|
41
|
-
session: PasskeyLoginTokens | null;
|
|
42
|
-
vault: ConnectVault | null;
|
|
43
|
-
/** Dexter Wallet address (swigAddress, base58). */
|
|
44
|
-
vaultAddress: string | null;
|
|
45
|
-
vaultPda: string | null;
|
|
46
|
-
credentialId: string | null;
|
|
47
|
-
/** Guest passkey signer for authorizing spends / opening x402 tabs. null until
|
|
48
|
-
* a vault is connected. Drive it via `passkeySigner.signOperation(op)`. */
|
|
49
|
-
passkeySigner: DexterApiBrowserPasskeySigner | null;
|
|
50
|
-
/** USD available. number once read; null = unknown → chip shows wallet only. */
|
|
51
|
-
usdcBalance: number | null;
|
|
52
|
-
refreshBalance: () => Promise<void>;
|
|
53
|
-
error: ConnectError | null;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* "Sign in with Dexter" — React surface over the login ceremony.
|
|
57
|
-
*
|
|
58
|
-
* Returns the Supabase session (always) plus the vault identity + USD balance
|
|
59
|
-
* (vault-review's login payload is live). dexter.cash login needs only
|
|
60
|
-
* `session`; the vault fields + balance drive the connected chip. The
|
|
61
|
-
* passkeySigner (for opening x402 tabs — dexter-agents) lands next, on the
|
|
62
|
-
* anon ServerPolicy bridge over the now-live publicKey/credentialId.
|
|
63
|
-
*/
|
|
64
|
-
declare function useSignInWithDexter(config?: UseSignInWithDexterConfig): UseSignInWithDexter;
|
|
65
|
-
|
|
66
|
-
interface SignInWithDexterProps extends UseSignInWithDexterConfig {
|
|
67
|
-
/** 'signin' (default) = full sign-in minting the account session.
|
|
68
|
-
* 'recover' = wallet-only: re-points this browser at an existing wallet and
|
|
69
|
-
* mints NOTHING else (the wallet IS the sign-in). After a successful
|
|
70
|
-
* recover the element renders null — identity display belongs to
|
|
71
|
-
* DexterWalletChip/useIdentity, which light up via the wallet store. */
|
|
72
|
-
mode?: 'signin' | 'recover';
|
|
73
|
-
/** Fired with the result the moment sign-in completes. */
|
|
74
|
-
onSuccess?: (result: SignInResult) => void;
|
|
75
|
-
/** Recover mode: fired with EVERY settled outcome (ok, no_credential,
|
|
76
|
-
* cancelled, error) — the single channel; onError is not used in this mode.
|
|
77
|
-
* Branch on `reason`: no_credential → offer create; cancelled → stay silent. */
|
|
78
|
-
onRecovered?: (outcome: RecoverOutcome) => void;
|
|
79
|
-
/** Fired with the typed error if the ceremony fails. */
|
|
80
|
-
onError?: (error: ConnectError) => void;
|
|
81
|
-
/** Button label when signed out. Default "Sign in with Dexter". */
|
|
82
|
-
label?: string;
|
|
83
|
-
/** 'primary' = filled ember (default), 'secondary' = outline. */
|
|
84
|
-
variant?: 'primary' | 'secondary';
|
|
85
|
-
/** Full-width button. */
|
|
86
|
-
block?: boolean;
|
|
87
|
-
/** 'md' (default) or 'sm' — the mini header variant of the button. */
|
|
88
|
-
size?: 'md' | 'sm';
|
|
89
|
-
/** Extra className composed after the brand classes. Prefer overriding the
|
|
90
|
-
* `--dx-*` CSS variables for theming. */
|
|
91
|
-
className?: string;
|
|
92
|
-
/** Render the built-in connected chip (wallet + balance). Default true. */
|
|
93
|
-
showConnectedChip?: boolean;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Turnkey "Sign in with Dexter" element. Signed out → the branded DexterButton
|
|
97
|
-
* (hover / focus / active / loading states, themeable via --dx-* CSS vars);
|
|
98
|
-
* signed in → a compact chip with the Dexter Wallet address + USD available.
|
|
99
|
-
* Wraps useSignInWithDexter; for the wallet CREATE flow use <DexterButton>
|
|
100
|
-
* wired to your create action. Brand voice: no emojis, "unlock" banned.
|
|
101
|
-
*/
|
|
102
|
-
declare function SignInWithDexter(props: SignInWithDexterProps): ReactElement | null;
|
|
103
|
-
|
|
104
|
-
/** The Dexter passkey mark — the brand glyph carried on the branded button. */
|
|
105
|
-
declare function DexterMark(): ReactElement;
|
|
106
|
-
interface DexterButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onClick' | 'disabled' | 'className' | 'type'> {
|
|
107
|
-
/** Button content (e.g. "Sign in with Dexter", "Create your Dexter Wallet"). */
|
|
108
|
-
children?: ReactNode;
|
|
109
|
-
/** Loading state: shows the animated spinner + `loadingLabel`, disables click. */
|
|
110
|
-
loading?: boolean;
|
|
111
|
-
/** Label shown next to the spinner while loading. Default "Connecting…". */
|
|
112
|
-
loadingLabel?: string;
|
|
113
|
-
/** 'primary' = filled ember (default), 'secondary' = outline,
|
|
114
|
-
* 'danger' = outline in the danger color for destructive actions. */
|
|
115
|
-
variant?: 'primary' | 'secondary' | 'danger';
|
|
116
|
-
/** Full-width (fills its container). */
|
|
117
|
-
block?: boolean;
|
|
118
|
-
/** 'md' (default) = the standard CTA. 'sm' = the mini header/chip-row
|
|
119
|
-
* variant: tighter padding, smaller type and mark. Same states, same
|
|
120
|
-
* theming — never hand-shrink the md button with a className. */
|
|
121
|
-
size?: 'md' | 'sm';
|
|
122
|
-
/** Render the Dexter mark before the children. Default true. */
|
|
123
|
-
withMark?: boolean;
|
|
124
|
-
onClick?: () => void;
|
|
125
|
-
disabled?: boolean;
|
|
126
|
-
/** Extra className composed after the brand classes. */
|
|
127
|
-
className?: string;
|
|
128
|
-
type?: 'button' | 'submit';
|
|
129
|
-
}
|
|
130
|
-
/** The branded Dexter button. Wire it to any action via `onClick`. */
|
|
131
|
-
declare function DexterButton(props: DexterButtonProps): ReactElement;
|
|
132
|
-
|
|
133
|
-
interface UseDexterWallet {
|
|
134
|
-
/** Active wallet handle, or null if this browser has no active wallet. */
|
|
135
|
-
activeHandle: string | null;
|
|
136
|
-
/** The active wallet's roster entry (handle + label + credentialId), or
|
|
137
|
-
* null. `activeWallet.label` is the wallet's human name — identity is
|
|
138
|
-
* first-class, so display surfaces read it here instead of re-fetching. */
|
|
139
|
-
activeWallet: StoredWallet | null;
|
|
140
|
-
/** Known wallets on this browser, most-recently-used first. */
|
|
141
|
-
wallets: StoredWallet[];
|
|
142
|
-
/** What the WebAuthn Signal API supports in THIS browser (rename / prune). */
|
|
143
|
-
support: PasskeySignalSupport;
|
|
144
|
-
/**
|
|
145
|
-
* Eject the active wallet — "switch / start fresh". Clears the local binding
|
|
146
|
-
* and, where supported, prunes the old passkey from the OS manager so it
|
|
147
|
-
* disappears from the user's list. `{ forget: true }` also drops it from the
|
|
148
|
-
* roster.
|
|
149
|
-
*/
|
|
150
|
-
eject: (opts?: {
|
|
151
|
-
forget?: boolean;
|
|
152
|
-
}) => void;
|
|
153
|
-
/** Switch the active wallet to a known handle. No-op if unknown. */
|
|
154
|
-
switchTo: (handle: string) => boolean;
|
|
155
|
-
/** Record/activate a handle (after enroll or recover). Prefer over writing
|
|
156
|
-
* localStorage by hand so the roster + subscribers stay correct. */
|
|
157
|
-
setActive: (handle: string, label?: string, credentialId?: string) => void;
|
|
158
|
-
/**
|
|
159
|
-
* Rename the ACTIVE passkey in the OS keychain (post-creation). Returns true
|
|
160
|
-
* if the browser supported it and the signal fired; false otherwise (the
|
|
161
|
-
* keychain entry is then just left as-is).
|
|
162
|
-
*/
|
|
163
|
-
rename: (name: string, displayName?: string) => Promise<boolean>;
|
|
164
|
-
}
|
|
165
|
-
declare function useDexterWallet(): UseDexterWallet;
|
|
166
|
-
|
|
167
|
-
interface DexterWalletChipProps {
|
|
168
|
-
/** Connected (a wallet/account is present) → avatar + label; else signed-out label only. */
|
|
169
|
-
connected: boolean;
|
|
170
|
-
/** What to show: account name, wallet label, or the signed-out prompt (e.g. "Log in"). */
|
|
171
|
-
label: string;
|
|
172
|
-
/** Avatar image (e.g. a linked X avatar); falls back to the initial. */
|
|
173
|
-
avatarUrl?: string | null;
|
|
174
|
-
/** Single-character avatar fallback (defaults to the first letter of `label`). */
|
|
175
|
-
avatarInitial?: string;
|
|
176
|
-
onClick?: () => void;
|
|
177
|
-
/** Extra className composed after the brand classes. */
|
|
178
|
-
className?: string;
|
|
179
|
-
/** Reflected to aria-expanded (when the chip toggles a menu). */
|
|
180
|
-
ariaExpanded?: boolean;
|
|
181
|
-
}
|
|
182
|
-
/** The branded wallet/account chip. Wire it to open your menu via `onClick`. */
|
|
183
|
-
declare function DexterWalletChip(props: DexterWalletChipProps): ReactElement;
|
|
184
|
-
|
|
185
|
-
interface DexterWalletMenuProps {
|
|
186
|
-
/** The wallet's display name (nickname, else "Dexter Wallet"). */
|
|
187
|
-
walletLabel: string;
|
|
188
|
-
/** Avatar initial (defaults to the first letter of walletLabel). */
|
|
189
|
-
avatarInitial?: string;
|
|
190
|
-
/** "Manage wallet" → the consumer's wallet page. Row hidden if omitted. */
|
|
191
|
-
onManageWallet?: () => void;
|
|
192
|
-
/** Eject row → the consumer ejects/resets (guard + perform on its side). Row hidden if omitted. */
|
|
193
|
-
onStartFresh?: () => void;
|
|
194
|
-
/** Label for the eject/reset row. Default "Eject wallet". */
|
|
195
|
-
startFreshLabel?: string;
|
|
196
|
-
/** Sign-in/save UI revealed when "Save your wallet" is tapped (e.g. <SignInWithDexter/>). Row hidden if omitted. */
|
|
197
|
-
saveSlot?: ReactNode;
|
|
198
|
-
/** Short hint shown above the save UI. */
|
|
199
|
-
saveHint?: string;
|
|
200
|
-
/** Extra className composed after the brand classes. */
|
|
201
|
-
className?: string;
|
|
202
|
-
}
|
|
203
|
-
/** The branded wallet dropdown. */
|
|
204
|
-
declare function DexterWalletMenu(props: DexterWalletMenuProps): ReactElement;
|
|
205
|
-
|
|
206
|
-
interface UseIdentityConfig {
|
|
207
|
-
/** The account session token (e.g. a Supabase access_token), or null when the
|
|
208
|
-
* user has no account session. The SDK is auth-agnostic — pass your own. */
|
|
209
|
-
accountToken: string | null;
|
|
210
|
-
}
|
|
211
|
-
declare function useIdentity({ accountToken }: UseIdentityConfig): ResolvedIdentity;
|
|
212
|
-
|
|
213
|
-
interface AllowanceChipsProps {
|
|
214
|
-
/** The authored USD amount as a raw string, or null when nothing is chosen.
|
|
215
|
-
* NONE selected initially → pass null. Preset chips echo '5' / '20' / '50';
|
|
216
|
-
* Custom echoes whatever the user types. */
|
|
217
|
-
value: string | null;
|
|
218
|
-
/** Fired with the raw USD string (or null when Custom is opened empty). */
|
|
219
|
-
onChange: (usd: string | null) => void;
|
|
220
|
-
/** Extra className composed after the brand classes. */
|
|
221
|
-
className?: string;
|
|
222
|
-
}
|
|
223
|
-
/** The consent-at-birth allowance chips. */
|
|
224
|
-
declare function AllowanceChips(props: AllowanceChipsProps): ReactElement;
|
|
225
|
-
|
|
226
|
-
interface CreateWalletPanelProps {
|
|
227
|
-
/** Fired with the minted wallet the moment creation succeeds. */
|
|
228
|
-
onCreated?: (result: CreateWalletResult) => void;
|
|
229
|
-
/** Fired with the typed error if the ceremony fails. */
|
|
230
|
-
onError?: (error: ConnectError) => void;
|
|
231
|
-
/** dexter-api base. Default https://api.dexter.cash (createWallet's default). */
|
|
232
|
-
apiBase?: string;
|
|
233
|
-
/** Where the WebAuthn ceremony runs. Default 'auto' (createWallet's default). */
|
|
234
|
-
transport?: 'auto' | 'popup' | 'inline';
|
|
235
|
-
/** Render the optional "Name your wallet" field. Default true. */
|
|
236
|
-
showName?: boolean;
|
|
237
|
-
/** Extra className composed after the brand classes. */
|
|
238
|
-
className?: string;
|
|
239
|
-
}
|
|
240
|
-
/** The turnkey consent-at-birth create panel. */
|
|
241
|
-
declare function CreateWalletPanel(props: CreateWalletPanelProps): ReactElement;
|
|
242
|
-
|
|
243
|
-
export { AllowanceChips, type AllowanceChipsProps, type ConnectStatus, CreateWalletPanel, type CreateWalletPanelProps, DexterButton, type DexterButtonProps, DexterMark, DexterWalletChip, type DexterWalletChipProps, DexterWalletMenu, type DexterWalletMenuProps, RecoverOutcome, SignInWithDexter, type SignInWithDexterProps, type UseDexterWallet, type UseIdentityConfig, type UseSignInWithDexter, type UseSignInWithDexterConfig, useDexterWallet, useIdentity, useSignInWithDexter };
|
package/dist/server.d.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { JWTPayload, JWK, JSONWebKeySet } from 'jose';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @dexterai/connect/server — offline Dexter session verification.
|
|
5
|
-
*
|
|
6
|
-
* The server half of Sign in with Dexter (CONTRACT-dexter-session-token.md):
|
|
7
|
-
* a local ES256 signature check against the published JWKS — no call to
|
|
8
|
-
* Supabase or dexter-api on the hot path, so it runs on Node and edge
|
|
9
|
-
* runtimes alike. Pre-hook tokens (no `dexter` claim) verify as signed-in
|
|
10
|
-
* with `vaultAddress: null`; once the access-token hook is enabled the
|
|
11
|
-
* claim appears with no code change here.
|
|
12
|
-
*
|
|
13
|
-
* Phase 1 issuer is Supabase (CONTRACT §3); everything is parameterized on
|
|
14
|
-
* (iss, jwksUrl) so the Phase-2 sovereign cutover is a config flip.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
declare const DEFAULT_ISS = "https://qdgumpoqnthrjfmqziwm.supabase.co/auth/v1";
|
|
18
|
-
declare const DEFAULT_AUDIENCE = "authenticated";
|
|
19
|
-
/** The namespaced claim sealed into the token by the access-token hook. */
|
|
20
|
-
interface DexterClaim {
|
|
21
|
-
ver: number;
|
|
22
|
-
/** Swig state address (base58) — the canonical Dexter Wallet identity. */
|
|
23
|
-
vault: string;
|
|
24
|
-
/** 16-byte passkey handle, base64url; absent on rows without one. */
|
|
25
|
-
userHandle?: string;
|
|
26
|
-
agentGrant?: unknown;
|
|
27
|
-
}
|
|
28
|
-
type VerifyFailureReason = 'no_token' | 'invalid' | 'expired' | 'issuer_mismatch' | 'audience_mismatch';
|
|
29
|
-
type DexterSession = {
|
|
30
|
-
isSignedIn: true;
|
|
31
|
-
sub: string;
|
|
32
|
-
vaultAddress: string | null;
|
|
33
|
-
userHandle: string | null;
|
|
34
|
-
agentGrant: unknown;
|
|
35
|
-
sessionId: string | null;
|
|
36
|
-
aal: string | null;
|
|
37
|
-
claims: JWTPayload & {
|
|
38
|
-
dexter?: DexterClaim;
|
|
39
|
-
};
|
|
40
|
-
} | {
|
|
41
|
-
isSignedIn: false;
|
|
42
|
-
reason: VerifyFailureReason;
|
|
43
|
-
};
|
|
44
|
-
interface VerifyOptions {
|
|
45
|
-
/** Expected issuer. Phase 1 default: the Dexter Supabase project. */
|
|
46
|
-
iss?: string;
|
|
47
|
-
/** JWKS location; defaults to `${iss}/.well-known/jwks.json`. */
|
|
48
|
-
jwksUrl?: string;
|
|
49
|
-
/**
|
|
50
|
-
* Public key(s) for fully networkless verification (a JWK or a JWKS).
|
|
51
|
-
* When omitted, the JWKS is fetched once and cached in-instance.
|
|
52
|
-
*/
|
|
53
|
-
jwtKey?: JWK | JSONWebKeySet;
|
|
54
|
-
/** Expected audience. Default: Supabase's `authenticated`. */
|
|
55
|
-
audience?: string;
|
|
56
|
-
}
|
|
57
|
-
/** A fetch-API Request or anything with a node-style headers bag. */
|
|
58
|
-
type RequestLike = Request | {
|
|
59
|
-
headers: Record<string, string | string[] | undefined>;
|
|
60
|
-
};
|
|
61
|
-
interface DexterClient {
|
|
62
|
-
verifyDexterSession(token: string): Promise<DexterSession>;
|
|
63
|
-
authenticateRequest(req: RequestLike): Promise<DexterSession>;
|
|
64
|
-
}
|
|
65
|
-
declare function createDexterClient(options?: VerifyOptions): DexterClient;
|
|
66
|
-
/**
|
|
67
|
-
* One-off verification. For servers verifying many requests against a
|
|
68
|
-
* remote JWKS, create a client once instead so the key set caches.
|
|
69
|
-
*/
|
|
70
|
-
declare function verifyDexterSession(token: string, options?: VerifyOptions): Promise<DexterSession>;
|
|
71
|
-
|
|
72
|
-
export { DEFAULT_AUDIENCE, DEFAULT_ISS, type DexterClaim, type DexterClient, type DexterSession, type RequestLike, type VerifyFailureReason, type VerifyOptions, createDexterClient, verifyDexterSession };
|
|
@@ -1,285 +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
|
-
/** The wallet's cross-device display name (user-authored via rename), or
|
|
29
|
-
* null when never named. Identity is first-class: every sign-in carries
|
|
30
|
-
* the human name so no consumer ever falls back to a synthetic email.
|
|
31
|
-
* Optional for wire-compat with servers/popup pages predating 0.23. */
|
|
32
|
-
walletLabel?: string | null;
|
|
33
|
-
}
|
|
34
|
-
/** Result of a completed "Sign in with Dexter" ceremony. */
|
|
35
|
-
interface SignInResult {
|
|
36
|
-
session: PasskeyLoginTokens;
|
|
37
|
-
/** Present once vault-review ships the vault-in-login change. */
|
|
38
|
-
vault?: ConnectVault;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Coarse ceremony phase, emitted as a sign-in/create ceremony progresses so the
|
|
42
|
-
* UI can show live "connecting steps" instead of one flat spinner:
|
|
43
|
-
* challenge → passkey (the OS prompt) → verifying → finalizing (create only).
|
|
44
|
-
*/
|
|
45
|
-
type CeremonyPhase = 'challenge' | 'passkey' | 'verifying' | 'finalizing';
|
|
46
|
-
/**
|
|
47
|
-
* Vault identity on the wallet-only recover leg, as reported by
|
|
48
|
-
* /api/passkey-vault-anon/status. Narrower than ConnectVault on purpose —
|
|
49
|
-
* the status endpoint carries no publicKey/usdcAta, so a recover cannot
|
|
50
|
-
* construct a passkey signer; it re-points this browser at the wallet and
|
|
51
|
-
* lets useIdentity/useDexterWallet light the UI.
|
|
52
|
-
*/
|
|
53
|
-
interface RecoverVault {
|
|
54
|
-
vaultPda: string;
|
|
55
|
-
/** Swig state address, base58 — the user-facing Dexter Wallet address. */
|
|
56
|
-
swigAddress: string;
|
|
57
|
-
/** Deposit address; null until the swig is deployed. */
|
|
58
|
-
receiveAddress: string | null;
|
|
59
|
-
isActivated: boolean;
|
|
60
|
-
walletLabel: string | null;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Result of a wallet-only recover ceremony. A discriminated RESULT, not a
|
|
64
|
-
* throw: user-cancel is a normal outcome in WebAuthn, and consumers branch on
|
|
65
|
-
* `reason` (no_credential → offer create; cancelled → stay silent; error →
|
|
66
|
-
* retry copy). `no_credential` covers both the immediate-mode instant
|
|
67
|
-
* rejection (no passkey on this device) and a verify 404 (a passkey the
|
|
68
|
-
* server has no row for).
|
|
69
|
-
*/
|
|
70
|
-
type RecoverOutcome = {
|
|
71
|
-
ok: true;
|
|
72
|
-
userHandle: string;
|
|
73
|
-
credentialId: string;
|
|
74
|
-
vault: RecoverVault;
|
|
75
|
-
} | {
|
|
76
|
-
ok: false;
|
|
77
|
-
reason: 'no_credential' | 'cancelled' | 'error';
|
|
78
|
-
error?: ConnectError;
|
|
79
|
-
};
|
|
80
|
-
interface RecoverWalletConfig extends DexterConnectConfig {
|
|
81
|
-
/** Chrome-149+ immediate UI mode: instant fast-fail when this device has no
|
|
82
|
-
* discoverable passkey (no empty account-picker sheet). Falls back to the
|
|
83
|
-
* normal modal wherever unsupported. */
|
|
84
|
-
preferImmediate?: boolean;
|
|
85
|
-
onPhase?: (phase: CeremonyPhase) => void;
|
|
86
|
-
}
|
|
87
|
-
interface DexterConnectConfig {
|
|
88
|
-
/** dexter-api base. Default https://api.dexter.cash. */
|
|
89
|
-
apiBase?: string;
|
|
90
|
-
/**
|
|
91
|
-
* Where the WebAuthn ceremony runs:
|
|
92
|
-
* - 'auto' (default): inline on the canonical Dexter origin (dexter.cash),
|
|
93
|
-
* popup on ANY other origin — so a third-party site works without the
|
|
94
|
-
* WebAuthn rpId-origin problem (in-page only works on dexter.cash).
|
|
95
|
-
* - 'popup': always via the hosted popup (works on any website).
|
|
96
|
-
* - 'inline': always in-page — only valid on a Dexter origin; this is what
|
|
97
|
-
* the hosted ceremony page itself uses.
|
|
98
|
-
*/
|
|
99
|
-
transport?: 'auto' | 'popup' | 'inline';
|
|
100
|
-
/** Hosted ceremony page (popup transport). Default https://dexter.cash/connect. */
|
|
101
|
-
connectHost?: string;
|
|
102
|
-
}
|
|
103
|
-
/** Typed error whose `code` is the server's snake_case error string. */
|
|
104
|
-
declare class ConnectError extends Error {
|
|
105
|
-
readonly code: string;
|
|
106
|
-
constructor(code: string, message?: string);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** Consent-at-birth allowance (Branch rulings 2026-07-02/03).
|
|
110
|
-
* The user authors the number; zero is not consent; TTL is fixed 30d and
|
|
111
|
-
* never user-editable; no caller may invent a default. */
|
|
112
|
-
declare const SESSION_TTL_30D = "2592000";
|
|
113
|
-
interface SpendPolicy {
|
|
114
|
-
/** Role-2 allowance, atomic USDC (6dp), decimal string. User-authored. */
|
|
115
|
-
spendLimitAtomic: string;
|
|
116
|
-
/** Fixed 30d. Present for wire compatibility; always SESSION_TTL_30D. */
|
|
117
|
-
sessionTtlSeconds: string;
|
|
118
|
-
}
|
|
119
|
-
/** Parse user-entered USD ("5", "$20", "1,000", "20.5") to atomic USDC.
|
|
120
|
-
* Null on anything invalid — callers must not invent a fallback. */
|
|
121
|
-
declare function usdToAtomic(input: string): bigint | null;
|
|
122
|
-
/** Null when invalid or zero (zero is not consent). */
|
|
123
|
-
declare function authoredPolicy(usdInput: string): SpendPolicy | null;
|
|
124
|
-
|
|
125
|
-
interface CreateWalletConfig extends DexterConnectConfig {
|
|
126
|
-
/** Label for the passkey in the OS keychain AND the wallet roster. Set at
|
|
127
|
-
* creation — the only moment naming is guaranteed to stick. Default "Dexter Wallet". */
|
|
128
|
-
name?: string;
|
|
129
|
-
/** RP id for the new credential. Default "dexter.cash". */
|
|
130
|
-
rpId?: string;
|
|
131
|
-
/** Consent-at-birth allowance the user authored at creation (chips $5/$20/$50
|
|
132
|
-
* or Custom; zero is not consent; build it with authoredPolicy()). When
|
|
133
|
-
* present it rides the /initialize body so the number becomes the server-side
|
|
134
|
-
* write-once consent record. The TTL is ruled fixed 30d — whatever the object
|
|
135
|
-
* carries, the wire always sends SESSION_TTL_30D. Absent → no policy authored
|
|
136
|
-
* (the vault initializes without one; nothing invents a default). */
|
|
137
|
-
spendPolicy?: SpendPolicy;
|
|
138
|
-
/** Called as the ceremony progresses, for live "connecting steps" UI:
|
|
139
|
-
* challenge → passkey → verifying → finalizing. */
|
|
140
|
-
onPhase?: (phase: CeremonyPhase) => void;
|
|
141
|
-
}
|
|
142
|
-
interface CreateWalletResult {
|
|
143
|
-
/** Server-minted 16-byte user handle, base64url — the vault identity. */
|
|
144
|
-
handle: string;
|
|
145
|
-
/** base64url credential id of the new passkey. */
|
|
146
|
-
credentialId: string;
|
|
147
|
-
/** The freshly initialized vault (swig not yet deployed; deploys lazily). */
|
|
148
|
-
vault: ConnectVault;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Mint a brand-new Dexter wallet (passkey + vault) and make it the active wallet.
|
|
152
|
-
*
|
|
153
|
-
* One passkey approval. Throws ConnectError on any failed leg (the `code` is the
|
|
154
|
-
* server's error string, or webauthn_failed / no_credential for the ceremony).
|
|
155
|
-
*/
|
|
156
|
-
declare function createWallet(config?: CreateWalletConfig): Promise<CreateWalletResult>;
|
|
157
|
-
|
|
158
|
-
type IdentityKind = 'passkey-vault' | 'account' | 'none';
|
|
159
|
-
interface IdentityInput {
|
|
160
|
-
/** An account session token (e.g. Supabase access_token) when present, else null. */
|
|
161
|
-
accountToken: string | null;
|
|
162
|
-
/** The passkey-vault user handle (the connect wallet store), else null. */
|
|
163
|
-
userHandle: string | null;
|
|
164
|
-
/** The active wallet's display name from the connect wallet store (persisted
|
|
165
|
-
* at sign-in/recover/rename), else null. Browser-only input like the handle. */
|
|
166
|
-
walletLabel?: string | null;
|
|
167
|
-
}
|
|
168
|
-
interface ResolvedIdentity {
|
|
169
|
-
/** The primary identity axis, passkey-vault-first. */
|
|
170
|
-
kind: IdentityKind;
|
|
171
|
-
/** Passkey-vault identity (FIRST-CLASS): the wallet handle, or null. */
|
|
172
|
-
userHandle: string | null;
|
|
173
|
-
/** The wallet's human display name, or null when the wallet was never named
|
|
174
|
-
* (or no wallet is active). Display surfaces prefer this over any synthetic
|
|
175
|
-
* account identifier — a user should never be shown a generated email. */
|
|
176
|
-
walletLabel: string | null;
|
|
177
|
-
/** Account identity (secondary/legacy axis): bearer for account-scoped fetches, or null. */
|
|
178
|
-
accountToken: string | null;
|
|
179
|
-
/** A passkey vault is present on this device. */
|
|
180
|
-
hasPasskeyVault: boolean;
|
|
181
|
-
/** An account session is present. */
|
|
182
|
-
hasAccount: boolean;
|
|
183
|
-
/** Any identity at all — drives "show the wallet" vs "Sign in with Dexter". */
|
|
184
|
-
hasWallet: boolean;
|
|
185
|
-
}
|
|
186
|
-
declare function resolveIdentity(input: IdentityInput): ResolvedIdentity;
|
|
187
|
-
|
|
188
|
-
/** A wallet this browser knows about. `handle` is the identity; the rest is UX. */
|
|
189
|
-
interface StoredWallet {
|
|
190
|
-
/** base64url 16-byte user handle — the vault identity. */
|
|
191
|
-
handle: string;
|
|
192
|
-
/** Human label for switch UIs (e.g. an email, or "Dexter Wallet"). */
|
|
193
|
-
label?: string;
|
|
194
|
-
/** base64url credential id — enables the WebAuthn Signal API to prune this
|
|
195
|
-
* passkey from the OS manager on eject (see ./signals). */
|
|
196
|
-
credentialId?: string;
|
|
197
|
-
/** Epoch ms of last activation — for ordering the switcher. */
|
|
198
|
-
lastUsedAt?: number;
|
|
199
|
-
}
|
|
200
|
-
type Listener = () => void;
|
|
201
|
-
/** The active wallet handle, or null if this browser has no active wallet. */
|
|
202
|
-
declare function getActiveHandle(): string | null;
|
|
203
|
-
/**
|
|
204
|
-
* Set the active wallet handle (e.g. after enroll or recover), upserting it into
|
|
205
|
-
* the roster with a fresh `lastUsedAt`. Idempotent. Fires subscribers.
|
|
206
|
-
*/
|
|
207
|
-
declare function setActiveHandle(handle: string, label?: string, credentialId?: string): void;
|
|
208
|
-
/** Look up a known wallet's stored credentialId (for Signal-API prune on eject). */
|
|
209
|
-
declare function getCredentialId(handle: string): string | undefined;
|
|
210
|
-
/**
|
|
211
|
-
* EJECT — clear the active wallet so the browser is no longer bound to it. This
|
|
212
|
-
* is "switch / start fresh / sign out of this wallet". The wallet stays in the
|
|
213
|
-
* roster (so the user can switch back) unless `forget` is true. After eject,
|
|
214
|
-
* `getActiveHandle()` is null and the next enroll/recover starts clean. Fires
|
|
215
|
-
* subscribers. This is the function whose absence WAS the welded-wallet bug.
|
|
216
|
-
*/
|
|
217
|
-
declare function ejectActiveWallet(opts?: {
|
|
218
|
-
forget?: boolean;
|
|
219
|
-
}): void;
|
|
220
|
-
/** Every wallet this browser knows about, most-recently-used first. */
|
|
221
|
-
declare function listWallets(): StoredWallet[];
|
|
222
|
-
/**
|
|
223
|
-
* Switch the active wallet to a handle ALREADY in the roster. Returns false (and
|
|
224
|
-
* does nothing) if the handle is unknown — switching is only ever to a wallet
|
|
225
|
-
* this browser has seen, never to an arbitrary string.
|
|
226
|
-
*/
|
|
227
|
-
declare function switchWallet(handle: string): boolean;
|
|
228
|
-
/** Remove a wallet from the roster entirely; clears active if it was active. */
|
|
229
|
-
declare function forgetWallet(handle: string): void;
|
|
230
|
-
/**
|
|
231
|
-
* Subscribe to active-wallet/roster changes. Returns an unsubscribe fn. Also
|
|
232
|
-
* wires the cross-tab `storage` event once, so ejecting in one tab updates the
|
|
233
|
-
* others. The React hook (`useDexterWallet`) is a thin wrapper over this.
|
|
234
|
-
*/
|
|
235
|
-
declare function subscribe(listener: Listener): () => void;
|
|
236
|
-
/** Exposed for consumers that must reference the canonical key (migrations,
|
|
237
|
-
* tests). Prefer the accessors above — do NOT read localStorage by hand. */
|
|
238
|
-
declare const ACTIVE_WALLET_STORAGE_KEY = "dexter:passkey:userHandle";
|
|
239
|
-
|
|
240
|
-
interface PasskeySignalSupport {
|
|
241
|
-
/** signalCurrentUserDetails — rename a passkey post-creation. */
|
|
242
|
-
rename: boolean;
|
|
243
|
-
/** signalUnknownCredential — remove one stale passkey from the manager. */
|
|
244
|
-
prune: boolean;
|
|
245
|
-
/** signalAllAcceptedCredentials — reconcile the full valid set. */
|
|
246
|
-
syncAccepted: boolean;
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* What the CURRENT browser supports, by direct feature-detection. Instant, no
|
|
250
|
-
* network, no UA sniffing — tells you exactly what will light up on THIS device
|
|
251
|
-
* (e.g. call once on Branch's iPhone to learn its Safari's status).
|
|
252
|
-
*/
|
|
253
|
-
declare function passkeySignalSupport(): PasskeySignalSupport;
|
|
254
|
-
/**
|
|
255
|
-
* Rename a passkey in the OS keychain AFTER creation. `userId` is the base64url
|
|
256
|
-
* user handle; `rpId` defaults to the current host. Returns true if the signal
|
|
257
|
-
* fired, false if unsupported/failed (caller treats false as "left as-is").
|
|
258
|
-
*/
|
|
259
|
-
declare function renamePasskey(args: {
|
|
260
|
-
userId: string;
|
|
261
|
-
name: string;
|
|
262
|
-
displayName?: string;
|
|
263
|
-
rpId?: string;
|
|
264
|
-
}): Promise<boolean>;
|
|
265
|
-
/**
|
|
266
|
-
* Tell the OS manager a credential is gone so it removes that passkey from the
|
|
267
|
-
* user's list — the welded-old-wallet auto-cleanup. `credentialId` is base64url.
|
|
268
|
-
* Returns true if fired, false if unsupported/failed.
|
|
269
|
-
*/
|
|
270
|
-
declare function prunePasskey(args: {
|
|
271
|
-
credentialId: string;
|
|
272
|
-
rpId?: string;
|
|
273
|
-
}): Promise<boolean>;
|
|
274
|
-
/**
|
|
275
|
-
* Declare the FULL set of still-valid credential IDs for a user; the manager
|
|
276
|
-
* prunes anything not listed. Use after sign-in or eject to reconcile in one
|
|
277
|
-
* shot (pass `[]` to clear all of a user's passkeys). Returns true if fired.
|
|
278
|
-
*/
|
|
279
|
-
declare function syncAcceptedPasskeys(args: {
|
|
280
|
-
userId: string;
|
|
281
|
-
acceptedCredentialIds: string[];
|
|
282
|
-
rpId?: string;
|
|
283
|
-
}): Promise<boolean>;
|
|
284
|
-
|
|
285
|
-
export { ACTIVE_WALLET_STORAGE_KEY as A, syncAcceptedPasskeys as B, type CreateWalletResult as C, type DexterConnectConfig as D, usdToAtomic as E, type IdentityKind as I, type PasskeyLoginTokens as P, type RecoverWalletConfig as R, type SignInResult as S, type CreateWalletConfig as a, type CeremonyPhase as b, type ConnectVault as c, type RecoverOutcome as d, ConnectError as e, type IdentityInput as f, type PasskeySignalSupport as g, type RecoverVault as h, type ResolvedIdentity as i, SESSION_TTL_30D as j, type SpendPolicy as k, type StoredWallet as l, authoredPolicy as m, createWallet as n, ejectActiveWallet as o, forgetWallet as p, getActiveHandle as q, getCredentialId as r, listWallets as s, passkeySignalSupport as t, prunePasskey as u, renamePasskey as v, resolveIdentity as w, setActiveHandle as x, subscribe as y, switchWallet as z };
|
package/dist/worldid.d.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
2
|
-
import { IDKitResult } from '@worldcoin/idkit';
|
|
3
|
-
|
|
4
|
-
type VerifyPersonhoodPhase = 'loading' | 'ready' | 'rp_error' | 'verified';
|
|
5
|
-
interface VerifyPersonhoodConfig {
|
|
6
|
-
/** World ID app id (`app_…`), from the developer portal. */
|
|
7
|
-
appId: `app_${string}`;
|
|
8
|
-
/** The registered action (e.g. `dexter-credit-root-v2`) — pins the nullifier namespace. */
|
|
9
|
-
action: string;
|
|
10
|
-
/** `production` | `staging`. Default `production`. */
|
|
11
|
-
environment?: 'production' | 'staging';
|
|
12
|
-
/**
|
|
13
|
-
* URL that returns the SERVER-SIGNED RP context as `{ rp_context: RpContext }`.
|
|
14
|
-
* The RP signing key is server-side only (never the browser), so the consumer
|
|
15
|
-
* exposes an endpoint that signs the request and returns just the signed
|
|
16
|
-
* context. Mirrors the capture rig's `/api/rp-context`.
|
|
17
|
-
*/
|
|
18
|
-
rpContextUrl: string;
|
|
19
|
-
/** Optional `fetch` init for the RP-context request (auth headers, etc.). */
|
|
20
|
-
rpContextInit?: RequestInit;
|
|
21
|
-
}
|
|
22
|
-
interface UseVerifyPersonhood {
|
|
23
|
-
phase: VerifyPersonhoodPhase;
|
|
24
|
-
error: string | null;
|
|
25
|
-
result: IDKitResult | null;
|
|
26
|
-
/** Open the World App verification sheet. No-op until phase is 'ready'/'verified'. */
|
|
27
|
-
open: () => void;
|
|
28
|
-
/** The IDKitRequestWidget element to render (null until the RP context loads). */
|
|
29
|
-
widget: ReactElement | null;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Headless hook: manages the RP-context fetch + IDKit lifecycle and hands back
|
|
33
|
-
* the raw proof. Render `widget` and call `open()` from your own UI, or use the
|
|
34
|
-
* turnkey <VerifyPersonhood> below.
|
|
35
|
-
*/
|
|
36
|
-
declare function useVerifyPersonhood(config: VerifyPersonhoodConfig, onProof?: (result: IDKitResult) => void, onError?: (error: Error) => void): UseVerifyPersonhood;
|
|
37
|
-
interface VerifyPersonhoodProps extends VerifyPersonhoodConfig {
|
|
38
|
-
/** Fired with the raw World ID v4 proof the moment verification completes. */
|
|
39
|
-
onProof?: (result: IDKitResult) => void;
|
|
40
|
-
/** Fired with the typed error if RP signing or verification fails. */
|
|
41
|
-
onError?: (error: Error) => void;
|
|
42
|
-
/** Button label when armed. Default "Verify your personhood". */
|
|
43
|
-
label?: string;
|
|
44
|
-
/** Label after a proof is captured. Default "Verify again". */
|
|
45
|
-
verifiedLabel?: string;
|
|
46
|
-
/** 'primary' = filled ember (default), 'secondary' = outline. */
|
|
47
|
-
variant?: 'primary' | 'secondary';
|
|
48
|
-
/** Full-width button. */
|
|
49
|
-
block?: boolean;
|
|
50
|
-
/** Extra className composed after the brand classes. */
|
|
51
|
-
className?: string;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Turnkey "Verify your personhood" element — the personhood sibling of
|
|
55
|
-
* <SignInWithDexter>. Renders the branded DexterButton (loading while the RP
|
|
56
|
-
* context signs server-side) that opens World App; on success hands the raw
|
|
57
|
-
* IDKitResult to `onProof`. Brand voice: no emojis. Themeable via --dx-* vars.
|
|
58
|
-
*/
|
|
59
|
-
declare function VerifyPersonhood(props: VerifyPersonhoodProps): ReactElement;
|
|
60
|
-
|
|
61
|
-
export { type UseVerifyPersonhood, VerifyPersonhood, type VerifyPersonhoodConfig, type VerifyPersonhoodPhase, type VerifyPersonhoodProps, useVerifyPersonhood };
|