@forge-connect/react 1.0.2 → 1.0.3

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/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/provider.tsx
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/provider.tsx
2
2
  var _react = require('react');
3
3
 
4
4
  // src/context.ts
@@ -813,1694 +813,1692 @@ function EmailOtpForm() {
813
813
  // src/components/tabs/wallet-connect.tsx
814
814
 
815
815
 
816
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/bufferToBase64URLString.js
817
- function bufferToBase64URLString(buffer) {
818
- const bytes = new Uint8Array(buffer);
819
- let str = "";
820
- for (const charCode of bytes) {
821
- str += String.fromCharCode(charCode);
816
+ var MOBILE_WALLETS = [
817
+ {
818
+ name: "Phantom",
819
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4IiBoZWlnaHQ9IjEwOCIgdmlld0JveD0iMCAwIDEwOCAxMDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00Ni41MjY3IDY5LjkyMjlDNDIuMDA1NCA3Ni44NTA5IDM0LjQyOTIgODUuNjE4MiAyNC4zNDggODUuNjE4MkMxOS41ODI0IDg1LjYxODIgMTUgODMuNjU2MyAxNSA3NS4xMzQyQzE1IDUzLjQzMDUgNDQuNjMyNiAxOS44MzI3IDcyLjEyNjggMTkuODMyN0M4Ny43NjggMTkuODMyNyA5NCAzMC42ODQ2IDk0IDQzLjAwNzlDOTQgNTguODI1OCA4My43MzU1IDc2LjkxMjIgNzMuNTMyMSA3Ni45MTIyQzcwLjI5MzkgNzYuOTEyMiA2OC43MDUzIDc1LjEzNDIgNjguNzA1MyA3Mi4zMTRDNjguNzA1MyA3MS41NzgzIDY4LjgyNzUgNzAuNzgxMiA2OS4wNzE5IDY5LjkyMjlDNjUuNTg5MyA3NS44Njk5IDU4Ljg2ODUgODEuMzg3OCA1Mi41NzU0IDgxLjM4NzhDNDcuOTkzIDgxLjM4NzggNDUuNjcxMyA3OC41MDYzIDQ1LjY3MTMgNzQuNDU5OEM0NS42NzEzIDcyLjk4ODQgNDUuOTc2OCA3MS40NTU2IDQ2LjUyNjcgNjkuOTIyOVpNODMuNjc2MSA0Mi41Nzk0QzgzLjY3NjEgNDYuMTcwNCA4MS41NTc1IDQ3Ljk2NTggNzkuMTg3NSA0Ny45NjU4Qzc2Ljc4MTYgNDcuOTY1OCA3NC42OTg5IDQ2LjE3MDQgNzQuNjk4OSA0Mi41Nzk0Qzc0LjY5ODkgMzguOTg4NSA3Ni43ODE2IDM3LjE5MzEgNzkuMTg3NSAzNy4xOTMxQzgxLjU1NzUgMzcuMTkzMSA4My42NzYxIDM4Ljk4ODUgODMuNjc2MSA0Mi41Nzk0Wk03MC4yMTAzIDQyLjU3OTVDNzAuMjEwMyA0Ni4xNzA0IDY4LjA5MTYgNDcuOTY1OCA2NS43MjE2IDQ3Ljk2NThDNjMuMzE1NyA0Ny45NjU4IDYxLjIzMyA0Ni4xNzA0IDYxLjIzMyA0Mi41Nzk1QzYxLjIzMyAzOC45ODg1IDYzLjMxNTcgMzcuMTkzMSA2NS43MjE2IDM3LjE5MzFDNjguMDkxNiAzNy4xOTMxIDcwLjIxMDMgMzguOTg4NSA3MC4yMTAzIDQyLjU3OTVaIiBmaWxsPSIjRkZGREY4Ii8+Cjwvc3ZnPgo=",
820
+ buildUrl: (url) => `https://phantom.app/ul/browse/${encodeURIComponent(url)}?ref=${encodeURIComponent(url)}`
821
+ },
822
+ {
823
+ name: "Solflare",
824
+ icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJTIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MCA1MCI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMwMjA1MGE7c3Ryb2tlOiNmZmVmNDY7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOi41cHg7fS5jbHMtMntmaWxsOiNmZmVmNDY7fTwvc3R5bGU+PC9kZWZzPjxyZWN0IGNsYXNzPSJjbHMtMiIgeD0iMCIgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwIiByeD0iMTIiIHJ5PSIxMiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTI0LjIzLDI2LjQybDIuNDYtMi4zOCw0LjU5LDEuNWMzLjAxLDEsNC41MSwyLjg0LDQuNTEsNS40MywwLDEuOTYtLjc1LDMuMjYtMi4yNSw0LjkzbC0uNDYuNS4xNy0xLjE3Yy42Ny00LjI2LS41OC02LjA5LTQuNzItNy40M2wtNC4zLTEuMzhoMFpNMTguMDUsMTEuODVsMTIuNTIsNC4xNy0yLjcxLDIuNTktNi41MS0yLjE3Yy0yLjI1LS43NS0zLjAxLTEuOTYtMy4zLTQuNTF2LS4wOGgwWk0xNy4zLDMzLjA2bDIuODQtMi43MSw1LjM0LDEuNzVjMi44LjkyLDMuNzYsMi4xMywzLjQ2LDUuMThsLTExLjY1LTQuMjJoMFpNMTMuNzEsMjAuOTVjMC0uNzkuNDItMS41NCwxLjEzLTIuMTcuNzUsMS4wOSwyLjA1LDIuMDUsNC4wOSwyLjcxbDQuNDIsMS40Ni0yLjQ2LDIuMzgtNC4zNC0xLjQyYy0yLS42Ny0yLjg0LTEuNjctMi44NC0yLjk2TTI2LjgyLDQyLjg3YzkuMTgtNi4wOSwxNC4xMS0xMC4yMywxNC4xMS0xNS4zMiwwLTMuMzgtMi01LjI2LTYuNDMtNi43MmwtMy4zNC0xLjEzLDkuMTQtOC43Ny0xLjg0LTEuOTYtMi43MSwyLjM4LTEyLjgxLTQuMjJjLTMuOTcsMS4yOS04Ljk3LDUuMDktOC45Nyw4Ljg5LDAsLjQyLjA0LjgzLjE3LDEuMjktMy4zLDEuODgtNC42MywzLjYzLTQuNjMsNS44LDAsMi4wNSwxLjA5LDQuMDksNC41NSw1LjIybDIuNzUuOTItOS41Miw5LjE0LDEuODQsMS45NiwyLjk2LTIuNzEsMTQuNzMsNS4yMmgwWiIvPjwvc3ZnPg==",
825
+ buildUrl: (url) => `https://solflare.com/ul/v1/browse/${encodeURIComponent(url)}?ref=${encodeURIComponent(url)}`
826
+ },
827
+ {
828
+ name: "Backpack",
829
+ icon: "data:image/webp;base64,UklGRlgCAABXRUJQVlA4WAoAAAAQAAAAOwAAOwAAQUxQSC8AAAABL6CmbQOGP75e/cti0oiIOI0KBto2+a8ACZjAAQ7wL2gCSCL6PwER2t+KmZpFDwBWUDggAgIAAPALAJ0BKjwAPAA+SSCMRKKiIRYKrTQoBISyAGp7nL12mKuwHiZ/pX71XoA8m7rXfQA8q39lfhJ/cL0ZimIeNSGxOaSWtqEDDdJ++ARG5/LVm6OquItoAu4rpz8VksUr1NEDJ0CeZucwAP7+VdYX7J5e8V3cJZ9QoY9vj8KsNGOvZSm+khDZOvwCeiDFjGweq/8KIUmVQk3T/qW3ONyMcepN2uwyEXpZZiidST0x705r7ZnNuWX42r8oi+FEshvXGWm6DabjfrMbiaxJ15irl2Gj3nKWbZ2v3k/jd172plSBejBs7dNt90Re/m+nmv5kNjM/SPfa4EpzvOdu/8BR+hTnR4qe4eWhTsh/oecEfN31OExdi/6AYrsth4nlx/qGEP70b1/TNKmgaB/18+c9ntTfhku9wYpy17/wN3r+B/1geZPzth+AtNsMDXE99PaPLWdFP9MOIMD6ME+MpZu2H7WSfzY7MkWs/N/NNzAZ0P/9vMvxgcdzFHvs/doeUU9WyVv+Ll8QDJbn9NZl86ZZNYtfP4Ol1hiJHWosWyj/66vhMUeFIcDheXIOSRTzvKwj5ffEl7fn/QwflNU556SEjM8MriwSFJ/nrFBrr8O1/pqdrYGqPijG6tjsBVBHp+EDAbtNLL375I2jnG9i3Xb1ZphsFYNjdRaknYdFf4g5iJBoAAA=",
830
+ buildUrl: (url) => `https://backpack.app/ul/browse/${encodeURIComponent(url)}`
822
831
  }
823
- const base64String = btoa(str);
824
- return base64String.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
832
+ ];
833
+ function isMobile() {
834
+ if (typeof navigator === "undefined") return false;
835
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
825
836
  }
826
-
827
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/base64URLStringToBuffer.js
828
- function base64URLStringToBuffer(base64URLString) {
829
- const base64 = base64URLString.replace(/-/g, "+").replace(/_/g, "/");
830
- const padLength = (4 - base64.length % 4) % 4;
831
- const padded = base64.padEnd(base64.length + padLength, "=");
832
- const binary = atob(padded);
833
- const buffer = new ArrayBuffer(binary.length);
834
- const bytes = new Uint8Array(buffer);
835
- for (let i = 0; i < binary.length; i++) {
836
- bytes[i] = binary.charCodeAt(i);
837
+ function WalletConnectForm() {
838
+ const { walletAdapter, setModalStep, config } = useForgeConnect();
839
+ const methods = resolveLoginMethods(config);
840
+ const showBack = methods.length > 1;
841
+ if (!walletAdapter && isMobile()) {
842
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MobileWalletFlow, {});
837
843
  }
838
- return buffer;
839
- }
840
-
841
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/browserSupportsWebAuthn.js
842
- function browserSupportsWebAuthn() {
843
- return _browserSupportsWebAuthnInternals.stubThis(_optionalChain([globalThis, 'optionalAccess', _13 => _13.PublicKeyCredential]) !== void 0 && typeof globalThis.PublicKeyCredential === "function");
844
+ if (walletAdapter) {
845
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WalletAdapterFlow, {});
846
+ }
847
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
848
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "fc-tab-title", children: "Connect wallet" }),
849
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "fc-text", children: [
850
+ "No wallet adapter detected. Pass ",
851
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "code", { children: "walletAdapter" }),
852
+ " to",
853
+ " ",
854
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "code", { children: "<ForgeConnectProvider>" }),
855
+ " to enable wallet login."
856
+ ] }),
857
+ showBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
858
+ ] });
844
859
  }
845
- var _browserSupportsWebAuthnInternals = {
846
- stubThis: (value) => value
847
- };
848
-
849
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/toPublicKeyCredentialDescriptor.js
850
- function toPublicKeyCredentialDescriptor(descriptor) {
851
- const { id } = descriptor;
852
- return {
853
- ...descriptor,
854
- id: base64URLStringToBuffer(id),
855
- /**
856
- * `descriptor.transports` is an array of our `AuthenticatorTransportFuture` that includes newer
857
- * transports that TypeScript's DOM lib is ignorant of. Convince TS that our list of transports
858
- * are fine to pass to WebAuthn since browsers will recognize the new value.
859
- */
860
- transports: descriptor.transports
860
+ function MobileWalletFlow() {
861
+ const { setModalStep, config } = useForgeConnect();
862
+ const methods = resolveLoginMethods(config);
863
+ const showBack = methods.length > 1;
864
+ const walletConfig = config.walletConfig;
865
+ const preferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _13 => _13.preferredWallets]), () => ( []));
866
+ const onlyPreferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _14 => _14.onlyPreferred]), () => ( false));
867
+ const walletsToShow = _react.useMemo.call(void 0, () => {
868
+ if (preferred.length > 0) {
869
+ const prefList = preferred.map((name) => MOBILE_WALLETS.find((mw) => mw.name === name)).filter(Boolean);
870
+ if (onlyPreferred) return prefList;
871
+ const prefNames = new Set(preferred);
872
+ const others = MOBILE_WALLETS.filter((mw) => !prefNames.has(mw.name));
873
+ return [...prefList, ...others];
874
+ }
875
+ return MOBILE_WALLETS;
876
+ }, [preferred, onlyPreferred]);
877
+ const handleOpen = (mw) => {
878
+ const pageUrl = window.location.href;
879
+ window.location.href = mw.buildUrl(pageUrl);
861
880
  };
881
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
882
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-wallet-list", children: walletsToShow.map((mw) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
883
+ "button",
884
+ {
885
+ type: "button",
886
+ className: "fc-btn fc-btn-wallet",
887
+ onClick: () => handleOpen(mw),
888
+ children: [
889
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: mw.icon, alt: "", className: "fc-wallet-icon" }) }),
890
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: mw.name }),
891
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-preferred", children: "Open app" })
892
+ ]
893
+ },
894
+ mw.name
895
+ )) }),
896
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", style: { textAlign: "center", fontSize: 12, opacity: 0.6 }, children: "You'll be redirected to the wallet app to sign in." }),
897
+ showBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
898
+ ] });
862
899
  }
863
-
864
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/isValidDomain.js
865
- function isValidDomain(hostname) {
866
- return (
867
- // Consider localhost valid as well since it's okay wrt Secure Contexts
868
- hostname === "localhost" || /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(hostname)
869
- );
870
- }
871
-
872
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/webAuthnError.js
873
- var WebAuthnError = class extends Error {
874
- constructor({ message, code, cause, name }) {
875
- super(message, { cause });
876
- Object.defineProperty(this, "code", {
877
- enumerable: true,
878
- configurable: true,
879
- writable: true,
880
- value: void 0
881
- });
882
- this.name = _nullishCoalesce(name, () => ( cause.name));
883
- this.code = code;
884
- }
885
- };
886
-
887
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/identifyRegistrationError.js
888
- function identifyRegistrationError({ error, options }) {
889
- const { publicKey } = options;
890
- if (!publicKey) {
891
- throw Error("options was missing required publicKey property");
892
- }
893
- if (error.name === "AbortError") {
894
- if (options.signal instanceof AbortSignal) {
895
- return new WebAuthnError({
896
- message: "Registration ceremony was sent an abort signal",
897
- code: "ERROR_CEREMONY_ABORTED",
898
- cause: error
899
- });
900
+ function WalletAdapterFlow() {
901
+ const { walletAdapter, loginWithWallet, setModalStep, config } = useForgeConnect();
902
+ const wallet = walletAdapter;
903
+ const walletConfig = config.walletConfig;
904
+ const methods = resolveLoginMethods(config);
905
+ const showBack = methods.length > 1;
906
+ const [error, setError] = _react.useState.call(void 0, "");
907
+ const [loading, setLoading] = _react.useState.call(void 0, false);
908
+ const [showOther, setShowOther] = _react.useState.call(void 0, false);
909
+ const [coldWallet, setColdWallet] = _react.useState.call(void 0, false);
910
+ const mobile = _react.useMemo.call(void 0, () => isMobile(), []);
911
+ const coldWalletRef = _react.useRef.call(void 0, coldWallet);
912
+ coldWalletRef.current = coldWallet;
913
+ const buildSignTxFnForAdapter = _react.useCallback.call(void 0, (adapter) => {
914
+ if (!adapter.signTransaction) return void 0;
915
+ const TxClass = _optionalChain([walletConfig, 'optionalAccess', _15 => _15.Transaction]);
916
+ if (!TxClass) return void 0;
917
+ return async (txBase64) => {
918
+ const bytes = Uint8Array.from(atob(txBase64), (c) => c.charCodeAt(0));
919
+ const tx = TxClass.from(bytes);
920
+ const signedTx = await adapter.signTransaction(tx);
921
+ return btoa(String.fromCharCode(...new Uint8Array(signedTx.serialize())));
922
+ };
923
+ }, [_optionalChain([walletConfig, 'optionalAccess', _16 => _16.Transaction])]);
924
+ const handleConnect = async (w) => {
925
+ if (w.readyState !== "Installed") {
926
+ if (mobile) {
927
+ const mw = MOBILE_WALLETS.find((m) => m.name === w.adapter.name);
928
+ if (mw) {
929
+ window.location.href = mw.buildUrl(window.location.href);
930
+ return;
931
+ }
932
+ }
933
+ const url = w.adapter.url;
934
+ if (url) window.open(url, "_blank");
935
+ return;
900
936
  }
901
- } else if (error.name === "ConstraintError") {
902
- if (_optionalChain([publicKey, 'access', _14 => _14.authenticatorSelection, 'optionalAccess', _15 => _15.requireResidentKey]) === true) {
903
- return new WebAuthnError({
904
- message: "Discoverable credentials were required but no available authenticator supported it",
905
- code: "ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",
906
- cause: error
907
- });
908
- } else if (
909
- // @ts-ignore: `mediation` doesn't yet exist on CredentialCreationOptions but it's possible as of Sept 2024
910
- options.mediation === "conditional" && _optionalChain([publicKey, 'access', _16 => _16.authenticatorSelection, 'optionalAccess', _17 => _17.userVerification]) === "required"
911
- ) {
912
- return new WebAuthnError({
913
- message: "User verification was required during automatic registration but it could not be performed",
914
- code: "ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",
915
- cause: error
916
- });
917
- } else if (_optionalChain([publicKey, 'access', _18 => _18.authenticatorSelection, 'optionalAccess', _19 => _19.userVerification]) === "required") {
918
- return new WebAuthnError({
919
- message: "User verification was required but no available authenticator supported it",
920
- code: "ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",
921
- cause: error
922
- });
937
+ setError("");
938
+ setLoading(true);
939
+ try {
940
+ if (!w.adapter.connected) {
941
+ await w.adapter.connect();
942
+ }
943
+ const pk = w.adapter.publicKey;
944
+ if (!pk) throw new Error("Wallet did not provide a public key.");
945
+ const address = pk.toBase58();
946
+ const useCold = coldWalletRef.current;
947
+ const adapterSignMessage = w.adapter.signMessage ? (msg) => w.adapter.signMessage(msg) : void 0;
948
+ await loginWithWallet(
949
+ address,
950
+ useCold ? void 0 : adapterSignMessage,
951
+ "solana",
952
+ useCold ? buildSignTxFnForAdapter(w.adapter) : void 0
953
+ );
954
+ } catch (err) {
955
+ setError(err instanceof Error ? err.message : "Could not verify your wallet. Please try again.");
956
+ setLoading(false);
923
957
  }
924
- } else if (error.name === "InvalidStateError") {
925
- return new WebAuthnError({
926
- message: "The authenticator was previously registered",
927
- code: "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",
928
- cause: error
929
- });
930
- } else if (error.name === "NotAllowedError") {
931
- return new WebAuthnError({
932
- message: error.message,
933
- code: "ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",
934
- cause: error
935
- });
936
- } else if (error.name === "NotSupportedError") {
937
- const validPubKeyCredParams = publicKey.pubKeyCredParams.filter((param) => param.type === "public-key");
938
- if (validPubKeyCredParams.length === 0) {
939
- return new WebAuthnError({
940
- message: 'No entry in pubKeyCredParams was of type "public-key"',
941
- code: "ERROR_MALFORMED_PUBKEYCREDPARAMS",
942
- cause: error
943
- });
958
+ };
959
+ const handleMobileOpen = (mw) => {
960
+ window.location.href = mw.buildUrl(window.location.href);
961
+ };
962
+ const preferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _17 => _17.preferredWallets]), () => ( []));
963
+ const onlyPreferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _18 => _18.onlyPreferred]), () => ( false));
964
+ const preferredSet = new Set(preferred);
965
+ const connectedWalletName = wallet.publicKey ? _nullishCoalesce(_optionalChain([wallet, 'access', _19 => _19.wallets, 'access', _20 => _20.find, 'call', _21 => _21((w) => w.adapter.connected), 'optionalAccess', _22 => _22.adapter, 'access', _23 => _23.name]), () => ( null)) : null;
966
+ const { preferredWallets, otherWallets } = _react.useMemo.call(void 0, () => {
967
+ const all = wallet.wallets;
968
+ const prefList = preferred.map((name) => all.find((w) => w.adapter.name === name)).filter(Boolean);
969
+ if (onlyPreferred && preferred.length > 0) {
970
+ return { preferredWallets: prefList, otherWallets: [] };
944
971
  }
945
- return new WebAuthnError({
946
- message: "No available authenticator supported any of the specified pubKeyCredParams algorithms",
947
- code: "ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",
948
- cause: error
949
- });
950
- } else if (error.name === "SecurityError") {
951
- const effectiveDomain = globalThis.location.hostname;
952
- if (!isValidDomain(effectiveDomain)) {
953
- return new WebAuthnError({
954
- message: `${globalThis.location.hostname} is an invalid domain`,
955
- code: "ERROR_INVALID_DOMAIN",
956
- cause: error
957
- });
958
- } else if (publicKey.rp.id !== effectiveDomain) {
959
- return new WebAuthnError({
960
- message: `The RP ID "${publicKey.rp.id}" is invalid for this domain`,
961
- code: "ERROR_INVALID_RP_ID",
962
- cause: error
963
- });
964
- }
965
- } else if (error.name === "TypeError") {
966
- if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) {
967
- return new WebAuthnError({
968
- message: "User ID was not between 1 and 64 characters",
969
- code: "ERROR_INVALID_USER_ID_LENGTH",
970
- cause: error
971
- });
972
- }
973
- } else if (error.name === "UnknownError") {
974
- return new WebAuthnError({
975
- message: "The authenticator was unable to process the specified options, or could not create a new credential",
976
- code: "ERROR_AUTHENTICATOR_GENERAL_ERROR",
977
- cause: error
978
- });
979
- }
980
- return error;
972
+ const others = all.filter(
973
+ (w) => !preferredSet.has(w.adapter.name) && w.readyState === "Installed"
974
+ );
975
+ return { preferredWallets: prefList, otherWallets: others };
976
+ }, [wallet.wallets, walletConfig]);
977
+ const mobileExtraWallets = _react.useMemo.call(void 0, () => {
978
+ if (!mobile) return [];
979
+ const adapterNames = new Set(wallet.wallets.map((w) => w.adapter.name));
980
+ return MOBILE_WALLETS.filter((mw) => !adapterNames.has(mw.name));
981
+ }, [mobile, wallet.wallets]);
982
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
983
+ loading ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { textAlign: "center", padding: "24px 0" }, children: [
984
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-tab-title", children: "Connecting..." }),
985
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: coldWallet ? "Confirm the transaction on your device" : "Approve the connection, then sign the verification request in your wallet" }),
986
+ error && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
987
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error }),
988
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
989
+ "button",
990
+ {
991
+ type: "button",
992
+ className: "fc-btn fc-btn-secondary",
993
+ onClick: () => {
994
+ setLoading(false);
995
+ setError("");
996
+ },
997
+ style: { marginTop: 8 },
998
+ children: "Try again"
999
+ }
1000
+ )
1001
+ ] })
1002
+ ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1003
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-wallet-list", children: [
1004
+ preferredWallets.map((w) => {
1005
+ const installed = w.readyState === "Installed";
1006
+ const isConnected = w.adapter.name === connectedWalletName;
1007
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1008
+ "button",
1009
+ {
1010
+ type: "button",
1011
+ className: "fc-btn fc-btn-wallet",
1012
+ onClick: () => handleConnect(w),
1013
+ children: [
1014
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: installed ? "fc-installed-dot" : "", style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: w.adapter.icon, alt: "", className: "fc-wallet-icon" }) }),
1015
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: w.adapter.name }),
1016
+ isConnected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-preferred", children: "Last used" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-preferred", children: "Preferred" }),
1017
+ !installed && mobile && MOBILE_WALLETS.some((mw) => mw.name === w.adapter.name) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-install", children: "Open app" }) : !installed && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-install", children: "Install" })
1018
+ ]
1019
+ },
1020
+ w.adapter.name
1021
+ );
1022
+ }),
1023
+ mobileExtraWallets.map((mw) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1024
+ "button",
1025
+ {
1026
+ type: "button",
1027
+ className: "fc-btn fc-btn-wallet",
1028
+ onClick: () => handleMobileOpen(mw),
1029
+ children: [
1030
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: mw.icon, alt: "", className: "fc-wallet-icon" }) }),
1031
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: mw.name }),
1032
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-install", children: "Open app" })
1033
+ ]
1034
+ },
1035
+ mw.name
1036
+ )),
1037
+ otherWallets.length > 0 && !showOther && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1038
+ "button",
1039
+ {
1040
+ type: "button",
1041
+ className: "fc-btn fc-btn-wallet",
1042
+ onClick: () => setShowOther(true),
1043
+ children: [
1044
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-other-wallets-icon", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
1045
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "3", width: "16", height: "14", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
1046
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M2 7h16", stroke: "currentColor", strokeWidth: "1.5" }),
1047
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "11", y: "10", width: "7", height: "4", rx: "1", stroke: "currentColor", strokeWidth: "1.5" })
1048
+ ] }) }),
1049
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: "Other wallets" })
1050
+ ]
1051
+ }
1052
+ ),
1053
+ showOther && otherWallets.map((w) => {
1054
+ const isConnected = w.adapter.name === connectedWalletName;
1055
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1056
+ "button",
1057
+ {
1058
+ type: "button",
1059
+ className: "fc-btn fc-btn-wallet",
1060
+ onClick: () => handleConnect(w),
1061
+ children: [
1062
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-installed-dot", style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: w.adapter.icon, alt: "", className: "fc-wallet-icon" }) }),
1063
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: w.adapter.name }),
1064
+ isConnected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-preferred", children: "Last used" })
1065
+ ]
1066
+ },
1067
+ w.adapter.name
1068
+ );
1069
+ })
1070
+ ] }),
1071
+ preferredWallets.length === 0 && otherWallets.length === 0 && mobileExtraWallets.length === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "No wallet found. Please install a Solana wallet (like Phantom) to continue." }),
1072
+ _optionalChain([walletConfig, 'optionalAccess', _24 => _24.Transaction]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-cold-wallet-toggle", children: [
1073
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1074
+ "input",
1075
+ {
1076
+ type: "checkbox",
1077
+ checked: coldWallet,
1078
+ onChange: (e) => setColdWallet(e.target.checked)
1079
+ }
1080
+ ),
1081
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-toggle-track" }),
1082
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "fc-cold-wallet-label", children: [
1083
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Hardware wallet" }),
1084
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Ledger, Trezor, Keystone..." })
1085
+ ] })
1086
+ ] }),
1087
+ error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error })
1088
+ ] }),
1089
+ showBack && !loading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
1090
+ ] });
981
1091
  }
982
1092
 
983
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/webAuthnAbortService.js
984
- var BaseWebAuthnAbortService = class {
985
- constructor() {
986
- Object.defineProperty(this, "controller", {
987
- enumerable: true,
988
- configurable: true,
989
- writable: true,
990
- value: void 0
991
- });
992
- }
993
- createNewAbortSignal() {
994
- if (this.controller) {
995
- const abortError = new Error("Cancelling existing WebAuthn API call for new one");
996
- abortError.name = "AbortError";
997
- this.controller.abort(abortError);
998
- }
999
- const newController = new AbortController();
1000
- this.controller = newController;
1001
- return newController.signal;
1002
- }
1003
- cancelCeremony() {
1004
- if (this.controller) {
1005
- const abortError = new Error("Manually cancelling existing WebAuthn API call");
1006
- abortError.name = "AbortError";
1007
- this.controller.abort(abortError);
1008
- this.controller = void 0;
1009
- }
1010
- }
1011
- };
1012
- var WebAuthnAbortService = new BaseWebAuthnAbortService();
1093
+ // src/components/tabs/forgot-password.tsx
1013
1094
 
1014
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/toAuthenticatorAttachment.js
1015
- var attachments = ["cross-platform", "platform"];
1016
- function toAuthenticatorAttachment(attachment) {
1017
- if (!attachment) {
1018
- return;
1019
- }
1020
- if (attachments.indexOf(attachment) < 0) {
1021
- return;
1022
- }
1023
- return attachment;
1024
- }
1025
1095
 
1026
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/methods/startRegistration.js
1027
- async function startRegistration(options) {
1028
- if (!options.optionsJSON && options.challenge) {
1029
- console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.");
1030
- options = { optionsJSON: options };
1031
- }
1032
- const { optionsJSON, useAutoRegister = false } = options;
1033
- if (!browserSupportsWebAuthn()) {
1034
- throw new Error("WebAuthn is not supported in this browser");
1035
- }
1036
- const publicKey = {
1037
- ...optionsJSON,
1038
- challenge: base64URLStringToBuffer(optionsJSON.challenge),
1039
- user: {
1040
- ...optionsJSON.user,
1041
- id: base64URLStringToBuffer(optionsJSON.user.id)
1042
- },
1043
- excludeCredentials: _optionalChain([optionsJSON, 'access', _20 => _20.excludeCredentials, 'optionalAccess', _21 => _21.map, 'call', _22 => _22(toPublicKeyCredentialDescriptor)])
1044
- };
1045
- const createOptions = {};
1046
- if (useAutoRegister) {
1047
- createOptions.mediation = "conditional";
1048
- }
1049
- createOptions.publicKey = publicKey;
1050
- createOptions.signal = WebAuthnAbortService.createNewAbortSignal();
1051
- let credential;
1052
- try {
1053
- credential = await navigator.credentials.create(createOptions);
1054
- } catch (err) {
1055
- throw identifyRegistrationError({ error: err, options: createOptions });
1056
- }
1057
- if (!credential) {
1058
- throw new Error("Registration was not completed");
1059
- }
1060
- const { id, rawId, response, type } = credential;
1061
- let transports = void 0;
1062
- if (typeof response.getTransports === "function") {
1063
- transports = response.getTransports();
1064
- }
1065
- let responsePublicKeyAlgorithm = void 0;
1066
- if (typeof response.getPublicKeyAlgorithm === "function") {
1067
- try {
1068
- responsePublicKeyAlgorithm = response.getPublicKeyAlgorithm();
1069
- } catch (error) {
1070
- warnOnBrokenImplementation("getPublicKeyAlgorithm()", error);
1071
- }
1072
- }
1073
- let responsePublicKey = void 0;
1074
- if (typeof response.getPublicKey === "function") {
1096
+ function ForgotPasswordForm() {
1097
+ const { forgotPassword, resetPassword, setModalStep } = useForgeConnect();
1098
+ const [step, setStep] = _react.useState.call(void 0, "email");
1099
+ const [email, setEmail] = _react.useState.call(void 0, "");
1100
+ const [token, setToken] = _react.useState.call(void 0, "");
1101
+ const [password, setPassword] = _react.useState.call(void 0, "");
1102
+ const [error, setError] = _react.useState.call(void 0, "");
1103
+ const [loading, setLoading] = _react.useState.call(void 0, false);
1104
+ const handleSendCode = async (e) => {
1105
+ e.preventDefault();
1106
+ setError("");
1107
+ setLoading(true);
1075
1108
  try {
1076
- const _publicKey = response.getPublicKey();
1077
- if (_publicKey !== null) {
1078
- responsePublicKey = bufferToBase64URLString(_publicKey);
1079
- }
1080
- } catch (error) {
1081
- warnOnBrokenImplementation("getPublicKey()", error);
1109
+ await forgotPassword(email);
1110
+ setStep("reset");
1111
+ } catch (err) {
1112
+ setError(err instanceof Error ? err.message : "Could not send the reset code. Please try again.");
1113
+ } finally {
1114
+ setLoading(false);
1082
1115
  }
1083
- }
1084
- let responseAuthenticatorData;
1085
- if (typeof response.getAuthenticatorData === "function") {
1116
+ };
1117
+ const handleReset = async (e) => {
1118
+ e.preventDefault();
1119
+ setError("");
1120
+ setLoading(true);
1086
1121
  try {
1087
- responseAuthenticatorData = bufferToBase64URLString(response.getAuthenticatorData());
1088
- } catch (error) {
1089
- warnOnBrokenImplementation("getAuthenticatorData()", error);
1122
+ await resetPassword(token.trim(), password);
1123
+ setStep("done");
1124
+ } catch (err) {
1125
+ setError(err instanceof Error ? err.message : "Could not reset your password. Please try again.");
1126
+ } finally {
1127
+ setLoading(false);
1090
1128
  }
1091
- }
1092
- return {
1093
- id,
1094
- rawId: bufferToBase64URLString(rawId),
1095
- response: {
1096
- attestationObject: bufferToBase64URLString(response.attestationObject),
1097
- clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
1098
- transports,
1099
- publicKeyAlgorithm: responsePublicKeyAlgorithm,
1100
- publicKey: responsePublicKey,
1101
- authenticatorData: responseAuthenticatorData
1102
- },
1103
- type,
1104
- clientExtensionResults: credential.getClientExtensionResults(),
1105
- authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment)
1106
1129
  };
1107
- }
1108
- function warnOnBrokenImplementation(methodName, cause) {
1109
- console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${methodName}. You should report this error to them.
1110
- `, cause);
1111
- }
1112
-
1113
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/browserSupportsWebAuthnAutofill.js
1114
- function browserSupportsWebAuthnAutofill() {
1115
- if (!browserSupportsWebAuthn()) {
1116
- return _browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
1130
+ if (step === "done") {
1131
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1132
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "fc-tab-title", children: "Password updated" }),
1133
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Your password has been reset. You can now sign in." }),
1134
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-primary", onClick: () => setModalStep("email-login"), children: "Sign in" })
1135
+ ] });
1117
1136
  }
1118
- const globalPublicKeyCredential = globalThis.PublicKeyCredential;
1119
- if (_optionalChain([globalPublicKeyCredential, 'optionalAccess', _23 => _23.isConditionalMediationAvailable]) === void 0) {
1120
- return _browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
1137
+ if (step === "reset") {
1138
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1139
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "fc-tab-title", children: "Set new password" }),
1140
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "fc-text", children: [
1141
+ "We sent a reset code to ",
1142
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: email }),
1143
+ ". Paste it below with your new password."
1144
+ ] }),
1145
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: handleReset, className: "fc-form", children: [
1146
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-label", children: [
1147
+ "Reset code",
1148
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1149
+ "input",
1150
+ {
1151
+ type: "text",
1152
+ className: "fc-input",
1153
+ value: token,
1154
+ onChange: (e) => setToken(e.target.value),
1155
+ placeholder: "Paste the code from your email",
1156
+ required: true,
1157
+ autoComplete: "off"
1158
+ }
1159
+ )
1160
+ ] }),
1161
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-label", children: [
1162
+ "New password",
1163
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1164
+ "input",
1165
+ {
1166
+ type: "password",
1167
+ className: "fc-input",
1168
+ value: password,
1169
+ onChange: (e) => setPassword(e.target.value),
1170
+ placeholder: "8+ characters",
1171
+ required: true,
1172
+ autoComplete: "new-password",
1173
+ minLength: 8
1174
+ }
1175
+ )
1176
+ ] }),
1177
+ error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error }),
1178
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading, children: loading ? "Resetting..." : "Reset password" })
1179
+ ] }),
1180
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setStep("email"), children: "Resend code" }) })
1181
+ ] });
1121
1182
  }
1122
- return _browserSupportsWebAuthnAutofillInternals.stubThis(globalPublicKeyCredential.isConditionalMediationAvailable());
1183
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1184
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "fc-tab-title", children: "Reset your password" }),
1185
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Enter your email and we'll send you a reset code." }),
1186
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: handleSendCode, className: "fc-form", children: [
1187
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-label", children: [
1188
+ "Email",
1189
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1190
+ "input",
1191
+ {
1192
+ type: "email",
1193
+ className: "fc-input",
1194
+ value: email,
1195
+ onChange: (e) => setEmail(e.target.value),
1196
+ placeholder: "you@example.com",
1197
+ required: true,
1198
+ autoComplete: "email"
1199
+ }
1200
+ )
1201
+ ] }),
1202
+ error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error }),
1203
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading, children: loading ? "Sending..." : "Send reset code" })
1204
+ ] }),
1205
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setModalStep("email-login"), children: "Back to sign in" }) })
1206
+ ] });
1123
1207
  }
1124
- var _browserSupportsWebAuthnAutofillInternals = {
1125
- stubThis: (value) => value
1126
- };
1127
1208
 
1128
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/identifyAuthenticationError.js
1129
- function identifyAuthenticationError({ error, options }) {
1130
- const { publicKey } = options;
1131
- if (!publicKey) {
1132
- throw Error("options was missing required publicKey property");
1133
- }
1134
- if (error.name === "AbortError") {
1135
- if (options.signal instanceof AbortSignal) {
1136
- return new WebAuthnError({
1137
- message: "Authentication ceremony was sent an abort signal",
1138
- code: "ERROR_CEREMONY_ABORTED",
1139
- cause: error
1140
- });
1209
+ // src/components/tabs/verify-2fa.tsx
1210
+
1211
+
1212
+ function Verify2FAForm() {
1213
+ const { verify2FA, verifyRecoveryCode, setModalStep } = useForgeConnect();
1214
+ const [code, setCode] = _react.useState.call(void 0, "");
1215
+ const [loading, setLoading] = _react.useState.call(void 0, false);
1216
+ const [error, setError] = _react.useState.call(void 0, "");
1217
+ const [useRecovery, setUseRecovery] = _react.useState.call(void 0, false);
1218
+ const inputRef = _react.useRef.call(void 0, null);
1219
+ const submittingRef = _react.useRef.call(void 0, false);
1220
+ _react.useEffect.call(void 0, () => {
1221
+ _optionalChain([inputRef, 'access', _25 => _25.current, 'optionalAccess', _26 => _26.focus, 'call', _27 => _27()]);
1222
+ }, [useRecovery]);
1223
+ const submitCode = _react.useCallback.call(void 0, async (codeValue, isRecovery) => {
1224
+ if (submittingRef.current || !codeValue.trim()) return;
1225
+ submittingRef.current = true;
1226
+ setLoading(true);
1227
+ setError("");
1228
+ try {
1229
+ if (isRecovery) {
1230
+ await verifyRecoveryCode(codeValue.trim());
1231
+ } else {
1232
+ await verify2FA(codeValue.trim());
1233
+ }
1234
+ } catch (err) {
1235
+ setError(err instanceof Error ? err.message : "Verification failed. Please try again.");
1236
+ } finally {
1237
+ setLoading(false);
1238
+ submittingRef.current = false;
1141
1239
  }
1142
- } else if (error.name === "NotAllowedError") {
1143
- return new WebAuthnError({
1144
- message: error.message,
1145
- code: "ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",
1146
- cause: error
1147
- });
1148
- } else if (error.name === "SecurityError") {
1149
- const effectiveDomain = globalThis.location.hostname;
1150
- if (!isValidDomain(effectiveDomain)) {
1151
- return new WebAuthnError({
1152
- message: `${globalThis.location.hostname} is an invalid domain`,
1153
- code: "ERROR_INVALID_DOMAIN",
1154
- cause: error
1155
- });
1156
- } else if (publicKey.rpId !== effectiveDomain) {
1157
- return new WebAuthnError({
1158
- message: `The RP ID "${publicKey.rpId}" is invalid for this domain`,
1159
- code: "ERROR_INVALID_RP_ID",
1160
- cause: error
1161
- });
1240
+ }, [verify2FA, verifyRecoveryCode]);
1241
+ const handleSubmit = async (e) => {
1242
+ _optionalChain([e, 'optionalAccess', _28 => _28.preventDefault, 'call', _29 => _29()]);
1243
+ await submitCode(code, useRecovery);
1244
+ };
1245
+ const handleCodeChange = (value) => {
1246
+ setCode(value);
1247
+ if (!useRecovery && value.length === 6 && /^\d{6}$/.test(value)) {
1248
+ submitCode(value, false);
1162
1249
  }
1163
- } else if (error.name === "UnknownError") {
1164
- return new WebAuthnError({
1165
- message: "The authenticator was unable to process the specified options, or could not create a new assertion signature",
1166
- code: "ERROR_AUTHENTICATOR_GENERAL_ERROR",
1167
- cause: error
1168
- });
1169
- }
1170
- return error;
1250
+ };
1251
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1252
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-back", onClick: () => setModalStep("method-select"), children: [
1253
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 12L6 8l4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
1254
+ "Back"
1255
+ ] }),
1256
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { marginTop: 8 }, children: useRecovery ? "Enter one of your recovery codes." : "Enter the 6-digit code from your authenticator app." }),
1257
+ error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error }),
1258
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: handleSubmit, className: "fc-form", children: [
1259
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1260
+ "input",
1261
+ {
1262
+ ref: inputRef,
1263
+ className: "fc-input fc-input-code",
1264
+ type: "text",
1265
+ inputMode: useRecovery ? "text" : "numeric",
1266
+ autoComplete: "one-time-code",
1267
+ placeholder: useRecovery ? "Recovery code" : "000000",
1268
+ maxLength: useRecovery ? 20 : 6,
1269
+ value: code,
1270
+ onChange: (e) => handleCodeChange(e.target.value),
1271
+ style: useRecovery ? {} : { textAlign: "center", letterSpacing: "0.3em", fontSize: "1.25rem" }
1272
+ }
1273
+ ),
1274
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading || !code.trim(), children: loading ? "Verifying..." : "Verify" })
1275
+ ] }),
1276
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1277
+ "button",
1278
+ {
1279
+ type: "button",
1280
+ className: "fc-link",
1281
+ onClick: () => {
1282
+ setUseRecovery(!useRecovery);
1283
+ setCode("");
1284
+ setError("");
1285
+ },
1286
+ style: { marginTop: 12 },
1287
+ children: useRecovery ? "Use authenticator code instead" : "Use a recovery code"
1288
+ }
1289
+ )
1290
+ ] });
1171
1291
  }
1172
1292
 
1173
- // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/methods/startAuthentication.js
1174
- async function startAuthentication(options) {
1175
- if (!options.optionsJSON && options.challenge) {
1176
- console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.");
1177
- options = { optionsJSON: options };
1178
- }
1179
- const { optionsJSON, useBrowserAutofill = false, verifyBrowserAutofillInput = true } = options;
1180
- if (!browserSupportsWebAuthn()) {
1181
- throw new Error("WebAuthn is not supported in this browser");
1182
- }
1183
- let allowCredentials;
1184
- if (_optionalChain([optionsJSON, 'access', _24 => _24.allowCredentials, 'optionalAccess', _25 => _25.length]) !== 0) {
1185
- allowCredentials = _optionalChain([optionsJSON, 'access', _26 => _26.allowCredentials, 'optionalAccess', _27 => _27.map, 'call', _28 => _28(toPublicKeyCredentialDescriptor)]);
1186
- }
1187
- const publicKey = {
1188
- ...optionsJSON,
1189
- challenge: base64URLStringToBuffer(optionsJSON.challenge),
1190
- allowCredentials
1191
- };
1192
- const getOptions = {};
1193
- if (useBrowserAutofill) {
1194
- if (!await browserSupportsWebAuthnAutofill()) {
1195
- throw Error("Browser does not support WebAuthn autofill");
1196
- }
1197
- const eligibleInputs = document.querySelectorAll("input[autocomplete$='webauthn']");
1198
- if (eligibleInputs.length < 1 && verifyBrowserAutofillInput) {
1199
- throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');
1293
+ // src/components/svg-icon.tsx
1294
+
1295
+
1296
+ function SvgIcon({ svg, className }) {
1297
+ const ref = _react.useRef.call(void 0, null);
1298
+ _react.useEffect.call(void 0, () => {
1299
+ if (!ref.current || !svg) return;
1300
+ try {
1301
+ const doc = new DOMParser().parseFromString(svg, "text/html");
1302
+ const svgEl = doc.body.querySelector("svg");
1303
+ if (!svgEl) {
1304
+ ref.current.textContent = "";
1305
+ return;
1306
+ }
1307
+ const dangerous = svgEl.querySelectorAll("script,iframe,object,embed,foreignObject");
1308
+ dangerous.forEach((el) => el.remove());
1309
+ const all = svgEl.querySelectorAll("*");
1310
+ all.forEach((el) => {
1311
+ for (const attr of Array.from(el.attributes)) {
1312
+ if (attr.name.startsWith("on")) {
1313
+ el.removeAttribute(attr.name);
1314
+ }
1315
+ }
1316
+ });
1317
+ ref.current.textContent = "";
1318
+ ref.current.appendChild(svgEl);
1319
+ } catch (e5) {
1320
+ ref.current.textContent = "";
1200
1321
  }
1201
- getOptions.mediation = "conditional";
1202
- publicKey.allowCredentials = [];
1203
- }
1204
- getOptions.publicKey = publicKey;
1205
- getOptions.signal = WebAuthnAbortService.createNewAbortSignal();
1206
- let credential;
1207
- try {
1208
- credential = await navigator.credentials.get(getOptions);
1209
- } catch (err) {
1210
- throw identifyAuthenticationError({ error: err, options: getOptions });
1211
- }
1212
- if (!credential) {
1213
- throw new Error("Authentication was not completed");
1214
- }
1215
- const { id, rawId, response, type } = credential;
1216
- let userHandle = void 0;
1217
- if (response.userHandle) {
1218
- userHandle = bufferToBase64URLString(response.userHandle);
1219
- }
1220
- return {
1221
- id,
1222
- rawId: bufferToBase64URLString(rawId),
1223
- response: {
1224
- authenticatorData: bufferToBase64URLString(response.authenticatorData),
1225
- clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
1226
- signature: bufferToBase64URLString(response.signature),
1227
- userHandle
1228
- },
1229
- type,
1230
- clientExtensionResults: credential.getClientExtensionResults(),
1231
- authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment)
1232
- };
1322
+ }, [svg]);
1323
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { ref, className });
1233
1324
  }
1234
1325
 
1235
- // src/runtime-imports.ts
1236
- var importSolanaWeb3 = () => Promise.resolve().then(() => _interopRequireWildcard(require("@solana/web3.js")));
1237
-
1238
- // src/components/tabs/wallet-connect.tsx
1326
+ // src/components/tabs/oauth-buttons.tsx
1239
1327
 
1240
- var MOBILE_WALLETS = [
1241
- {
1242
- name: "Phantom",
1243
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4IiBoZWlnaHQ9IjEwOCIgdmlld0JveD0iMCAwIDEwOCAxMDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00Ni41MjY3IDY5LjkyMjlDNDIuMDA1NCA3Ni44NTA5IDM0LjQyOTIgODUuNjE4MiAyNC4zNDggODUuNjE4MkMxOS41ODI0IDg1LjYxODIgMTUgODMuNjU2MyAxNSA3NS4xMzQyQzE1IDUzLjQzMDUgNDQuNjMyNiAxOS44MzI3IDcyLjEyNjggMTkuODMyN0M4Ny43NjggMTkuODMyNyA5NCAzMC42ODQ2IDk0IDQzLjAwNzlDOTQgNTguODI1OCA4My43MzU1IDc2LjkxMjIgNzMuNTMyMSA3Ni45MTIyQzcwLjI5MzkgNzYuOTEyMiA2OC43MDUzIDc1LjEzNDIgNjguNzA1MyA3Mi4zMTRDNjguNzA1MyA3MS41NzgzIDY4LjgyNzUgNzAuNzgxMiA2OS4wNzE5IDY5LjkyMjlDNjUuNTg5MyA3NS44Njk5IDU4Ljg2ODUgODEuMzg3OCA1Mi41NzU0IDgxLjM4NzhDNDcuOTkzIDgxLjM4NzggNDUuNjcxMyA3OC41MDYzIDQ1LjY3MTMgNzQuNDU5OEM0NS42NzEzIDcyLjk4ODQgNDUuOTc2OCA3MS40NTU2IDQ2LjUyNjcgNjkuOTIyOVpNODMuNjc2MSA0Mi41Nzk0QzgzLjY3NjEgNDYuMTcwNCA4MS41NTc1IDQ3Ljk2NTggNzkuMTg3NSA0Ny45NjU4Qzc2Ljc4MTYgNDcuOTY1OCA3NC42OTg5IDQ2LjE3MDQgNzQuNjk4OSA0Mi41Nzk0Qzc0LjY5ODkgMzguOTg4NSA3Ni43ODE2IDM3LjE5MzEgNzkuMTg3NSAzNy4xOTMxQzgxLjU1NzUgMzcuMTkzMSA4My42NzYxIDM4Ljk4ODUgODMuNjc2MSA0Mi41Nzk0Wk03MC4yMTAzIDQyLjU3OTVDNzAuMjEwMyA0Ni4xNzA0IDY4LjA5MTYgNDcuOTY1OCA2NS43MjE2IDQ3Ljk2NThDNjMuMzE1NyA0Ny45NjU4IDYxLjIzMyA0Ni4xNzA0IDYxLjIzMyA0Mi41Nzk1QzYxLjIzMyAzOC45ODg1IDYzLjMxNTcgMzcuMTkzMSA2NS43MjE2IDM3LjE5MzFDNjguMDkxNiAzNy4xOTMxIDcwLjIxMDMgMzguOTg4NSA3MC4yMTAzIDQyLjU3OTVaIiBmaWxsPSIjRkZGREY4Ii8+Cjwvc3ZnPgo=",
1244
- buildUrl: (url) => `https://phantom.app/ul/browse/${encodeURIComponent(url)}?ref=${encodeURIComponent(url)}`
1328
+ var PROVIDER_INFO = {
1329
+ google: {
1330
+ label: "Google",
1331
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/></svg>'
1245
1332
  },
1246
- {
1247
- name: "Solflare",
1248
- icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJTIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MCA1MCI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiMwMjA1MGE7c3Ryb2tlOiNmZmVmNDY7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOi41cHg7fS5jbHMtMntmaWxsOiNmZmVmNDY7fTwvc3R5bGU+PC9kZWZzPjxyZWN0IGNsYXNzPSJjbHMtMiIgeD0iMCIgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwIiByeD0iMTIiIHJ5PSIxMiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTI0LjIzLDI2LjQybDIuNDYtMi4zOCw0LjU5LDEuNWMzLjAxLDEsNC41MSwyLjg0LDQuNTEsNS40MywwLDEuOTYtLjc1LDMuMjYtMi4yNSw0LjkzbC0uNDYuNS4xNy0xLjE3Yy42Ny00LjI2LS41OC02LjA5LTQuNzItNy40M2wtNC4zLTEuMzhoMFpNMTguMDUsMTEuODVsMTIuNTIsNC4xNy0yLjcxLDIuNTktNi41MS0yLjE3Yy0yLjI1LS43NS0zLjAxLTEuOTYtMy4zLTQuNTF2LS4wOGgwWk0xNy4zLDMzLjA2bDIuODQtMi43MSw1LjM0LDEuNzVjMi44LjkyLDMuNzYsMi4xMywzLjQ2LDUuMThsLTExLjY1LTQuMjJoMFpNMTMuNzEsMjAuOTVjMC0uNzkuNDItMS41NCwxLjEzLTIuMTcuNzUsMS4wOSwyLjA1LDIuMDUsNC4wOSwyLjcxbDQuNDIsMS40Ni0yLjQ2LDIuMzgtNC4zNC0xLjQyYy0yLS42Ny0yLjg0LTEuNjctMi44NC0yLjk2TTI2LjgyLDQyLjg3YzkuMTgtNi4wOSwxNC4xMS0xMC4yMywxNC4xMS0xNS4zMiwwLTMuMzgtMi01LjI2LTYuNDMtNi43MmwtMy4zNC0xLjEzLDkuMTQtOC43Ny0xLjg0LTEuOTYtMi43MSwyLjM4LTEyLjgxLTQuMjJjLTMuOTcsMS4yOS04Ljk3LDUuMDktOC45Nyw4Ljg5LDAsLjQyLjA0LjgzLjE3LDEuMjktMy4zLDEuODgtNC42MywzLjYzLTQuNjMsNS44LDAsMi4wNSwxLjA5LDQuMDksNC41NSw1LjIybDIuNzUuOTItOS41Miw5LjE0LDEuODQsMS45NiwyLjk2LTIuNzEsMTQuNzMsNS4yMmgwWiIvPjwvc3ZnPg==",
1249
- buildUrl: (url) => `https://solflare.com/ul/v1/browse/${encodeURIComponent(url)}?ref=${encodeURIComponent(url)}`
1333
+ discord: {
1334
+ label: "Discord",
1335
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.126-.094.252-.192.372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z" fill="#5865F2"/></svg>'
1250
1336
  },
1251
- {
1252
- name: "Backpack",
1253
- icon: "data:image/webp;base64,UklGRlgCAABXRUJQVlA4WAoAAAAQAAAAOwAAOwAAQUxQSC8AAAABL6CmbQOGP75e/cti0oiIOI0KBto2+a8ACZjAAQ7wL2gCSCL6PwER2t+KmZpFDwBWUDggAgIAAPALAJ0BKjwAPAA+SSCMRKKiIRYKrTQoBISyAGp7nL12mKuwHiZ/pX71XoA8m7rXfQA8q39lfhJ/cL0ZimIeNSGxOaSWtqEDDdJ++ARG5/LVm6OquItoAu4rpz8VksUr1NEDJ0CeZucwAP7+VdYX7J5e8V3cJZ9QoY9vj8KsNGOvZSm+khDZOvwCeiDFjGweq/8KIUmVQk3T/qW3ONyMcepN2uwyEXpZZiidST0x705r7ZnNuWX42r8oi+FEshvXGWm6DabjfrMbiaxJ15irl2Gj3nKWbZ2v3k/jd172plSBejBs7dNt90Re/m+nmv5kNjM/SPfa4EpzvOdu/8BR+hTnR4qe4eWhTsh/oecEfN31OExdi/6AYrsth4nlx/qGEP70b1/TNKmgaB/18+c9ntTfhku9wYpy17/wN3r+B/1geZPzth+AtNsMDXE99PaPLWdFP9MOIMD6ME+MpZu2H7WSfzY7MkWs/N/NNzAZ0P/9vMvxgcdzFHvs/doeUU9WyVv+Ll8QDJbn9NZl86ZZNYtfP4Ol1hiJHWosWyj/66vhMUeFIcDheXIOSRTzvKwj5ffEl7fn/QwflNU556SEjM8MriwSFJ/nrFBrr8O1/pqdrYGqPijG6tjsBVBHp+EDAbtNLL375I2jnG9i3Xb1ZphsFYNjdRaknYdFf4g5iJBoAAA=",
1254
- buildUrl: (url) => `https://backpack.app/ul/browse/${encodeURIComponent(url)}`
1255
- }
1256
- ];
1257
- function isMobile() {
1258
- if (typeof navigator === "undefined") return false;
1259
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1260
- }
1261
- function WalletConnectForm() {
1262
- const { walletAdapter, setModalStep, config } = useForgeConnect();
1263
- const methods = resolveLoginMethods(config);
1264
- const showBack = methods.length > 1;
1265
- if (!walletAdapter && isMobile()) {
1266
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MobileWalletFlow, {});
1267
- }
1268
- if (walletAdapter) {
1269
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WalletAdapterFlow, {});
1337
+ twitter: {
1338
+ label: "Twitter",
1339
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" fill="currentColor"/></svg>'
1340
+ },
1341
+ apple: {
1342
+ label: "Apple",
1343
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.52-3.23 0-1.44.64-2.2.45-3.06-.4C3.79 16.17 4.36 9.02 8.8 8.78c1.27.06 2.15.72 2.91.76.93-.19 1.82-.88 2.83-.8 1.21.1 2.12.58 2.72 1.49-2.46 1.48-1.88 4.73.52 5.64-.42 1.13-.98 2.24-1.73 3.41zM12.03 8.7c-.12-2.35 1.82-4.38 4.04-4.54.29 2.56-2.34 4.68-4.04 4.54z" fill="currentColor"/></svg>'
1344
+ },
1345
+ telegram: {
1346
+ label: "Telegram",
1347
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z" fill="#2AABEE"/></svg>'
1270
1348
  }
1271
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1272
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "fc-tab-title", children: "Connect wallet" }),
1273
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "fc-text", children: [
1274
- "No wallet adapter detected. Pass ",
1275
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "code", { children: "walletAdapter" }),
1276
- " to",
1277
- " ",
1278
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "code", { children: "<ForgeConnectProvider>" }),
1279
- " to enable wallet login."
1280
- ] }),
1281
- showBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
1282
- ] });
1349
+ };
1350
+ function OAuthButton({ provider }) {
1351
+ const { loginWithOAuth } = useForgeConnect();
1352
+ const info = PROVIDER_INFO[provider];
1353
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1354
+ "button",
1355
+ {
1356
+ type: "button",
1357
+ className: "fc-btn fc-btn-oauth",
1358
+ onClick: () => loginWithOAuth(provider),
1359
+ children: [
1360
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SvgIcon, { svg: info.icon, className: "fc-oauth-icon" }),
1361
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: info.label })
1362
+ ]
1363
+ }
1364
+ );
1283
1365
  }
1284
- function MobileWalletFlow() {
1285
- const { setModalStep, config } = useForgeConnect();
1286
- const methods = resolveLoginMethods(config);
1287
- const showBack = methods.length > 1;
1288
- const walletConfig = config.walletConfig;
1289
- const preferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _29 => _29.preferredWallets]), () => ( []));
1290
- const onlyPreferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _30 => _30.onlyPreferred]), () => ( false));
1291
- const walletsToShow = _react.useMemo.call(void 0, () => {
1292
- if (preferred.length > 0) {
1293
- const prefList = preferred.map((name) => MOBILE_WALLETS.find((mw) => mw.name === name)).filter(Boolean);
1294
- if (onlyPreferred) return prefList;
1295
- const prefNames = new Set(preferred);
1296
- const others = MOBILE_WALLETS.filter((mw) => !prefNames.has(mw.name));
1297
- return [...prefList, ...others];
1366
+
1367
+ // src/components/login-modal.tsx
1368
+
1369
+ function LoginModal() {
1370
+ const { modal, closeModal, config } = useForgeConnect();
1371
+ const renderStep = () => {
1372
+ switch (modal.step) {
1373
+ case "email-login":
1374
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmailLoginForm, {});
1375
+ case "email-register":
1376
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmailRegisterForm, {});
1377
+ case "email-otp":
1378
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmailOtpForm, {});
1379
+ case "wallet-connect":
1380
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WalletConnectForm, {});
1381
+ case "forgot-password":
1382
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ForgotPasswordForm, {});
1383
+ case "verify-2fa":
1384
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Verify2FAForm, {});
1385
+ case "oauth":
1386
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OAuthLoadingView, {});
1387
+ case "success":
1388
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SuccessView, {});
1389
+ case "method-select":
1390
+ default:
1391
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MethodSelect, {});
1298
1392
  }
1299
- return MOBILE_WALLETS;
1300
- }, [preferred, onlyPreferred]);
1301
- const handleOpen = (mw) => {
1302
- const pageUrl = window.location.href;
1303
- window.location.href = mw.buildUrl(pageUrl);
1304
1393
  };
1305
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1306
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-wallet-list", children: walletsToShow.map((mw) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1307
- "button",
1308
- {
1309
- type: "button",
1310
- className: "fc-btn fc-btn-wallet",
1311
- onClick: () => handleOpen(mw),
1312
- children: [
1313
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: mw.icon, alt: "", className: "fc-wallet-icon" }) }),
1314
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: mw.name }),
1315
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-preferred", children: "Open app" })
1316
- ]
1394
+ const renderLogo = () => {
1395
+ if (_optionalChain([config, 'access', _30 => _30.appearance, 'optionalAccess', _31 => _31.logoNode])) {
1396
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-logo", children: config.appearance.logoNode });
1397
+ }
1398
+ if (_optionalChain([config, 'access', _32 => _32.appearance, 'optionalAccess', _33 => _33.logo])) {
1399
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: config.appearance.logo, alt: "", className: "fc-logo" });
1400
+ }
1401
+ return null;
1402
+ };
1403
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ModalOverlay, { isOpen: modal.isOpen, onClose: closeModal, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1404
+ "div",
1405
+ {
1406
+ className: "fc-modal-content",
1407
+ style: {
1408
+ "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _34 => _34.appearance, 'optionalAccess', _35 => _35.accentColor]), () => ( "#8b5cf6"))
1317
1409
  },
1318
- mw.name
1319
- )) }),
1320
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", style: { textAlign: "center", fontSize: 12, opacity: 0.6 }, children: "You'll be redirected to the wallet app to sign in." }),
1321
- showBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
1322
- ] });
1410
+ "data-theme": _nullishCoalesce(_optionalChain([config, 'access', _36 => _36.appearance, 'optionalAccess', _37 => _37.theme]), () => ( "light")),
1411
+ children: modal.step === "success" || modal.step === "oauth" ? renderStep() : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1412
+ renderLogo(),
1413
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: _nullishCoalesce(_optionalChain([config, 'access', _38 => _38.appearance, 'optionalAccess', _39 => _39.title]), () => ( "Log in or sign up")) }),
1414
+ renderStep(),
1415
+ (_optionalChain([config, 'access', _40 => _40.appearance, 'optionalAccess', _41 => _41.termsUrl]) || _optionalChain([config, 'access', _42 => _42.appearance, 'optionalAccess', _43 => _43.privacyUrl])) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "fc-legal", children: [
1416
+ "By continuing, you agree to our",
1417
+ " ",
1418
+ config.appearance.termsUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href: config.appearance.termsUrl, target: "_blank", rel: "noopener noreferrer", className: "fc-legal-link", children: "Terms" }),
1419
+ config.appearance.termsUrl && config.appearance.privacyUrl && " and ",
1420
+ config.appearance.privacyUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href: config.appearance.privacyUrl, target: "_blank", rel: "noopener noreferrer", className: "fc-legal-link", children: "Privacy Policy" })
1421
+ ] })
1422
+ ] })
1423
+ }
1424
+ ) });
1323
1425
  }
1324
- function WalletAdapterFlow() {
1325
- const { walletAdapter, loginWithWallet, setModalStep, config } = useForgeConnect();
1326
- const wallet = walletAdapter;
1327
- const walletConfig = config.walletConfig;
1426
+ var EmailIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon", children: [
1427
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "4", width: "16", height: "12", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
1428
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M2 6l8 5 8-5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
1429
+ ] }) });
1430
+ var OtpIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon", children: [
1431
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "3", y: "6", width: "14", height: "9", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
1432
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "6.5", cy: "10.5", r: "1", fill: "currentColor" }),
1433
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "10.5", r: "1", fill: "currentColor" }),
1434
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "13.5", cy: "10.5", r: "1", fill: "currentColor" })
1435
+ ] }) });
1436
+ var WalletIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon", children: [
1437
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "5", width: "16", height: "11", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
1438
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "13", y: "9", width: "5", height: "3", rx: "1", stroke: "currentColor", strokeWidth: "1.5" })
1439
+ ] }) });
1440
+ var PasskeyIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon", children: [
1441
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "8", cy: "7", r: "3", stroke: "currentColor", strokeWidth: "1.5" }),
1442
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M13 13.5a5 5 0 0 0-10 0", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1443
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M15 10v4m0 0l-1.5-1m1.5 1l1.5-1", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1444
+ ] }) });
1445
+ var LoadingSpinner = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon fc-spin", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 2a8 8 0 0 1 8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) });
1446
+ function MethodSelect() {
1447
+ const { setModalStep, loginWithPasskey, config } = useForgeConnect();
1328
1448
  const methods = resolveLoginMethods(config);
1329
- const showBack = methods.length > 1;
1330
- const [error, setError] = _react.useState.call(void 0, "");
1331
- const [loading, setLoading] = _react.useState.call(void 0, false);
1332
- const [showOther, setShowOther] = _react.useState.call(void 0, false);
1333
- const [coldWallet, setColdWallet] = _react.useState.call(void 0, false);
1334
- const mobile = _react.useMemo.call(void 0, () => isMobile(), []);
1335
- const coldWalletRef = _react.useRef.call(void 0, coldWallet);
1336
- coldWalletRef.current = coldWallet;
1337
- const buildSignTxFnForAdapter = _react.useCallback.call(void 0, (adapter) => {
1338
- if (!adapter.signTransaction) return void 0;
1339
- return async (txBase64) => {
1340
- const { Transaction } = await importSolanaWeb3();
1341
- const bytes = Uint8Array.from(atob(txBase64), (c) => c.charCodeAt(0));
1342
- const tx = Transaction.from(bytes);
1343
- const signedTx = await adapter.signTransaction(tx);
1344
- return btoa(String.fromCharCode(...new Uint8Array(signedTx.serialize())));
1345
- };
1346
- }, []);
1347
- const handleConnect = async (w) => {
1348
- if (w.readyState !== "Installed") {
1349
- if (mobile) {
1350
- const mw = MOBILE_WALLETS.find((m) => m.name === w.adapter.name);
1351
- if (mw) {
1352
- window.location.href = mw.buildUrl(window.location.href);
1353
- return;
1354
- }
1355
- }
1356
- const url = w.adapter.url;
1357
- if (url) window.open(url, "_blank");
1358
- return;
1359
- }
1360
- setError("");
1361
- setLoading(true);
1449
+ const [passkeyLoading, setPasskeyLoading] = _react.useState.call(void 0, false);
1450
+ const [passkeyError, setPasskeyError] = _react.useState.call(void 0, "");
1451
+ const handlePasskey = async () => {
1452
+ setPasskeyLoading(true);
1453
+ setPasskeyError("");
1362
1454
  try {
1363
- if (!w.adapter.connected) {
1364
- await w.adapter.connect();
1365
- }
1366
- const pk = w.adapter.publicKey;
1367
- if (!pk) throw new Error("Wallet did not provide a public key.");
1368
- const address = pk.toBase58();
1369
- const useCold = coldWalletRef.current;
1370
- const adapterSignMessage = w.adapter.signMessage ? (msg) => w.adapter.signMessage(msg) : void 0;
1371
- await loginWithWallet(
1372
- address,
1373
- useCold ? void 0 : adapterSignMessage,
1374
- "solana",
1375
- useCold ? buildSignTxFnForAdapter(w.adapter) : void 0
1376
- );
1455
+ await loginWithPasskey();
1377
1456
  } catch (err) {
1378
- setError(err instanceof Error ? err.message : "Could not verify your wallet. Please try again.");
1379
- setLoading(false);
1457
+ setPasskeyError(err instanceof Error ? err.message : "Passkey authentication failed.");
1458
+ } finally {
1459
+ setPasskeyLoading(false);
1380
1460
  }
1381
1461
  };
1382
- const handleMobileOpen = (mw) => {
1383
- window.location.href = mw.buildUrl(window.location.href);
1384
- };
1385
- const preferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _31 => _31.preferredWallets]), () => ( []));
1386
- const onlyPreferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _32 => _32.onlyPreferred]), () => ( false));
1387
- const preferredSet = new Set(preferred);
1388
- const connectedWalletName = wallet.publicKey ? _nullishCoalesce(_optionalChain([wallet, 'access', _33 => _33.wallets, 'access', _34 => _34.find, 'call', _35 => _35((w) => w.adapter.connected), 'optionalAccess', _36 => _36.adapter, 'access', _37 => _37.name]), () => ( null)) : null;
1389
- const { preferredWallets, otherWallets } = _react.useMemo.call(void 0, () => {
1390
- const all = wallet.wallets;
1391
- const prefList = preferred.map((name) => all.find((w) => w.adapter.name === name)).filter(Boolean);
1392
- if (onlyPreferred && preferred.length > 0) {
1393
- return { preferredWallets: prefList, otherWallets: [] };
1394
- }
1395
- const others = all.filter(
1396
- (w) => !preferredSet.has(w.adapter.name) && w.readyState === "Installed"
1397
- );
1398
- return { preferredWallets: prefList, otherWallets: others };
1399
- }, [wallet.wallets, walletConfig]);
1400
- const mobileExtraWallets = _react.useMemo.call(void 0, () => {
1401
- if (!mobile) return [];
1402
- const adapterNames = new Set(wallet.wallets.map((w) => w.adapter.name));
1403
- return MOBILE_WALLETS.filter((mw) => !adapterNames.has(mw.name));
1404
- }, [mobile, wallet.wallets]);
1405
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1406
- loading ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { textAlign: "center", padding: "24px 0" }, children: [
1407
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-tab-title", children: "Connecting..." }),
1408
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: coldWallet ? "Confirm the transaction on your device" : "Approve the connection, then sign the verification request in your wallet" }),
1409
- error && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1410
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error }),
1411
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1412
- "button",
1413
- {
1414
- type: "button",
1415
- className: "fc-btn fc-btn-secondary",
1416
- onClick: () => {
1417
- setLoading(false);
1418
- setError("");
1419
- },
1420
- style: { marginTop: 8 },
1421
- children: "Try again"
1422
- }
1423
- )
1424
- ] })
1425
- ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1426
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-wallet-list", children: [
1427
- preferredWallets.map((w) => {
1428
- const installed = w.readyState === "Installed";
1429
- const isConnected = w.adapter.name === connectedWalletName;
1430
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1431
- "button",
1432
- {
1433
- type: "button",
1434
- className: "fc-btn fc-btn-wallet",
1435
- onClick: () => handleConnect(w),
1436
- children: [
1437
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: installed ? "fc-installed-dot" : "", style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: w.adapter.icon, alt: "", className: "fc-wallet-icon" }) }),
1438
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: w.adapter.name }),
1439
- isConnected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-preferred", children: "Last used" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-preferred", children: "Preferred" }),
1440
- !installed && mobile && MOBILE_WALLETS.some((mw) => mw.name === w.adapter.name) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-install", children: "Open app" }) : !installed && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-install", children: "Install" })
1441
- ]
1442
- },
1443
- w.adapter.name
1462
+ const elements = [];
1463
+ let i = 0;
1464
+ while (i < methods.length) {
1465
+ const method = methods[i];
1466
+ if (isOAuthMethod(method)) {
1467
+ const oauthGroup = [];
1468
+ while (i < methods.length && isOAuthMethod(methods[i])) {
1469
+ oauthGroup.push(methods[i]);
1470
+ i++;
1471
+ }
1472
+ if (elements.length > 0) {
1473
+ elements.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-divider", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "or" }) }, `div-before-${oauthGroup[0]}`));
1474
+ }
1475
+ elements.push(
1476
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-oauth-group", children: oauthGroup.map((p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OAuthButton, { provider: p }, p)) }, `oauth-${oauthGroup.join("-")}`)
1477
+ );
1478
+ } else {
1479
+ if (elements.length > 0) {
1480
+ const prev = methods[i - 1];
1481
+ if (prev && isOAuthMethod(prev)) {
1482
+ elements.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-divider", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "or" }) }, `div-after-${prev}`));
1483
+ }
1484
+ }
1485
+ switch (method) {
1486
+ case "email":
1487
+ elements.push(
1488
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-method", onClick: () => setModalStep("email-login"), children: [
1489
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmailIcon, {}),
1490
+ " ",
1491
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: "Password" })
1492
+ ] }, "email")
1444
1493
  );
1445
- }),
1446
- mobileExtraWallets.map((mw) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1447
- "button",
1448
- {
1449
- type: "button",
1450
- className: "fc-btn fc-btn-wallet",
1451
- onClick: () => handleMobileOpen(mw),
1452
- children: [
1453
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: mw.icon, alt: "", className: "fc-wallet-icon" }) }),
1454
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: mw.name }),
1455
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-install", children: "Open app" })
1456
- ]
1457
- },
1458
- mw.name
1459
- )),
1460
- otherWallets.length > 0 && !showOther && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1461
- "button",
1462
- {
1463
- type: "button",
1464
- className: "fc-btn fc-btn-wallet",
1465
- onClick: () => setShowOther(true),
1466
- children: [
1467
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-other-wallets-icon", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
1468
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "3", width: "16", height: "14", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
1469
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M2 7h16", stroke: "currentColor", strokeWidth: "1.5" }),
1470
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "11", y: "10", width: "7", height: "4", rx: "1", stroke: "currentColor", strokeWidth: "1.5" })
1471
- ] }) }),
1472
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: "Other wallets" })
1473
- ]
1474
- }
1475
- ),
1476
- showOther && otherWallets.map((w) => {
1477
- const isConnected = w.adapter.name === connectedWalletName;
1478
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1479
- "button",
1480
- {
1481
- type: "button",
1482
- className: "fc-btn fc-btn-wallet",
1483
- onClick: () => handleConnect(w),
1484
- children: [
1485
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-installed-dot", style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: w.adapter.icon, alt: "", className: "fc-wallet-icon" }) }),
1486
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-wallet-name", children: w.adapter.name }),
1487
- isConnected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-preferred", children: "Last used" })
1488
- ]
1489
- },
1490
- w.adapter.name
1494
+ break;
1495
+ case "otp":
1496
+ elements.push(
1497
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-method", onClick: () => setModalStep("email-otp"), children: [
1498
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OtpIcon, {}),
1499
+ " ",
1500
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: "Magic code" })
1501
+ ] }, "otp")
1491
1502
  );
1492
- })
1493
- ] }),
1494
- preferredWallets.length === 0 && otherWallets.length === 0 && mobileExtraWallets.length === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "No wallet found. Please install a Solana wallet (like Phantom) to continue." }),
1495
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-cold-wallet-toggle", children: [
1496
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1497
- "input",
1498
- {
1499
- type: "checkbox",
1500
- checked: coldWallet,
1501
- onChange: (e) => setColdWallet(e.target.checked)
1502
- }
1503
- ),
1504
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-toggle-track" }),
1505
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "fc-cold-wallet-label", children: [
1506
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Hardware wallet" }),
1507
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Ledger, Trezor, Keystone..." })
1508
- ] })
1509
- ] }),
1510
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error })
1511
- ] }),
1512
- showBack && !loading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
1503
+ break;
1504
+ case "wallet":
1505
+ elements.push(
1506
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-method", onClick: () => setModalStep("wallet-connect"), children: [
1507
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WalletIcon, {}),
1508
+ " ",
1509
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: "Wallet" })
1510
+ ] }, "wallet")
1511
+ );
1512
+ break;
1513
+ case "passkey":
1514
+ elements.push(
1515
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-method", onClick: handlePasskey, disabled: passkeyLoading, children: [
1516
+ passkeyLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSpinner, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PasskeyIcon, {}),
1517
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: passkeyLoading ? "Waiting for passkey..." : "Passkey" })
1518
+ ] }, "passkey")
1519
+ );
1520
+ break;
1521
+ }
1522
+ i++;
1523
+ }
1524
+ }
1525
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-method-select", children: [
1526
+ passkeyError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: passkeyError }),
1527
+ elements
1528
+ ] });
1529
+ }
1530
+ function OAuthLoadingView() {
1531
+ const { setModalStep } = useForgeConnect();
1532
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-success", children: [
1533
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-success-icon", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "52", height: "52", viewBox: "0 0 52 52", className: "fc-spin", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "26", cy: "26", r: "24", fill: "none", stroke: "var(--fc-accent, #8b5cf6)", strokeWidth: "3", strokeLinecap: "round", strokeDasharray: "100", strokeDashoffset: "30" }) }) }),
1534
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-success-text", children: "Completing sign in..." }),
1535
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-secondary", style: { marginTop: "16px" }, onClick: () => setModalStep("method-select"), children: "Cancel" })
1536
+ ] });
1537
+ }
1538
+ function SuccessView() {
1539
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-success", children: [
1540
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-success-icon", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { viewBox: "0 0 52 52", className: "fc-success-check", children: [
1541
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { className: "fc-success-circle", cx: "26", cy: "26", r: "24", fill: "none" }),
1542
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { className: "fc-success-tick", fill: "none", d: "M15 26l7.5 7.5L37 19" })
1543
+ ] }) }),
1544
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-success-text", children: "You're in" })
1513
1545
  ] });
1514
1546
  }
1515
1547
 
1516
- // src/components/tabs/forgot-password.tsx
1548
+ // src/components/account-modal.tsx
1517
1549
 
1518
1550
 
1519
- function ForgotPasswordForm() {
1520
- const { forgotPassword, resetPassword, setModalStep } = useForgeConnect();
1521
- const [step, setStep] = _react.useState.call(void 0, "email");
1522
- const [email, setEmail] = _react.useState.call(void 0, "");
1523
- const [token, setToken] = _react.useState.call(void 0, "");
1524
- const [password, setPassword] = _react.useState.call(void 0, "");
1525
- const [error, setError] = _react.useState.call(void 0, "");
1551
+ // src/hooks/use-user.ts
1552
+
1553
+ function useUser() {
1554
+ const { auth, api, config, getAccessToken } = useForgeConnect();
1555
+ const [authMethods, setAuthMethods] = _react.useState.call(void 0, null);
1526
1556
  const [loading, setLoading] = _react.useState.call(void 0, false);
1527
- const handleSendCode = async (e) => {
1528
- e.preventDefault();
1529
- setError("");
1557
+ const pendingRefreshRef = _react.useRef.call(void 0, false);
1558
+ const updateProfile = _react.useCallback.call(void 0,
1559
+ async (data) => {
1560
+ const token = getAccessToken();
1561
+ if (!token) throw new Error("Please sign in to continue.");
1562
+ return api.updateMe(token, data);
1563
+ },
1564
+ [api, getAccessToken]
1565
+ );
1566
+ const fetchAuthMethods = _react.useCallback.call(void 0, async () => {
1567
+ const token = getAccessToken();
1568
+ if (!token) throw new Error("Please sign in to continue.");
1530
1569
  setLoading(true);
1531
1570
  try {
1532
- await forgotPassword(email);
1533
- setStep("reset");
1534
- } catch (err) {
1535
- setError(err instanceof Error ? err.message : "Could not send the reset code. Please try again.");
1571
+ const methods = await api.getAuthMethods(token);
1572
+ setAuthMethods(methods);
1573
+ return methods;
1536
1574
  } finally {
1537
1575
  setLoading(false);
1538
1576
  }
1577
+ }, [api, getAccessToken]);
1578
+ const linkAuthMethod = _react.useCallback.call(void 0,
1579
+ async (data) => {
1580
+ const token = getAccessToken();
1581
+ if (!token) throw new Error("Please sign in to continue.");
1582
+ await api.linkAuthMethod(token, data);
1583
+ await fetchAuthMethods();
1584
+ },
1585
+ [api, getAccessToken, fetchAuthMethods]
1586
+ );
1587
+ const linkOtpSend = _react.useCallback.call(void 0,
1588
+ async (email) => {
1589
+ const token = getAccessToken();
1590
+ if (!token) throw new Error("Please sign in to continue.");
1591
+ await api.linkOtpSend(token, email);
1592
+ },
1593
+ [api, getAccessToken]
1594
+ );
1595
+ const linkOtpVerify = _react.useCallback.call(void 0,
1596
+ async (email, code) => {
1597
+ const token = getAccessToken();
1598
+ if (!token) throw new Error("Please sign in to continue.");
1599
+ await api.linkOtpVerify(token, email, code);
1600
+ await fetchAuthMethods();
1601
+ },
1602
+ [api, getAccessToken, fetchAuthMethods]
1603
+ );
1604
+ const unlinkAuthMethod = _react.useCallback.call(void 0,
1605
+ async (id) => {
1606
+ const token = getAccessToken();
1607
+ if (!token) throw new Error("Please sign in to continue.");
1608
+ await api.unlinkAuthMethod(token, id);
1609
+ await fetchAuthMethods();
1610
+ },
1611
+ [api, getAccessToken, fetchAuthMethods]
1612
+ );
1613
+ const linkOAuth = _react.useCallback.call(void 0,
1614
+ async (provider) => {
1615
+ const token = getAccessToken();
1616
+ if (!token) throw new Error("Please sign in to continue.");
1617
+ const { intentToken } = await api.createLinkIntent(token);
1618
+ const redirectUri = encodeURIComponent(window.location.origin + "/fc-oauth-callback");
1619
+ const url = `${config.apiUrl}/auth/oauth/${provider}/link?intent=${encodeURIComponent(intentToken)}&redirect_uri=${redirectUri}`;
1620
+ const width = 500;
1621
+ const height = 600;
1622
+ const left = window.screenX + (window.innerWidth - width) / 2;
1623
+ const top = window.screenY + (window.innerHeight - height) / 2;
1624
+ window.open(url, "fc_oauth_link", `width=${width},height=${height},left=${left},top=${top}`);
1625
+ pendingRefreshRef.current = true;
1626
+ },
1627
+ [api, config.apiUrl, getAccessToken]
1628
+ );
1629
+ _react.useEffect.call(void 0, () => {
1630
+ const handleMessage = (event) => {
1631
+ if (event.origin !== window.location.origin) return;
1632
+ if (_optionalChain([event, 'access', _44 => _44.data, 'optionalAccess', _45 => _45.type]) === "fc_oauth_link_success" && pendingRefreshRef.current) {
1633
+ pendingRefreshRef.current = false;
1634
+ fetchAuthMethods().catch(() => {
1635
+ });
1636
+ }
1637
+ };
1638
+ window.addEventListener("message", handleMessage);
1639
+ return () => window.removeEventListener("message", handleMessage);
1640
+ }, [fetchAuthMethods]);
1641
+ return {
1642
+ user: auth.user,
1643
+ authMethods,
1644
+ loading,
1645
+ updateProfile,
1646
+ fetchAuthMethods,
1647
+ linkAuthMethod,
1648
+ linkOtpSend,
1649
+ linkOtpVerify,
1650
+ unlinkAuthMethod,
1651
+ linkOAuth
1539
1652
  };
1540
- const handleReset = async (e) => {
1541
- e.preventDefault();
1542
- setError("");
1543
- setLoading(true);
1544
- try {
1545
- await resetPassword(token.trim(), password);
1546
- setStep("done");
1547
- } catch (err) {
1548
- setError(err instanceof Error ? err.message : "Could not reset your password. Please try again.");
1549
- } finally {
1550
- setLoading(false);
1653
+ }
1654
+
1655
+ // src/hooks/use-wallets.ts
1656
+
1657
+
1658
+ // src/lib/utils.ts
1659
+ var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
1660
+ function uint8ArrayToBase58(bytes) {
1661
+ const digits = [0];
1662
+ for (const byte of bytes) {
1663
+ let carry = byte;
1664
+ for (let j = 0; j < digits.length; j++) {
1665
+ carry += digits[j] << 8;
1666
+ digits[j] = carry % 58;
1667
+ carry = carry / 58 | 0;
1668
+ }
1669
+ while (carry > 0) {
1670
+ digits.push(carry % 58);
1671
+ carry = carry / 58 | 0;
1551
1672
  }
1552
- };
1553
- if (step === "done") {
1554
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1555
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "fc-tab-title", children: "Password updated" }),
1556
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Your password has been reset. You can now sign in." }),
1557
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-primary", onClick: () => setModalStep("email-login"), children: "Sign in" })
1558
- ] });
1559
1673
  }
1560
- if (step === "reset") {
1561
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1562
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "fc-tab-title", children: "Set new password" }),
1563
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "fc-text", children: [
1564
- "We sent a reset code to ",
1565
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: email }),
1566
- ". Paste it below with your new password."
1567
- ] }),
1568
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: handleReset, className: "fc-form", children: [
1569
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-label", children: [
1570
- "Reset code",
1571
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1572
- "input",
1573
- {
1574
- type: "text",
1575
- className: "fc-input",
1576
- value: token,
1577
- onChange: (e) => setToken(e.target.value),
1578
- placeholder: "Paste the code from your email",
1579
- required: true,
1580
- autoComplete: "off"
1581
- }
1582
- )
1583
- ] }),
1584
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-label", children: [
1585
- "New password",
1586
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1587
- "input",
1588
- {
1589
- type: "password",
1590
- className: "fc-input",
1591
- value: password,
1592
- onChange: (e) => setPassword(e.target.value),
1593
- placeholder: "8+ characters",
1594
- required: true,
1595
- autoComplete: "new-password",
1596
- minLength: 8
1597
- }
1598
- )
1599
- ] }),
1600
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error }),
1601
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading, children: loading ? "Resetting..." : "Reset password" })
1602
- ] }),
1603
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setStep("email"), children: "Resend code" }) })
1604
- ] });
1674
+ let str = "";
1675
+ for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
1676
+ str += "1";
1605
1677
  }
1606
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1607
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "fc-tab-title", children: "Reset your password" }),
1608
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Enter your email and we'll send you a reset code." }),
1609
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: handleSendCode, className: "fc-form", children: [
1610
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-label", children: [
1611
- "Email",
1612
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1613
- "input",
1614
- {
1615
- type: "email",
1616
- className: "fc-input",
1617
- value: email,
1618
- onChange: (e) => setEmail(e.target.value),
1619
- placeholder: "you@example.com",
1620
- required: true,
1621
- autoComplete: "email"
1622
- }
1623
- )
1624
- ] }),
1625
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error }),
1626
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading, children: loading ? "Sending..." : "Send reset code" })
1627
- ] }),
1628
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-switch", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setModalStep("email-login"), children: "Back to sign in" }) })
1629
- ] });
1678
+ for (let i = digits.length - 1; i >= 0; i--) {
1679
+ str += BASE58_ALPHABET[digits[i]];
1680
+ }
1681
+ return str;
1682
+ }
1683
+ function timeAgo(dateStr) {
1684
+ const now = Date.now();
1685
+ const then = new Date(dateStr).getTime();
1686
+ const diff = now - then;
1687
+ const mins = Math.floor(diff / 6e4);
1688
+ if (mins < 1) return "just now";
1689
+ if (mins < 60) return `${mins}m ago`;
1690
+ const hours = Math.floor(mins / 60);
1691
+ if (hours < 24) return `${hours}h ago`;
1692
+ const days = Math.floor(hours / 24);
1693
+ if (days < 30) return `${days}d ago`;
1694
+ return new Date(dateStr).toLocaleDateString();
1630
1695
  }
1631
1696
 
1632
- // src/components/tabs/verify-2fa.tsx
1633
-
1634
-
1635
- function Verify2FAForm() {
1636
- const { verify2FA, verifyRecoveryCode, setModalStep } = useForgeConnect();
1637
- const [code, setCode] = _react.useState.call(void 0, "");
1697
+ // src/hooks/use-wallets.ts
1698
+ function useWallets() {
1699
+ const { api, getAccessToken } = useForgeConnect();
1700
+ const [wallets, setWallets] = _react.useState.call(void 0, null);
1638
1701
  const [loading, setLoading] = _react.useState.call(void 0, false);
1639
- const [error, setError] = _react.useState.call(void 0, "");
1640
- const [useRecovery, setUseRecovery] = _react.useState.call(void 0, false);
1641
- const inputRef = _react.useRef.call(void 0, null);
1642
- const submittingRef = _react.useRef.call(void 0, false);
1643
- _react.useEffect.call(void 0, () => {
1644
- _optionalChain([inputRef, 'access', _38 => _38.current, 'optionalAccess', _39 => _39.focus, 'call', _40 => _40()]);
1645
- }, [useRecovery]);
1646
- const submitCode = _react.useCallback.call(void 0, async (codeValue, isRecovery) => {
1647
- if (submittingRef.current || !codeValue.trim()) return;
1648
- submittingRef.current = true;
1702
+ const fetchWallets = _react.useCallback.call(void 0, async () => {
1703
+ const token = getAccessToken();
1704
+ if (!token) throw new Error("Please sign in to continue.");
1649
1705
  setLoading(true);
1650
- setError("");
1651
1706
  try {
1652
- if (isRecovery) {
1653
- await verifyRecoveryCode(codeValue.trim());
1654
- } else {
1655
- await verify2FA(codeValue.trim());
1656
- }
1657
- } catch (err) {
1658
- setError(err instanceof Error ? err.message : "Verification failed. Please try again.");
1707
+ const data = await api.getWallets(token);
1708
+ setWallets(data);
1709
+ return data;
1659
1710
  } finally {
1660
1711
  setLoading(false);
1661
- submittingRef.current = false;
1662
- }
1663
- }, [verify2FA, verifyRecoveryCode]);
1664
- const handleSubmit = async (e) => {
1665
- _optionalChain([e, 'optionalAccess', _41 => _41.preventDefault, 'call', _42 => _42()]);
1666
- await submitCode(code, useRecovery);
1667
- };
1668
- const handleCodeChange = (value) => {
1669
- setCode(value);
1670
- if (!useRecovery && value.length === 6 && /^\d{6}$/.test(value)) {
1671
- submitCode(value, false);
1672
1712
  }
1673
- };
1674
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1675
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-back", onClick: () => setModalStep("method-select"), children: [
1676
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 12L6 8l4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
1677
- "Back"
1678
- ] }),
1679
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { marginTop: 8 }, children: useRecovery ? "Enter one of your recovery codes." : "Enter the 6-digit code from your authenticator app." }),
1680
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: error }),
1681
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: handleSubmit, className: "fc-form", children: [
1682
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1683
- "input",
1684
- {
1685
- ref: inputRef,
1686
- className: "fc-input fc-input-code",
1687
- type: "text",
1688
- inputMode: useRecovery ? "text" : "numeric",
1689
- autoComplete: "one-time-code",
1690
- placeholder: useRecovery ? "Recovery code" : "000000",
1691
- maxLength: useRecovery ? 20 : 6,
1692
- value: code,
1693
- onChange: (e) => handleCodeChange(e.target.value),
1694
- style: useRecovery ? {} : { textAlign: "center", letterSpacing: "0.3em", fontSize: "1.25rem" }
1713
+ }, [api, getAccessToken]);
1714
+ const updateWallet = _react.useCallback.call(void 0,
1715
+ async (id, data) => {
1716
+ const token = getAccessToken();
1717
+ if (!token) throw new Error("Please sign in to continue.");
1718
+ await api.updateWallet(token, id, data);
1719
+ await fetchWallets();
1720
+ },
1721
+ [api, getAccessToken, fetchWallets]
1722
+ );
1723
+ const linkWallet = _react.useCallback.call(void 0,
1724
+ async (walletAddress, signMessage, chain = "solana", signTransaction) => {
1725
+ const token = getAccessToken();
1726
+ if (!token) throw new Error("Please sign in to continue.");
1727
+ if (signMessage) {
1728
+ const { challengeId, message: challengeMessage } = await api.walletChallenge(walletAddress, chain);
1729
+ const encoded = new TextEncoder().encode(challengeMessage);
1730
+ const signatureBytes = await signMessage(encoded);
1731
+ const signature = chain === "solana" ? uint8ArrayToBase58(signatureBytes) : Array.from(signatureBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1732
+ await api.linkAuthMethod(token, {
1733
+ provider: `${chain}_wallet`,
1734
+ challengeId,
1735
+ signature,
1736
+ walletAddress
1737
+ });
1738
+ } else {
1739
+ if (!signTransaction) {
1740
+ throw new Error("Wallet does not support message signing or transaction signing.");
1695
1741
  }
1696
- ),
1697
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading || !code.trim(), children: loading ? "Verifying..." : "Verify" })
1698
- ] }),
1699
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1700
- "button",
1701
- {
1702
- type: "button",
1703
- className: "fc-link",
1704
- onClick: () => {
1705
- setUseRecovery(!useRecovery);
1706
- setCode("");
1707
- setError("");
1708
- },
1709
- style: { marginTop: 12 },
1710
- children: useRecovery ? "Use authenticator code instead" : "Use a recovery code"
1742
+ const { challengeId, transaction: txBase64 } = await api.walletChallengeTx(walletAddress, chain);
1743
+ const signedTxBase64 = await signTransaction(txBase64);
1744
+ await api.linkAuthMethod(token, {
1745
+ provider: `${chain}_wallet_tx`,
1746
+ challengeId,
1747
+ signedTransaction: signedTxBase64,
1748
+ walletAddress
1749
+ });
1711
1750
  }
1712
- )
1713
- ] });
1751
+ await fetchWallets();
1752
+ },
1753
+ [api, getAccessToken, fetchWallets]
1754
+ );
1755
+ return {
1756
+ wallets,
1757
+ loading,
1758
+ fetchWallets,
1759
+ updateWallet,
1760
+ linkWallet
1761
+ };
1714
1762
  }
1715
1763
 
1716
- // src/components/svg-icon.tsx
1717
-
1764
+ // src/hooks/use-sessions.ts
1718
1765
 
1719
- function SvgIcon({ svg, className }) {
1720
- const ref = _react.useRef.call(void 0, null);
1721
- _react.useEffect.call(void 0, () => {
1722
- if (!ref.current || !svg) return;
1766
+ function useSessions() {
1767
+ const { api, getAccessToken } = useForgeConnect();
1768
+ const [sessions, setSessions] = _react.useState.call(void 0, null);
1769
+ const [loading, setLoading] = _react.useState.call(void 0, false);
1770
+ const fetchSessions = _react.useCallback.call(void 0, async () => {
1771
+ const token = getAccessToken();
1772
+ if (!token) throw new Error("Please sign in to continue.");
1773
+ setLoading(true);
1723
1774
  try {
1724
- const doc = new DOMParser().parseFromString(svg, "text/html");
1725
- const svgEl = doc.body.querySelector("svg");
1726
- if (!svgEl) {
1727
- ref.current.textContent = "";
1728
- return;
1729
- }
1730
- const dangerous = svgEl.querySelectorAll("script,iframe,object,embed,foreignObject");
1731
- dangerous.forEach((el) => el.remove());
1732
- const all = svgEl.querySelectorAll("*");
1733
- all.forEach((el) => {
1734
- for (const attr of Array.from(el.attributes)) {
1735
- if (attr.name.startsWith("on")) {
1736
- el.removeAttribute(attr.name);
1737
- }
1738
- }
1739
- });
1740
- ref.current.textContent = "";
1741
- ref.current.appendChild(svgEl);
1742
- } catch (e5) {
1743
- ref.current.textContent = "";
1775
+ const data = await api.getSessions(token);
1776
+ setSessions(data);
1777
+ return data;
1778
+ } finally {
1779
+ setLoading(false);
1744
1780
  }
1745
- }, [svg]);
1746
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { ref, className });
1781
+ }, [api, getAccessToken]);
1782
+ const revokeSession = _react.useCallback.call(void 0,
1783
+ async (id) => {
1784
+ const token = getAccessToken();
1785
+ if (!token) throw new Error("Please sign in to continue.");
1786
+ await api.revokeSession(token, id);
1787
+ await fetchSessions();
1788
+ },
1789
+ [api, getAccessToken, fetchSessions]
1790
+ );
1791
+ return {
1792
+ sessions,
1793
+ loading,
1794
+ fetchSessions,
1795
+ revokeSession
1796
+ };
1747
1797
  }
1748
1798
 
1749
- // src/components/tabs/oauth-buttons.tsx
1799
+ // src/components/two-factor-modal.tsx
1750
1800
 
1751
- var PROVIDER_INFO = {
1752
- google: {
1753
- label: "Google",
1754
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/></svg>'
1755
- },
1756
- discord: {
1757
- label: "Discord",
1758
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.126-.094.252-.192.372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z" fill="#5865F2"/></svg>'
1759
- },
1760
- twitter: {
1761
- label: "Twitter",
1762
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" fill="currentColor"/></svg>'
1763
- },
1764
- apple: {
1765
- label: "Apple",
1766
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.52-3.23 0-1.44.64-2.2.45-3.06-.4C3.79 16.17 4.36 9.02 8.8 8.78c1.27.06 2.15.72 2.91.76.93-.19 1.82-.88 2.83-.8 1.21.1 2.12.58 2.72 1.49-2.46 1.48-1.88 4.73.52 5.64-.42 1.13-.98 2.24-1.73 3.41zM12.03 8.7c-.12-2.35 1.82-4.38 4.04-4.54.29 2.56-2.34 4.68-4.04 4.54z" fill="currentColor"/></svg>'
1767
- },
1768
- telegram: {
1769
- label: "Telegram",
1770
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z" fill="#2AABEE"/></svg>'
1771
- }
1772
- };
1773
- function OAuthButton({ provider }) {
1774
- const { loginWithOAuth } = useForgeConnect();
1775
- const info = PROVIDER_INFO[provider];
1776
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1777
- "button",
1778
- {
1779
- type: "button",
1780
- className: "fc-btn fc-btn-oauth",
1781
- onClick: () => loginWithOAuth(provider),
1782
- children: [
1783
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SvgIcon, { svg: info.icon, className: "fc-oauth-icon" }),
1784
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: info.label })
1785
- ]
1801
+
1802
+ function TwoFactorModal({ isOpen, onClose, initialEnabled, onStatusChange }) {
1803
+ const { api, getAccessToken, config } = useForgeConnect();
1804
+ const theme = _nullishCoalesce(_optionalChain([config, 'access', _46 => _46.appearance, 'optionalAccess', _47 => _47.theme]), () => ( "light"));
1805
+ const [step, setStep] = _react.useState.call(void 0, initialEnabled ? "manage" : "setup");
1806
+ const [setupData, setSetupData] = _react.useState.call(void 0, null);
1807
+ const [code, setCode] = _react.useState.call(void 0, "");
1808
+ const [loading, setLoading] = _react.useState.call(void 0, false);
1809
+ const [msg, setMsg] = _react.useState.call(void 0, null);
1810
+ const [showSecret, setShowSecret] = _react.useState.call(void 0, false);
1811
+ const [recoveryCodes, setRecoveryCodes] = _react.useState.call(void 0, []);
1812
+ _react.useEffect.call(void 0, () => {
1813
+ if (isOpen) {
1814
+ setStep(initialEnabled ? "manage" : "setup");
1815
+ setSetupData(null);
1816
+ setCode("");
1817
+ setMsg(null);
1818
+ setLoading(false);
1819
+ setShowSecret(false);
1820
+ setRecoveryCodes([]);
1821
+ if (!initialEnabled) {
1822
+ const token = getAccessToken();
1823
+ if (token) {
1824
+ setLoading(true);
1825
+ api.setup2FA(token).then((data) => {
1826
+ setSetupData(data);
1827
+ setRecoveryCodes(data.recoveryCodes);
1828
+ }).catch((err) => {
1829
+ setMsg({ text: err instanceof Error ? err.message : "Could not set up 2FA.", ok: false });
1830
+ }).finally(() => setLoading(false));
1831
+ }
1832
+ }
1786
1833
  }
1787
- );
1788
- }
1789
-
1790
- // src/components/login-modal.tsx
1791
-
1792
- function LoginModal() {
1793
- const { modal, closeModal, config } = useForgeConnect();
1794
- const renderStep = () => {
1795
- switch (modal.step) {
1796
- case "email-login":
1797
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmailLoginForm, {});
1798
- case "email-register":
1799
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmailRegisterForm, {});
1800
- case "email-otp":
1801
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmailOtpForm, {});
1802
- case "wallet-connect":
1803
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WalletConnectForm, {});
1804
- case "forgot-password":
1805
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ForgotPasswordForm, {});
1806
- case "verify-2fa":
1807
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Verify2FAForm, {});
1808
- case "oauth":
1809
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OAuthLoadingView, {});
1810
- case "success":
1811
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SuccessView, {});
1812
- case "method-select":
1813
- default:
1814
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MethodSelect, {});
1834
+ }, [isOpen, initialEnabled, api, getAccessToken]);
1835
+ const handleEnable = async () => {
1836
+ const token = getAccessToken();
1837
+ if (!token || !code) return;
1838
+ setLoading(true);
1839
+ setMsg(null);
1840
+ try {
1841
+ await api.enable2FA(token, code);
1842
+ onStatusChange(true);
1843
+ setStep("recovery-codes");
1844
+ setCode("");
1845
+ } catch (err) {
1846
+ setMsg({ text: err instanceof Error ? err.message : "Invalid code.", ok: false });
1847
+ } finally {
1848
+ setLoading(false);
1815
1849
  }
1816
1850
  };
1817
- const renderLogo = () => {
1818
- if (_optionalChain([config, 'access', _43 => _43.appearance, 'optionalAccess', _44 => _44.logoNode])) {
1819
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-logo", children: config.appearance.logoNode });
1851
+ const handleDisable = async () => {
1852
+ const token = getAccessToken();
1853
+ if (!token || !code) return;
1854
+ setLoading(true);
1855
+ setMsg(null);
1856
+ try {
1857
+ await api.disable2FA(token, code);
1858
+ onStatusChange(false);
1859
+ setCode("");
1860
+ onClose();
1861
+ } catch (err) {
1862
+ setMsg({ text: err instanceof Error ? err.message : "Invalid code.", ok: false });
1863
+ } finally {
1864
+ setLoading(false);
1820
1865
  }
1821
- if (_optionalChain([config, 'access', _45 => _45.appearance, 'optionalAccess', _46 => _46.logo])) {
1822
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: config.appearance.logo, alt: "", className: "fc-logo" });
1866
+ };
1867
+ const handleRegenerate = async () => {
1868
+ const token = getAccessToken();
1869
+ if (!token || !code) return;
1870
+ setLoading(true);
1871
+ setMsg(null);
1872
+ try {
1873
+ const { recoveryCodes: codes } = await api.regenerateRecoveryCodes(token, code);
1874
+ setRecoveryCodes(codes);
1875
+ setStep("recovery-codes");
1876
+ setCode("");
1877
+ } catch (err) {
1878
+ setMsg({ text: err instanceof Error ? err.message : "Invalid code.", ok: false });
1879
+ } finally {
1880
+ setLoading(false);
1823
1881
  }
1824
- return null;
1825
1882
  };
1826
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ModalOverlay, { isOpen: modal.isOpen, onClose: closeModal, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1883
+ const handleCopyAll = () => {
1884
+ navigator.clipboard.writeText(recoveryCodes.join("\n")).catch(() => {
1885
+ });
1886
+ };
1887
+ const goBack = () => {
1888
+ setCode("");
1889
+ setMsg(null);
1890
+ setStep("manage");
1891
+ };
1892
+ if (!isOpen) return null;
1893
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ModalOverlay, { isOpen, onClose, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1827
1894
  "div",
1828
1895
  {
1829
1896
  className: "fc-modal-content",
1830
- style: {
1831
- "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _47 => _47.appearance, 'optionalAccess', _48 => _48.accentColor]), () => ( "#8b5cf6"))
1832
- },
1833
- "data-theme": _nullishCoalesce(_optionalChain([config, 'access', _49 => _49.appearance, 'optionalAccess', _50 => _50.theme]), () => ( "light")),
1834
- children: modal.step === "success" || modal.step === "oauth" ? renderStep() : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1835
- renderLogo(),
1836
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: _nullishCoalesce(_optionalChain([config, 'access', _51 => _51.appearance, 'optionalAccess', _52 => _52.title]), () => ( "Log in or sign up")) }),
1837
- renderStep(),
1838
- (_optionalChain([config, 'access', _53 => _53.appearance, 'optionalAccess', _54 => _54.termsUrl]) || _optionalChain([config, 'access', _55 => _55.appearance, 'optionalAccess', _56 => _56.privacyUrl])) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "fc-legal", children: [
1839
- "By continuing, you agree to our",
1840
- " ",
1841
- config.appearance.termsUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href: config.appearance.termsUrl, target: "_blank", rel: "noopener noreferrer", className: "fc-legal-link", children: "Terms" }),
1842
- config.appearance.termsUrl && config.appearance.privacyUrl && " and ",
1843
- config.appearance.privacyUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href: config.appearance.privacyUrl, target: "_blank", rel: "noopener noreferrer", className: "fc-legal-link", children: "Privacy Policy" })
1897
+ style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _48 => _48.appearance, 'optionalAccess', _49 => _49.accentColor]), () => ( "#8b5cf6")) },
1898
+ "data-theme": theme,
1899
+ children: [
1900
+ step === "setup" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1901
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Set up 2FA" }),
1902
+ msg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: msg.ok ? "fc-text" : "fc-error", children: msg.text }),
1903
+ loading && !setupData && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Loading..." }),
1904
+ setupData && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1905
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { textAlign: "center" }, children: "Scan this QR code with your authenticator app" }),
1906
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { display: "flex", justifyContent: "center", margin: "12px 0" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1907
+ "img",
1908
+ {
1909
+ src: setupData.qrCodeDataUrl,
1910
+ alt: "TOTP QR code",
1911
+ style: { width: 180, height: 180, borderRadius: 12 }
1912
+ }
1913
+ ) }),
1914
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { textAlign: "center", marginBottom: 12 }, children: [
1915
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setShowSecret(!showSecret), children: showSecret ? "Hide code" : "Can't scan? Enter manually" }),
1916
+ showSecret && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: { margin: "8px 0 0", fontFamily: "monospace", fontSize: 12, opacity: 0.7, wordBreak: "break-all" }, children: setupData.secret })
1917
+ ] }),
1918
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1919
+ "input",
1920
+ {
1921
+ className: "fc-input",
1922
+ type: "text",
1923
+ inputMode: "numeric",
1924
+ placeholder: "Enter 6-digit code",
1925
+ maxLength: 6,
1926
+ value: code,
1927
+ onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
1928
+ style: { textAlign: "center", letterSpacing: "0.2em" },
1929
+ autoFocus: true
1930
+ }
1931
+ ),
1932
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1933
+ "button",
1934
+ {
1935
+ type: "button",
1936
+ className: "fc-btn fc-btn-primary",
1937
+ onClick: handleEnable,
1938
+ disabled: loading || code.length !== 6,
1939
+ style: { marginTop: 10 },
1940
+ children: loading ? "Verifying..." : "Verify & Enable"
1941
+ }
1942
+ )
1943
+ ] })
1944
+ ] }),
1945
+ step === "manage" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1946
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Two-factor authentication" }),
1947
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { textAlign: "center", marginBottom: 20 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-verified", style: { fontSize: 12, padding: "4px 12px" }, children: "Enabled" }) }),
1948
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
1949
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1950
+ "button",
1951
+ {
1952
+ type: "button",
1953
+ className: "fc-security-card",
1954
+ onClick: () => {
1955
+ setCode("");
1956
+ setMsg(null);
1957
+ setStep("confirm-regenerate");
1958
+ },
1959
+ children: [
1960
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-icon", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { viewBox: "0 0 20 20", fill: "none", children: [
1961
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M3 10a7 7 0 0 1 7-7m0 14a7 7 0 0 1-7-7m14 0a7 7 0 0 1-7 7m0-14a7 7 0 0 1 7 7", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1962
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M14 3l-1 3h3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1963
+ ] }) }),
1964
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "fc-security-card-info", children: [
1965
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-label", children: "Regenerate recovery codes" }),
1966
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-detail", children: "Get new backup codes" })
1967
+ ] }),
1968
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-chevron", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M6 4l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
1969
+ ]
1970
+ }
1971
+ ),
1972
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1973
+ "button",
1974
+ {
1975
+ type: "button",
1976
+ className: "fc-security-card",
1977
+ onClick: () => {
1978
+ setCode("");
1979
+ setMsg(null);
1980
+ setStep("confirm-disable");
1981
+ },
1982
+ children: [
1983
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-icon", style: { color: "#dc2626" }, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { viewBox: "0 0 20 20", fill: "none", children: [
1984
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 2l6 3v4c0 4.42-2.56 8.22-6 9.5C6.56 17.22 4 13.42 4 9V5l6-3z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }),
1985
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M7.5 7.5l5 5M12.5 7.5l-5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
1986
+ ] }) }),
1987
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "fc-security-card-info", children: [
1988
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-label", style: { color: "#dc2626" }, children: "Disable 2FA" }),
1989
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-detail", children: "Remove two-factor authentication" })
1990
+ ] }),
1991
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-chevron", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M6 4l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
1992
+ ]
1993
+ }
1994
+ )
1995
+ ] })
1996
+ ] }),
1997
+ step === "confirm-regenerate" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1998
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Regenerate recovery codes" }),
1999
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { textAlign: "center" }, children: "Enter your 2FA code to generate new recovery codes. Your old codes will stop working." }),
2000
+ msg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: msg.ok ? "fc-text" : "fc-error", children: msg.text }),
2001
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
2002
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2003
+ "input",
2004
+ {
2005
+ className: "fc-input",
2006
+ type: "text",
2007
+ inputMode: "numeric",
2008
+ placeholder: "Enter 6-digit code",
2009
+ maxLength: 6,
2010
+ value: code,
2011
+ onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
2012
+ style: { textAlign: "center", letterSpacing: "0.2em" },
2013
+ autoFocus: true
2014
+ }
2015
+ ),
2016
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2017
+ "button",
2018
+ {
2019
+ type: "button",
2020
+ className: "fc-btn fc-btn-primary",
2021
+ onClick: handleRegenerate,
2022
+ disabled: loading || code.length !== 6,
2023
+ style: { marginTop: 10 },
2024
+ children: loading ? "Generating..." : "Regenerate codes"
2025
+ }
2026
+ ),
2027
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-switch", style: { marginTop: 12 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: goBack, children: "Back" }) })
2028
+ ] })
2029
+ ] }),
2030
+ step === "confirm-disable" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2031
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Disable 2FA" }),
2032
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { textAlign: "center" }, children: "Enter your 2FA code to disable two-factor authentication." }),
2033
+ msg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: msg.ok ? "fc-text" : "fc-error", children: msg.text }),
2034
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
2035
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2036
+ "input",
2037
+ {
2038
+ className: "fc-input",
2039
+ type: "text",
2040
+ inputMode: "numeric",
2041
+ placeholder: "Enter 6-digit code",
2042
+ maxLength: 6,
2043
+ value: code,
2044
+ onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
2045
+ style: { textAlign: "center", letterSpacing: "0.2em" },
2046
+ autoFocus: true
2047
+ }
2048
+ ),
2049
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2050
+ "button",
2051
+ {
2052
+ type: "button",
2053
+ className: "fc-btn fc-btn-secondary",
2054
+ onClick: handleDisable,
2055
+ disabled: loading || code.length !== 6,
2056
+ style: { marginTop: 10, background: "rgba(220, 38, 38, 0.1)", color: "#dc2626", borderColor: "rgba(220, 38, 38, 0.2)" },
2057
+ children: loading ? "Disabling..." : "Disable 2FA"
2058
+ }
2059
+ ),
2060
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-switch", style: { marginTop: 12 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: goBack, children: "Back" }) })
2061
+ ] })
2062
+ ] }),
2063
+ step === "recovery-codes" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2064
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Save your recovery codes" }),
2065
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { textAlign: "center" }, children: "Store these codes somewhere safe. Each code can only be used once." }),
2066
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-recovery-grid", children: recoveryCodes.map((c, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-recovery-code", children: c }, i)) }),
2067
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { textAlign: "center", margin: "8px 0 12px" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: handleCopyAll, children: "Copy all" }) }),
2068
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-primary", onClick: onClose, children: "Done" })
1844
2069
  ] })
1845
- ] })
2070
+ ]
1846
2071
  }
1847
2072
  ) });
1848
2073
  }
1849
- var EmailIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon", children: [
1850
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "4", width: "16", height: "12", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
1851
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M2 6l8 5 8-5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
1852
- ] }) });
1853
- var OtpIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon", children: [
1854
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "3", y: "6", width: "14", height: "9", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
1855
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "6.5", cy: "10.5", r: "1", fill: "currentColor" }),
1856
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "10", cy: "10.5", r: "1", fill: "currentColor" }),
1857
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "13.5", cy: "10.5", r: "1", fill: "currentColor" })
1858
- ] }) });
1859
- var WalletIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon", children: [
1860
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "5", width: "16", height: "11", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
1861
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "13", y: "9", width: "5", height: "3", rx: "1", stroke: "currentColor", strokeWidth: "1.5" })
1862
- ] }) });
1863
- var PasskeyIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon", children: [
1864
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "8", cy: "7", r: "3", stroke: "currentColor", strokeWidth: "1.5" }),
1865
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M13 13.5a5 5 0 0 0-10 0", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1866
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M15 10v4m0 0l-1.5-1m1.5 1l1.5-1", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1867
- ] }) });
1868
- var LoadingSpinner = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-method-icon-wrap", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", className: "fc-method-icon fc-spin", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 2a8 8 0 0 1 8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) });
1869
- function MethodSelect() {
1870
- const { setModalStep, loginWithPasskey, config } = useForgeConnect();
1871
- const methods = resolveLoginMethods(config);
1872
- const [passkeyLoading, setPasskeyLoading] = _react.useState.call(void 0, false);
1873
- const [passkeyError, setPasskeyError] = _react.useState.call(void 0, "");
1874
- const handlePasskey = async () => {
1875
- setPasskeyLoading(true);
1876
- setPasskeyError("");
1877
- try {
1878
- await loginWithPasskey();
1879
- } catch (err) {
1880
- setPasskeyError(err instanceof Error ? err.message : "Passkey authentication failed.");
1881
- } finally {
1882
- setPasskeyLoading(false);
1883
- }
1884
- };
1885
- const elements = [];
1886
- let i = 0;
1887
- while (i < methods.length) {
1888
- const method = methods[i];
1889
- if (isOAuthMethod(method)) {
1890
- const oauthGroup = [];
1891
- while (i < methods.length && isOAuthMethod(methods[i])) {
1892
- oauthGroup.push(methods[i]);
1893
- i++;
1894
- }
1895
- if (elements.length > 0) {
1896
- elements.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-divider", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "or" }) }, `div-before-${oauthGroup[0]}`));
1897
- }
1898
- elements.push(
1899
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-oauth-group", children: oauthGroup.map((p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OAuthButton, { provider: p }, p)) }, `oauth-${oauthGroup.join("-")}`)
1900
- );
1901
- } else {
1902
- if (elements.length > 0) {
1903
- const prev = methods[i - 1];
1904
- if (prev && isOAuthMethod(prev)) {
1905
- elements.push(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-divider", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "or" }) }, `div-after-${prev}`));
1906
- }
1907
- }
1908
- switch (method) {
1909
- case "email":
1910
- elements.push(
1911
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-method", onClick: () => setModalStep("email-login"), children: [
1912
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmailIcon, {}),
1913
- " ",
1914
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: "Password" })
1915
- ] }, "email")
1916
- );
1917
- break;
1918
- case "otp":
1919
- elements.push(
1920
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-method", onClick: () => setModalStep("email-otp"), children: [
1921
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OtpIcon, {}),
1922
- " ",
1923
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: "Magic code" })
1924
- ] }, "otp")
1925
- );
1926
- break;
1927
- case "wallet":
1928
- elements.push(
1929
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-method", onClick: () => setModalStep("wallet-connect"), children: [
1930
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WalletIcon, {}),
1931
- " ",
1932
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: "Wallet" })
1933
- ] }, "wallet")
1934
- );
1935
- break;
1936
- case "passkey":
1937
- elements.push(
1938
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-method", onClick: handlePasskey, disabled: passkeyLoading, children: [
1939
- passkeyLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSpinner, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PasskeyIcon, {}),
1940
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-btn-name", children: passkeyLoading ? "Waiting for passkey..." : "Passkey" })
1941
- ] }, "passkey")
1942
- );
1943
- break;
1944
- }
1945
- i++;
1946
- }
1947
- }
1948
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-method-select", children: [
1949
- passkeyError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: passkeyError }),
1950
- elements
1951
- ] });
1952
- }
1953
- function OAuthLoadingView() {
1954
- const { setModalStep } = useForgeConnect();
1955
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-success", children: [
1956
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-success-icon", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "52", height: "52", viewBox: "0 0 52 52", className: "fc-spin", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "26", cy: "26", r: "24", fill: "none", stroke: "var(--fc-accent, #8b5cf6)", strokeWidth: "3", strokeLinecap: "round", strokeDasharray: "100", strokeDashoffset: "30" }) }) }),
1957
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-success-text", children: "Completing sign in..." }),
1958
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-secondary", style: { marginTop: "16px" }, onClick: () => setModalStep("method-select"), children: "Cancel" })
1959
- ] });
1960
- }
1961
- function SuccessView() {
1962
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-success", children: [
1963
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-success-icon", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { viewBox: "0 0 52 52", className: "fc-success-check", children: [
1964
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { className: "fc-success-circle", cx: "26", cy: "26", r: "24", fill: "none" }),
1965
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { className: "fc-success-tick", fill: "none", d: "M15 26l7.5 7.5L37 19" })
1966
- ] }) }),
1967
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-success-text", children: "You're in" })
1968
- ] });
1969
- }
1970
2074
 
1971
- // src/components/account-modal.tsx
2075
+ // src/components/passkeys-modal.tsx
1972
2076
 
1973
2077
 
1974
- // src/hooks/use-user.ts
2078
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/bufferToBase64URLString.js
2079
+ function bufferToBase64URLString(buffer) {
2080
+ const bytes = new Uint8Array(buffer);
2081
+ let str = "";
2082
+ for (const charCode of bytes) {
2083
+ str += String.fromCharCode(charCode);
2084
+ }
2085
+ const base64String = btoa(str);
2086
+ return base64String.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
2087
+ }
1975
2088
 
1976
- function useUser() {
1977
- const { auth, api, config, getAccessToken } = useForgeConnect();
1978
- const [authMethods, setAuthMethods] = _react.useState.call(void 0, null);
1979
- const [loading, setLoading] = _react.useState.call(void 0, false);
1980
- const pendingRefreshRef = _react.useRef.call(void 0, false);
1981
- const updateProfile = _react.useCallback.call(void 0,
1982
- async (data) => {
1983
- const token = getAccessToken();
1984
- if (!token) throw new Error("Please sign in to continue.");
1985
- return api.updateMe(token, data);
1986
- },
1987
- [api, getAccessToken]
1988
- );
1989
- const fetchAuthMethods = _react.useCallback.call(void 0, async () => {
1990
- const token = getAccessToken();
1991
- if (!token) throw new Error("Please sign in to continue.");
1992
- setLoading(true);
1993
- try {
1994
- const methods = await api.getAuthMethods(token);
1995
- setAuthMethods(methods);
1996
- return methods;
1997
- } finally {
1998
- setLoading(false);
1999
- }
2000
- }, [api, getAccessToken]);
2001
- const linkAuthMethod = _react.useCallback.call(void 0,
2002
- async (data) => {
2003
- const token = getAccessToken();
2004
- if (!token) throw new Error("Please sign in to continue.");
2005
- await api.linkAuthMethod(token, data);
2006
- await fetchAuthMethods();
2007
- },
2008
- [api, getAccessToken, fetchAuthMethods]
2009
- );
2010
- const linkOtpSend = _react.useCallback.call(void 0,
2011
- async (email) => {
2012
- const token = getAccessToken();
2013
- if (!token) throw new Error("Please sign in to continue.");
2014
- await api.linkOtpSend(token, email);
2015
- },
2016
- [api, getAccessToken]
2017
- );
2018
- const linkOtpVerify = _react.useCallback.call(void 0,
2019
- async (email, code) => {
2020
- const token = getAccessToken();
2021
- if (!token) throw new Error("Please sign in to continue.");
2022
- await api.linkOtpVerify(token, email, code);
2023
- await fetchAuthMethods();
2024
- },
2025
- [api, getAccessToken, fetchAuthMethods]
2026
- );
2027
- const unlinkAuthMethod = _react.useCallback.call(void 0,
2028
- async (id) => {
2029
- const token = getAccessToken();
2030
- if (!token) throw new Error("Please sign in to continue.");
2031
- await api.unlinkAuthMethod(token, id);
2032
- await fetchAuthMethods();
2033
- },
2034
- [api, getAccessToken, fetchAuthMethods]
2035
- );
2036
- const linkOAuth = _react.useCallback.call(void 0,
2037
- async (provider) => {
2038
- const token = getAccessToken();
2039
- if (!token) throw new Error("Please sign in to continue.");
2040
- const { intentToken } = await api.createLinkIntent(token);
2041
- const redirectUri = encodeURIComponent(window.location.origin + "/fc-oauth-callback");
2042
- const url = `${config.apiUrl}/auth/oauth/${provider}/link?intent=${encodeURIComponent(intentToken)}&redirect_uri=${redirectUri}`;
2043
- const width = 500;
2044
- const height = 600;
2045
- const left = window.screenX + (window.innerWidth - width) / 2;
2046
- const top = window.screenY + (window.innerHeight - height) / 2;
2047
- window.open(url, "fc_oauth_link", `width=${width},height=${height},left=${left},top=${top}`);
2048
- pendingRefreshRef.current = true;
2049
- },
2050
- [api, config.apiUrl, getAccessToken]
2051
- );
2052
- _react.useEffect.call(void 0, () => {
2053
- const handleMessage = (event) => {
2054
- if (event.origin !== window.location.origin) return;
2055
- if (_optionalChain([event, 'access', _57 => _57.data, 'optionalAccess', _58 => _58.type]) === "fc_oauth_link_success" && pendingRefreshRef.current) {
2056
- pendingRefreshRef.current = false;
2057
- fetchAuthMethods().catch(() => {
2058
- });
2059
- }
2060
- };
2061
- window.addEventListener("message", handleMessage);
2062
- return () => window.removeEventListener("message", handleMessage);
2063
- }, [fetchAuthMethods]);
2089
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/base64URLStringToBuffer.js
2090
+ function base64URLStringToBuffer(base64URLString) {
2091
+ const base64 = base64URLString.replace(/-/g, "+").replace(/_/g, "/");
2092
+ const padLength = (4 - base64.length % 4) % 4;
2093
+ const padded = base64.padEnd(base64.length + padLength, "=");
2094
+ const binary = atob(padded);
2095
+ const buffer = new ArrayBuffer(binary.length);
2096
+ const bytes = new Uint8Array(buffer);
2097
+ for (let i = 0; i < binary.length; i++) {
2098
+ bytes[i] = binary.charCodeAt(i);
2099
+ }
2100
+ return buffer;
2101
+ }
2102
+
2103
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/browserSupportsWebAuthn.js
2104
+ function browserSupportsWebAuthn() {
2105
+ return _browserSupportsWebAuthnInternals.stubThis(_optionalChain([globalThis, 'optionalAccess', _50 => _50.PublicKeyCredential]) !== void 0 && typeof globalThis.PublicKeyCredential === "function");
2106
+ }
2107
+ var _browserSupportsWebAuthnInternals = {
2108
+ stubThis: (value) => value
2109
+ };
2110
+
2111
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/toPublicKeyCredentialDescriptor.js
2112
+ function toPublicKeyCredentialDescriptor(descriptor) {
2113
+ const { id } = descriptor;
2064
2114
  return {
2065
- user: auth.user,
2066
- authMethods,
2067
- loading,
2068
- updateProfile,
2069
- fetchAuthMethods,
2070
- linkAuthMethod,
2071
- linkOtpSend,
2072
- linkOtpVerify,
2073
- unlinkAuthMethod,
2074
- linkOAuth
2115
+ ...descriptor,
2116
+ id: base64URLStringToBuffer(id),
2117
+ /**
2118
+ * `descriptor.transports` is an array of our `AuthenticatorTransportFuture` that includes newer
2119
+ * transports that TypeScript's DOM lib is ignorant of. Convince TS that our list of transports
2120
+ * are fine to pass to WebAuthn since browsers will recognize the new value.
2121
+ */
2122
+ transports: descriptor.transports
2075
2123
  };
2076
2124
  }
2077
2125
 
2078
- // src/hooks/use-wallets.ts
2126
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/isValidDomain.js
2127
+ function isValidDomain(hostname) {
2128
+ return (
2129
+ // Consider localhost valid as well since it's okay wrt Secure Contexts
2130
+ hostname === "localhost" || /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(hostname)
2131
+ );
2132
+ }
2079
2133
 
2134
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/webAuthnError.js
2135
+ var WebAuthnError = class extends Error {
2136
+ constructor({ message, code, cause, name }) {
2137
+ super(message, { cause });
2138
+ Object.defineProperty(this, "code", {
2139
+ enumerable: true,
2140
+ configurable: true,
2141
+ writable: true,
2142
+ value: void 0
2143
+ });
2144
+ this.name = _nullishCoalesce(name, () => ( cause.name));
2145
+ this.code = code;
2146
+ }
2147
+ };
2080
2148
 
2081
- // src/lib/utils.ts
2082
- var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
2083
- function uint8ArrayToBase58(bytes) {
2084
- const digits = [0];
2085
- for (const byte of bytes) {
2086
- let carry = byte;
2087
- for (let j = 0; j < digits.length; j++) {
2088
- carry += digits[j] << 8;
2089
- digits[j] = carry % 58;
2090
- carry = carry / 58 | 0;
2149
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/identifyRegistrationError.js
2150
+ function identifyRegistrationError({ error, options }) {
2151
+ const { publicKey } = options;
2152
+ if (!publicKey) {
2153
+ throw Error("options was missing required publicKey property");
2154
+ }
2155
+ if (error.name === "AbortError") {
2156
+ if (options.signal instanceof AbortSignal) {
2157
+ return new WebAuthnError({
2158
+ message: "Registration ceremony was sent an abort signal",
2159
+ code: "ERROR_CEREMONY_ABORTED",
2160
+ cause: error
2161
+ });
2091
2162
  }
2092
- while (carry > 0) {
2093
- digits.push(carry % 58);
2094
- carry = carry / 58 | 0;
2163
+ } else if (error.name === "ConstraintError") {
2164
+ if (_optionalChain([publicKey, 'access', _51 => _51.authenticatorSelection, 'optionalAccess', _52 => _52.requireResidentKey]) === true) {
2165
+ return new WebAuthnError({
2166
+ message: "Discoverable credentials were required but no available authenticator supported it",
2167
+ code: "ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",
2168
+ cause: error
2169
+ });
2170
+ } else if (
2171
+ // @ts-ignore: `mediation` doesn't yet exist on CredentialCreationOptions but it's possible as of Sept 2024
2172
+ options.mediation === "conditional" && _optionalChain([publicKey, 'access', _53 => _53.authenticatorSelection, 'optionalAccess', _54 => _54.userVerification]) === "required"
2173
+ ) {
2174
+ return new WebAuthnError({
2175
+ message: "User verification was required during automatic registration but it could not be performed",
2176
+ code: "ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",
2177
+ cause: error
2178
+ });
2179
+ } else if (_optionalChain([publicKey, 'access', _55 => _55.authenticatorSelection, 'optionalAccess', _56 => _56.userVerification]) === "required") {
2180
+ return new WebAuthnError({
2181
+ message: "User verification was required but no available authenticator supported it",
2182
+ code: "ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",
2183
+ cause: error
2184
+ });
2185
+ }
2186
+ } else if (error.name === "InvalidStateError") {
2187
+ return new WebAuthnError({
2188
+ message: "The authenticator was previously registered",
2189
+ code: "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",
2190
+ cause: error
2191
+ });
2192
+ } else if (error.name === "NotAllowedError") {
2193
+ return new WebAuthnError({
2194
+ message: error.message,
2195
+ code: "ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",
2196
+ cause: error
2197
+ });
2198
+ } else if (error.name === "NotSupportedError") {
2199
+ const validPubKeyCredParams = publicKey.pubKeyCredParams.filter((param) => param.type === "public-key");
2200
+ if (validPubKeyCredParams.length === 0) {
2201
+ return new WebAuthnError({
2202
+ message: 'No entry in pubKeyCredParams was of type "public-key"',
2203
+ code: "ERROR_MALFORMED_PUBKEYCREDPARAMS",
2204
+ cause: error
2205
+ });
2206
+ }
2207
+ return new WebAuthnError({
2208
+ message: "No available authenticator supported any of the specified pubKeyCredParams algorithms",
2209
+ code: "ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",
2210
+ cause: error
2211
+ });
2212
+ } else if (error.name === "SecurityError") {
2213
+ const effectiveDomain = globalThis.location.hostname;
2214
+ if (!isValidDomain(effectiveDomain)) {
2215
+ return new WebAuthnError({
2216
+ message: `${globalThis.location.hostname} is an invalid domain`,
2217
+ code: "ERROR_INVALID_DOMAIN",
2218
+ cause: error
2219
+ });
2220
+ } else if (publicKey.rp.id !== effectiveDomain) {
2221
+ return new WebAuthnError({
2222
+ message: `The RP ID "${publicKey.rp.id}" is invalid for this domain`,
2223
+ code: "ERROR_INVALID_RP_ID",
2224
+ cause: error
2225
+ });
2095
2226
  }
2227
+ } else if (error.name === "TypeError") {
2228
+ if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) {
2229
+ return new WebAuthnError({
2230
+ message: "User ID was not between 1 and 64 characters",
2231
+ code: "ERROR_INVALID_USER_ID_LENGTH",
2232
+ cause: error
2233
+ });
2234
+ }
2235
+ } else if (error.name === "UnknownError") {
2236
+ return new WebAuthnError({
2237
+ message: "The authenticator was unable to process the specified options, or could not create a new credential",
2238
+ code: "ERROR_AUTHENTICATOR_GENERAL_ERROR",
2239
+ cause: error
2240
+ });
2096
2241
  }
2097
- let str = "";
2098
- for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
2099
- str += "1";
2242
+ return error;
2243
+ }
2244
+
2245
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/webAuthnAbortService.js
2246
+ var BaseWebAuthnAbortService = class {
2247
+ constructor() {
2248
+ Object.defineProperty(this, "controller", {
2249
+ enumerable: true,
2250
+ configurable: true,
2251
+ writable: true,
2252
+ value: void 0
2253
+ });
2100
2254
  }
2101
- for (let i = digits.length - 1; i >= 0; i--) {
2102
- str += BASE58_ALPHABET[digits[i]];
2255
+ createNewAbortSignal() {
2256
+ if (this.controller) {
2257
+ const abortError = new Error("Cancelling existing WebAuthn API call for new one");
2258
+ abortError.name = "AbortError";
2259
+ this.controller.abort(abortError);
2260
+ }
2261
+ const newController = new AbortController();
2262
+ this.controller = newController;
2263
+ return newController.signal;
2103
2264
  }
2104
- return str;
2105
- }
2106
- function timeAgo(dateStr) {
2107
- const now = Date.now();
2108
- const then = new Date(dateStr).getTime();
2109
- const diff = now - then;
2110
- const mins = Math.floor(diff / 6e4);
2111
- if (mins < 1) return "just now";
2112
- if (mins < 60) return `${mins}m ago`;
2113
- const hours = Math.floor(mins / 60);
2114
- if (hours < 24) return `${hours}h ago`;
2115
- const days = Math.floor(hours / 24);
2116
- if (days < 30) return `${days}d ago`;
2117
- return new Date(dateStr).toLocaleDateString();
2265
+ cancelCeremony() {
2266
+ if (this.controller) {
2267
+ const abortError = new Error("Manually cancelling existing WebAuthn API call");
2268
+ abortError.name = "AbortError";
2269
+ this.controller.abort(abortError);
2270
+ this.controller = void 0;
2271
+ }
2272
+ }
2273
+ };
2274
+ var WebAuthnAbortService = new BaseWebAuthnAbortService();
2275
+
2276
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/toAuthenticatorAttachment.js
2277
+ var attachments = ["cross-platform", "platform"];
2278
+ function toAuthenticatorAttachment(attachment) {
2279
+ if (!attachment) {
2280
+ return;
2281
+ }
2282
+ if (attachments.indexOf(attachment) < 0) {
2283
+ return;
2284
+ }
2285
+ return attachment;
2118
2286
  }
2119
2287
 
2120
- // src/hooks/use-wallets.ts
2121
- function useWallets() {
2122
- const { api, getAccessToken } = useForgeConnect();
2123
- const [wallets, setWallets] = _react.useState.call(void 0, null);
2124
- const [loading, setLoading] = _react.useState.call(void 0, false);
2125
- const fetchWallets = _react.useCallback.call(void 0, async () => {
2126
- const token = getAccessToken();
2127
- if (!token) throw new Error("Please sign in to continue.");
2128
- setLoading(true);
2288
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/methods/startRegistration.js
2289
+ async function startRegistration(options) {
2290
+ if (!options.optionsJSON && options.challenge) {
2291
+ console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.");
2292
+ options = { optionsJSON: options };
2293
+ }
2294
+ const { optionsJSON, useAutoRegister = false } = options;
2295
+ if (!browserSupportsWebAuthn()) {
2296
+ throw new Error("WebAuthn is not supported in this browser");
2297
+ }
2298
+ const publicKey = {
2299
+ ...optionsJSON,
2300
+ challenge: base64URLStringToBuffer(optionsJSON.challenge),
2301
+ user: {
2302
+ ...optionsJSON.user,
2303
+ id: base64URLStringToBuffer(optionsJSON.user.id)
2304
+ },
2305
+ excludeCredentials: _optionalChain([optionsJSON, 'access', _57 => _57.excludeCredentials, 'optionalAccess', _58 => _58.map, 'call', _59 => _59(toPublicKeyCredentialDescriptor)])
2306
+ };
2307
+ const createOptions = {};
2308
+ if (useAutoRegister) {
2309
+ createOptions.mediation = "conditional";
2310
+ }
2311
+ createOptions.publicKey = publicKey;
2312
+ createOptions.signal = WebAuthnAbortService.createNewAbortSignal();
2313
+ let credential;
2314
+ try {
2315
+ credential = await navigator.credentials.create(createOptions);
2316
+ } catch (err) {
2317
+ throw identifyRegistrationError({ error: err, options: createOptions });
2318
+ }
2319
+ if (!credential) {
2320
+ throw new Error("Registration was not completed");
2321
+ }
2322
+ const { id, rawId, response, type } = credential;
2323
+ let transports = void 0;
2324
+ if (typeof response.getTransports === "function") {
2325
+ transports = response.getTransports();
2326
+ }
2327
+ let responsePublicKeyAlgorithm = void 0;
2328
+ if (typeof response.getPublicKeyAlgorithm === "function") {
2129
2329
  try {
2130
- const data = await api.getWallets(token);
2131
- setWallets(data);
2132
- return data;
2133
- } finally {
2134
- setLoading(false);
2330
+ responsePublicKeyAlgorithm = response.getPublicKeyAlgorithm();
2331
+ } catch (error) {
2332
+ warnOnBrokenImplementation("getPublicKeyAlgorithm()", error);
2135
2333
  }
2136
- }, [api, getAccessToken]);
2137
- const updateWallet = _react.useCallback.call(void 0,
2138
- async (id, data) => {
2139
- const token = getAccessToken();
2140
- if (!token) throw new Error("Please sign in to continue.");
2141
- await api.updateWallet(token, id, data);
2142
- await fetchWallets();
2143
- },
2144
- [api, getAccessToken, fetchWallets]
2145
- );
2146
- const linkWallet = _react.useCallback.call(void 0,
2147
- async (walletAddress, signMessage, chain = "solana", signTransaction) => {
2148
- const token = getAccessToken();
2149
- if (!token) throw new Error("Please sign in to continue.");
2150
- if (signMessage) {
2151
- const { challengeId, message: challengeMessage } = await api.walletChallenge(walletAddress, chain);
2152
- const encoded = new TextEncoder().encode(challengeMessage);
2153
- const signatureBytes = await signMessage(encoded);
2154
- const signature = chain === "solana" ? uint8ArrayToBase58(signatureBytes) : Array.from(signatureBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
2155
- await api.linkAuthMethod(token, {
2156
- provider: `${chain}_wallet`,
2157
- challengeId,
2158
- signature,
2159
- walletAddress
2160
- });
2161
- } else {
2162
- if (!signTransaction) {
2163
- throw new Error("Wallet does not support message signing or transaction signing.");
2164
- }
2165
- const { challengeId, transaction: txBase64 } = await api.walletChallengeTx(walletAddress, chain);
2166
- const signedTxBase64 = await signTransaction(txBase64);
2167
- await api.linkAuthMethod(token, {
2168
- provider: `${chain}_wallet_tx`,
2169
- challengeId,
2170
- signedTransaction: signedTxBase64,
2171
- walletAddress
2172
- });
2334
+ }
2335
+ let responsePublicKey = void 0;
2336
+ if (typeof response.getPublicKey === "function") {
2337
+ try {
2338
+ const _publicKey = response.getPublicKey();
2339
+ if (_publicKey !== null) {
2340
+ responsePublicKey = bufferToBase64URLString(_publicKey);
2173
2341
  }
2174
- await fetchWallets();
2175
- },
2176
- [api, getAccessToken, fetchWallets]
2177
- );
2178
- return {
2179
- wallets,
2180
- loading,
2181
- fetchWallets,
2182
- updateWallet,
2183
- linkWallet
2184
- };
2185
- }
2186
-
2187
- // src/hooks/use-sessions.ts
2188
-
2189
- function useSessions() {
2190
- const { api, getAccessToken } = useForgeConnect();
2191
- const [sessions, setSessions] = _react.useState.call(void 0, null);
2192
- const [loading, setLoading] = _react.useState.call(void 0, false);
2193
- const fetchSessions = _react.useCallback.call(void 0, async () => {
2194
- const token = getAccessToken();
2195
- if (!token) throw new Error("Please sign in to continue.");
2196
- setLoading(true);
2342
+ } catch (error) {
2343
+ warnOnBrokenImplementation("getPublicKey()", error);
2344
+ }
2345
+ }
2346
+ let responseAuthenticatorData;
2347
+ if (typeof response.getAuthenticatorData === "function") {
2197
2348
  try {
2198
- const data = await api.getSessions(token);
2199
- setSessions(data);
2200
- return data;
2201
- } finally {
2202
- setLoading(false);
2349
+ responseAuthenticatorData = bufferToBase64URLString(response.getAuthenticatorData());
2350
+ } catch (error) {
2351
+ warnOnBrokenImplementation("getAuthenticatorData()", error);
2203
2352
  }
2204
- }, [api, getAccessToken]);
2205
- const revokeSession = _react.useCallback.call(void 0,
2206
- async (id) => {
2207
- const token = getAccessToken();
2208
- if (!token) throw new Error("Please sign in to continue.");
2209
- await api.revokeSession(token, id);
2210
- await fetchSessions();
2211
- },
2212
- [api, getAccessToken, fetchSessions]
2213
- );
2353
+ }
2214
2354
  return {
2215
- sessions,
2216
- loading,
2217
- fetchSessions,
2218
- revokeSession
2355
+ id,
2356
+ rawId: bufferToBase64URLString(rawId),
2357
+ response: {
2358
+ attestationObject: bufferToBase64URLString(response.attestationObject),
2359
+ clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
2360
+ transports,
2361
+ publicKeyAlgorithm: responsePublicKeyAlgorithm,
2362
+ publicKey: responsePublicKey,
2363
+ authenticatorData: responseAuthenticatorData
2364
+ },
2365
+ type,
2366
+ clientExtensionResults: credential.getClientExtensionResults(),
2367
+ authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment)
2219
2368
  };
2220
2369
  }
2370
+ function warnOnBrokenImplementation(methodName, cause) {
2371
+ console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${methodName}. You should report this error to them.
2372
+ `, cause);
2373
+ }
2221
2374
 
2222
- // src/components/two-factor-modal.tsx
2223
-
2375
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/browserSupportsWebAuthnAutofill.js
2376
+ function browserSupportsWebAuthnAutofill() {
2377
+ if (!browserSupportsWebAuthn()) {
2378
+ return _browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
2379
+ }
2380
+ const globalPublicKeyCredential = globalThis.PublicKeyCredential;
2381
+ if (_optionalChain([globalPublicKeyCredential, 'optionalAccess', _60 => _60.isConditionalMediationAvailable]) === void 0) {
2382
+ return _browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
2383
+ }
2384
+ return _browserSupportsWebAuthnAutofillInternals.stubThis(globalPublicKeyCredential.isConditionalMediationAvailable());
2385
+ }
2386
+ var _browserSupportsWebAuthnAutofillInternals = {
2387
+ stubThis: (value) => value
2388
+ };
2224
2389
 
2225
- function TwoFactorModal({ isOpen, onClose, initialEnabled, onStatusChange }) {
2226
- const { api, getAccessToken, config } = useForgeConnect();
2227
- const theme = _nullishCoalesce(_optionalChain([config, 'access', _59 => _59.appearance, 'optionalAccess', _60 => _60.theme]), () => ( "light"));
2228
- const [step, setStep] = _react.useState.call(void 0, initialEnabled ? "manage" : "setup");
2229
- const [setupData, setSetupData] = _react.useState.call(void 0, null);
2230
- const [code, setCode] = _react.useState.call(void 0, "");
2231
- const [loading, setLoading] = _react.useState.call(void 0, false);
2232
- const [msg, setMsg] = _react.useState.call(void 0, null);
2233
- const [showSecret, setShowSecret] = _react.useState.call(void 0, false);
2234
- const [recoveryCodes, setRecoveryCodes] = _react.useState.call(void 0, []);
2235
- _react.useEffect.call(void 0, () => {
2236
- if (isOpen) {
2237
- setStep(initialEnabled ? "manage" : "setup");
2238
- setSetupData(null);
2239
- setCode("");
2240
- setMsg(null);
2241
- setLoading(false);
2242
- setShowSecret(false);
2243
- setRecoveryCodes([]);
2244
- if (!initialEnabled) {
2245
- const token = getAccessToken();
2246
- if (token) {
2247
- setLoading(true);
2248
- api.setup2FA(token).then((data) => {
2249
- setSetupData(data);
2250
- setRecoveryCodes(data.recoveryCodes);
2251
- }).catch((err) => {
2252
- setMsg({ text: err instanceof Error ? err.message : "Could not set up 2FA.", ok: false });
2253
- }).finally(() => setLoading(false));
2254
- }
2255
- }
2256
- }
2257
- }, [isOpen, initialEnabled, api, getAccessToken]);
2258
- const handleEnable = async () => {
2259
- const token = getAccessToken();
2260
- if (!token || !code) return;
2261
- setLoading(true);
2262
- setMsg(null);
2263
- try {
2264
- await api.enable2FA(token, code);
2265
- onStatusChange(true);
2266
- setStep("recovery-codes");
2267
- setCode("");
2268
- } catch (err) {
2269
- setMsg({ text: err instanceof Error ? err.message : "Invalid code.", ok: false });
2270
- } finally {
2271
- setLoading(false);
2272
- }
2273
- };
2274
- const handleDisable = async () => {
2275
- const token = getAccessToken();
2276
- if (!token || !code) return;
2277
- setLoading(true);
2278
- setMsg(null);
2279
- try {
2280
- await api.disable2FA(token, code);
2281
- onStatusChange(false);
2282
- setCode("");
2283
- onClose();
2284
- } catch (err) {
2285
- setMsg({ text: err instanceof Error ? err.message : "Invalid code.", ok: false });
2286
- } finally {
2287
- setLoading(false);
2390
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/helpers/identifyAuthenticationError.js
2391
+ function identifyAuthenticationError({ error, options }) {
2392
+ const { publicKey } = options;
2393
+ if (!publicKey) {
2394
+ throw Error("options was missing required publicKey property");
2395
+ }
2396
+ if (error.name === "AbortError") {
2397
+ if (options.signal instanceof AbortSignal) {
2398
+ return new WebAuthnError({
2399
+ message: "Authentication ceremony was sent an abort signal",
2400
+ code: "ERROR_CEREMONY_ABORTED",
2401
+ cause: error
2402
+ });
2288
2403
  }
2289
- };
2290
- const handleRegenerate = async () => {
2291
- const token = getAccessToken();
2292
- if (!token || !code) return;
2293
- setLoading(true);
2294
- setMsg(null);
2295
- try {
2296
- const { recoveryCodes: codes } = await api.regenerateRecoveryCodes(token, code);
2297
- setRecoveryCodes(codes);
2298
- setStep("recovery-codes");
2299
- setCode("");
2300
- } catch (err) {
2301
- setMsg({ text: err instanceof Error ? err.message : "Invalid code.", ok: false });
2302
- } finally {
2303
- setLoading(false);
2404
+ } else if (error.name === "NotAllowedError") {
2405
+ return new WebAuthnError({
2406
+ message: error.message,
2407
+ code: "ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",
2408
+ cause: error
2409
+ });
2410
+ } else if (error.name === "SecurityError") {
2411
+ const effectiveDomain = globalThis.location.hostname;
2412
+ if (!isValidDomain(effectiveDomain)) {
2413
+ return new WebAuthnError({
2414
+ message: `${globalThis.location.hostname} is an invalid domain`,
2415
+ code: "ERROR_INVALID_DOMAIN",
2416
+ cause: error
2417
+ });
2418
+ } else if (publicKey.rpId !== effectiveDomain) {
2419
+ return new WebAuthnError({
2420
+ message: `The RP ID "${publicKey.rpId}" is invalid for this domain`,
2421
+ code: "ERROR_INVALID_RP_ID",
2422
+ cause: error
2423
+ });
2304
2424
  }
2305
- };
2306
- const handleCopyAll = () => {
2307
- navigator.clipboard.writeText(recoveryCodes.join("\n")).catch(() => {
2425
+ } else if (error.name === "UnknownError") {
2426
+ return new WebAuthnError({
2427
+ message: "The authenticator was unable to process the specified options, or could not create a new assertion signature",
2428
+ code: "ERROR_AUTHENTICATOR_GENERAL_ERROR",
2429
+ cause: error
2308
2430
  });
2431
+ }
2432
+ return error;
2433
+ }
2434
+
2435
+ // ../../node_modules/.pnpm/@simplewebauthn+browser@13.2.2/node_modules/@simplewebauthn/browser/esm/methods/startAuthentication.js
2436
+ async function startAuthentication(options) {
2437
+ if (!options.optionsJSON && options.challenge) {
2438
+ console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.");
2439
+ options = { optionsJSON: options };
2440
+ }
2441
+ const { optionsJSON, useBrowserAutofill = false, verifyBrowserAutofillInput = true } = options;
2442
+ if (!browserSupportsWebAuthn()) {
2443
+ throw new Error("WebAuthn is not supported in this browser");
2444
+ }
2445
+ let allowCredentials;
2446
+ if (_optionalChain([optionsJSON, 'access', _61 => _61.allowCredentials, 'optionalAccess', _62 => _62.length]) !== 0) {
2447
+ allowCredentials = _optionalChain([optionsJSON, 'access', _63 => _63.allowCredentials, 'optionalAccess', _64 => _64.map, 'call', _65 => _65(toPublicKeyCredentialDescriptor)]);
2448
+ }
2449
+ const publicKey = {
2450
+ ...optionsJSON,
2451
+ challenge: base64URLStringToBuffer(optionsJSON.challenge),
2452
+ allowCredentials
2309
2453
  };
2310
- const goBack = () => {
2311
- setCode("");
2312
- setMsg(null);
2313
- setStep("manage");
2314
- };
2315
- if (!isOpen) return null;
2316
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ModalOverlay, { isOpen, onClose, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2317
- "div",
2318
- {
2319
- className: "fc-modal-content",
2320
- style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _61 => _61.appearance, 'optionalAccess', _62 => _62.accentColor]), () => ( "#8b5cf6")) },
2321
- "data-theme": theme,
2322
- children: [
2323
- step === "setup" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2324
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Set up 2FA" }),
2325
- msg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: msg.ok ? "fc-text" : "fc-error", children: msg.text }),
2326
- loading && !setupData && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Loading..." }),
2327
- setupData && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
2328
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { textAlign: "center" }, children: "Scan this QR code with your authenticator app" }),
2329
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { display: "flex", justifyContent: "center", margin: "12px 0" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2330
- "img",
2331
- {
2332
- src: setupData.qrCodeDataUrl,
2333
- alt: "TOTP QR code",
2334
- style: { width: 180, height: 180, borderRadius: 12 }
2335
- }
2336
- ) }),
2337
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { textAlign: "center", marginBottom: 12 }, children: [
2338
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: () => setShowSecret(!showSecret), children: showSecret ? "Hide code" : "Can't scan? Enter manually" }),
2339
- showSecret && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: { margin: "8px 0 0", fontFamily: "monospace", fontSize: 12, opacity: 0.7, wordBreak: "break-all" }, children: setupData.secret })
2340
- ] }),
2341
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2342
- "input",
2343
- {
2344
- className: "fc-input",
2345
- type: "text",
2346
- inputMode: "numeric",
2347
- placeholder: "Enter 6-digit code",
2348
- maxLength: 6,
2349
- value: code,
2350
- onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
2351
- style: { textAlign: "center", letterSpacing: "0.2em" },
2352
- autoFocus: true
2353
- }
2354
- ),
2355
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2356
- "button",
2357
- {
2358
- type: "button",
2359
- className: "fc-btn fc-btn-primary",
2360
- onClick: handleEnable,
2361
- disabled: loading || code.length !== 6,
2362
- style: { marginTop: 10 },
2363
- children: loading ? "Verifying..." : "Verify & Enable"
2364
- }
2365
- )
2366
- ] })
2367
- ] }),
2368
- step === "manage" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2369
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Two-factor authentication" }),
2370
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { textAlign: "center", marginBottom: 20 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-badge-verified", style: { fontSize: 12, padding: "4px 12px" }, children: "Enabled" }) }),
2371
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
2372
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2373
- "button",
2374
- {
2375
- type: "button",
2376
- className: "fc-security-card",
2377
- onClick: () => {
2378
- setCode("");
2379
- setMsg(null);
2380
- setStep("confirm-regenerate");
2381
- },
2382
- children: [
2383
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-icon", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { viewBox: "0 0 20 20", fill: "none", children: [
2384
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M3 10a7 7 0 0 1 7-7m0 14a7 7 0 0 1-7-7m14 0a7 7 0 0 1-7 7m0-14a7 7 0 0 1 7 7", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
2385
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M14 3l-1 3h3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
2386
- ] }) }),
2387
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "fc-security-card-info", children: [
2388
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-label", children: "Regenerate recovery codes" }),
2389
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-detail", children: "Get new backup codes" })
2390
- ] }),
2391
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-chevron", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M6 4l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
2392
- ]
2393
- }
2394
- ),
2395
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2396
- "button",
2397
- {
2398
- type: "button",
2399
- className: "fc-security-card",
2400
- onClick: () => {
2401
- setCode("");
2402
- setMsg(null);
2403
- setStep("confirm-disable");
2404
- },
2405
- children: [
2406
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-icon", style: { color: "#dc2626" }, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { viewBox: "0 0 20 20", fill: "none", children: [
2407
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M10 2l6 3v4c0 4.42-2.56 8.22-6 9.5C6.56 17.22 4 13.42 4 9V5l6-3z", stroke: "currentColor", strokeWidth: "1.5", strokeLinejoin: "round" }),
2408
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M7.5 7.5l5 5M12.5 7.5l-5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
2409
- ] }) }),
2410
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "fc-security-card-info", children: [
2411
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-label", style: { color: "#dc2626" }, children: "Disable 2FA" }),
2412
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-detail", children: "Remove two-factor authentication" })
2413
- ] }),
2414
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-security-card-chevron", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M6 4l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
2415
- ]
2416
- }
2417
- )
2418
- ] })
2419
- ] }),
2420
- step === "confirm-regenerate" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2421
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Regenerate recovery codes" }),
2422
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { textAlign: "center" }, children: "Enter your 2FA code to generate new recovery codes. Your old codes will stop working." }),
2423
- msg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: msg.ok ? "fc-text" : "fc-error", children: msg.text }),
2424
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
2425
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2426
- "input",
2427
- {
2428
- className: "fc-input",
2429
- type: "text",
2430
- inputMode: "numeric",
2431
- placeholder: "Enter 6-digit code",
2432
- maxLength: 6,
2433
- value: code,
2434
- onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
2435
- style: { textAlign: "center", letterSpacing: "0.2em" },
2436
- autoFocus: true
2437
- }
2438
- ),
2439
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2440
- "button",
2441
- {
2442
- type: "button",
2443
- className: "fc-btn fc-btn-primary",
2444
- onClick: handleRegenerate,
2445
- disabled: loading || code.length !== 6,
2446
- style: { marginTop: 10 },
2447
- children: loading ? "Generating..." : "Regenerate codes"
2448
- }
2449
- ),
2450
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-switch", style: { marginTop: 12 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: goBack, children: "Back" }) })
2451
- ] })
2452
- ] }),
2453
- step === "confirm-disable" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2454
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Disable 2FA" }),
2455
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { textAlign: "center" }, children: "Enter your 2FA code to disable two-factor authentication." }),
2456
- msg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: msg.ok ? "fc-text" : "fc-error", children: msg.text }),
2457
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
2458
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2459
- "input",
2460
- {
2461
- className: "fc-input",
2462
- type: "text",
2463
- inputMode: "numeric",
2464
- placeholder: "Enter 6-digit code",
2465
- maxLength: 6,
2466
- value: code,
2467
- onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
2468
- style: { textAlign: "center", letterSpacing: "0.2em" },
2469
- autoFocus: true
2470
- }
2471
- ),
2472
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2473
- "button",
2474
- {
2475
- type: "button",
2476
- className: "fc-btn fc-btn-secondary",
2477
- onClick: handleDisable,
2478
- disabled: loading || code.length !== 6,
2479
- style: { marginTop: 10, background: "rgba(220, 38, 38, 0.1)", color: "#dc2626", borderColor: "rgba(220, 38, 38, 0.2)" },
2480
- children: loading ? "Disabling..." : "Disable 2FA"
2481
- }
2482
- ),
2483
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-switch", style: { marginTop: 12 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: goBack, children: "Back" }) })
2484
- ] })
2485
- ] }),
2486
- step === "recovery-codes" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2487
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Save your recovery codes" }),
2488
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", style: { textAlign: "center" }, children: "Store these codes somewhere safe. Each code can only be used once." }),
2489
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-recovery-grid", children: recoveryCodes.map((c, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-recovery-code", children: c }, i)) }),
2490
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { textAlign: "center", margin: "8px 0 12px" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-link", onClick: handleCopyAll, children: "Copy all" }) }),
2491
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-primary", onClick: onClose, children: "Done" })
2492
- ] })
2493
- ]
2454
+ const getOptions = {};
2455
+ if (useBrowserAutofill) {
2456
+ if (!await browserSupportsWebAuthnAutofill()) {
2457
+ throw Error("Browser does not support WebAuthn autofill");
2494
2458
  }
2495
- ) });
2459
+ const eligibleInputs = document.querySelectorAll("input[autocomplete$='webauthn']");
2460
+ if (eligibleInputs.length < 1 && verifyBrowserAutofillInput) {
2461
+ throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');
2462
+ }
2463
+ getOptions.mediation = "conditional";
2464
+ publicKey.allowCredentials = [];
2465
+ }
2466
+ getOptions.publicKey = publicKey;
2467
+ getOptions.signal = WebAuthnAbortService.createNewAbortSignal();
2468
+ let credential;
2469
+ try {
2470
+ credential = await navigator.credentials.get(getOptions);
2471
+ } catch (err) {
2472
+ throw identifyAuthenticationError({ error: err, options: getOptions });
2473
+ }
2474
+ if (!credential) {
2475
+ throw new Error("Authentication was not completed");
2476
+ }
2477
+ const { id, rawId, response, type } = credential;
2478
+ let userHandle = void 0;
2479
+ if (response.userHandle) {
2480
+ userHandle = bufferToBase64URLString(response.userHandle);
2481
+ }
2482
+ return {
2483
+ id,
2484
+ rawId: bufferToBase64URLString(rawId),
2485
+ response: {
2486
+ authenticatorData: bufferToBase64URLString(response.authenticatorData),
2487
+ clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
2488
+ signature: bufferToBase64URLString(response.signature),
2489
+ userHandle
2490
+ },
2491
+ type,
2492
+ clientExtensionResults: credential.getClientExtensionResults(),
2493
+ authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment)
2494
+ };
2496
2495
  }
2497
2496
 
2498
2497
  // src/components/passkeys-modal.tsx
2499
2498
 
2500
-
2501
2499
  function PasskeysModal({ isOpen, onClose, onCountChange }) {
2502
2500
  const { api, getAccessToken, config } = useForgeConnect();
2503
- const theme = _nullishCoalesce(_optionalChain([config, 'access', _63 => _63.appearance, 'optionalAccess', _64 => _64.theme]), () => ( "light"));
2501
+ const theme = _nullishCoalesce(_optionalChain([config, 'access', _66 => _66.appearance, 'optionalAccess', _67 => _67.theme]), () => ( "light"));
2504
2502
  const [passkeys, setPasskeys] = _react.useState.call(void 0, []);
2505
2503
  const [loading, setLoading] = _react.useState.call(void 0, false);
2506
2504
  const [addLoading, setAddLoading] = _react.useState.call(void 0, false);
@@ -2560,7 +2558,7 @@ function PasskeysModal({ isOpen, onClose, onCountChange }) {
2560
2558
  "div",
2561
2559
  {
2562
2560
  className: "fc-modal-content",
2563
- style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _65 => _65.appearance, 'optionalAccess', _66 => _66.accentColor]), () => ( "#8b5cf6")) },
2561
+ style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _68 => _68.appearance, 'optionalAccess', _69 => _69.accentColor]), () => ( "#8b5cf6")) },
2564
2562
  "data-theme": theme,
2565
2563
  children: [
2566
2564
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "fc-modal-title", children: "Passkeys" }),
@@ -2634,7 +2632,7 @@ function ErrorView({
2634
2632
 
2635
2633
  function PasswordModal({ isOpen, onClose, hasPassword }) {
2636
2634
  const { api, getAccessToken, config } = useForgeConnect();
2637
- const theme = _nullishCoalesce(_optionalChain([config, 'access', _67 => _67.appearance, 'optionalAccess', _68 => _68.theme]), () => ( "light"));
2635
+ const theme = _nullishCoalesce(_optionalChain([config, 'access', _70 => _70.appearance, 'optionalAccess', _71 => _71.theme]), () => ( "light"));
2638
2636
  const [step, setStep] = _react.useState.call(void 0, "form");
2639
2637
  const [currentPassword, setCurrentPassword] = _react.useState.call(void 0, "");
2640
2638
  const [newPassword, setNewPassword] = _react.useState.call(void 0, "");
@@ -2671,7 +2669,7 @@ function PasswordModal({ isOpen, onClose, hasPassword }) {
2671
2669
  "div",
2672
2670
  {
2673
2671
  className: "fc-modal-content",
2674
- style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _69 => _69.appearance, 'optionalAccess', _70 => _70.accentColor]), () => ( "#8b5cf6")) },
2672
+ style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _72 => _72.appearance, 'optionalAccess', _73 => _73.accentColor]), () => ( "#8b5cf6")) },
2675
2673
  "data-theme": theme,
2676
2674
  children: step === "done" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", style: { textAlign: "center", padding: "24px 0" }, children: [
2677
2675
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-success", children: [
@@ -2740,7 +2738,7 @@ function PasswordModal({ isOpen, onClose, hasPassword }) {
2740
2738
 
2741
2739
  function DeleteAccountModal({ isOpen, onClose, onDeleted }) {
2742
2740
  const { api, getAccessToken, config, logout } = useForgeConnect();
2743
- const theme = _nullishCoalesce(_optionalChain([config, 'access', _71 => _71.appearance, 'optionalAccess', _72 => _72.theme]), () => ( "light"));
2741
+ const theme = _nullishCoalesce(_optionalChain([config, 'access', _74 => _74.appearance, 'optionalAccess', _75 => _75.theme]), () => ( "light"));
2744
2742
  const [step, setStep] = _react.useState.call(void 0, "confirm");
2745
2743
  const [code, setCode] = _react.useState.call(void 0, "");
2746
2744
  const [loading, setLoading] = _react.useState.call(void 0, false);
@@ -2800,7 +2798,7 @@ function DeleteAccountModal({ isOpen, onClose, onDeleted }) {
2800
2798
  "div",
2801
2799
  {
2802
2800
  className: "fc-modal-content",
2803
- style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _73 => _73.appearance, 'optionalAccess', _74 => _74.accentColor]), () => ( "#8b5cf6")) },
2801
+ style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _76 => _76.appearance, 'optionalAccess', _77 => _77.accentColor]), () => ( "#8b5cf6")) },
2804
2802
  "data-theme": theme,
2805
2803
  children: [
2806
2804
  step === "confirm" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
@@ -2927,20 +2925,20 @@ function AccountModal() {
2927
2925
  prevLinkOpen.current = linkModal.isOpen;
2928
2926
  }, [linkModal.isOpen]);
2929
2927
  if (!accountModal.isOpen) return null;
2930
- const theme = _nullishCoalesce(_optionalChain([config, 'access', _75 => _75.appearance, 'optionalAccess', _76 => _76.theme]), () => ( "light"));
2931
- const initial = (_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _77 => _77.displayName]), () => ( _optionalChain([user, 'optionalAccess', _78 => _78.primaryEmail]))), () => ( "?"))).charAt(0).toUpperCase();
2928
+ const theme = _nullishCoalesce(_optionalChain([config, 'access', _78 => _78.appearance, 'optionalAccess', _79 => _79.theme]), () => ( "light"));
2929
+ const initial = (_nullishCoalesce(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _80 => _80.displayName]), () => ( _optionalChain([user, 'optionalAccess', _81 => _81.primaryEmail]))), () => ( "?"))).charAt(0).toUpperCase();
2932
2930
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ModalOverlay, { isOpen: accountModal.isOpen, onClose: closeAccountModal, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2933
2931
  "div",
2934
2932
  {
2935
2933
  className: "fc-modal-content",
2936
- style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _79 => _79.appearance, 'optionalAccess', _80 => _80.accentColor]), () => ( "#8b5cf6")) },
2934
+ style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _82 => _82.appearance, 'optionalAccess', _83 => _83.accentColor]), () => ( "#8b5cf6")) },
2937
2935
  "data-theme": theme,
2938
2936
  children: [
2939
2937
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-account-hero", children: [
2940
- _optionalChain([user, 'optionalAccess', _81 => _81.avatarUrl]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: user.avatarUrl, alt: "", className: "fc-account-hero-avatar" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-account-hero-avatar fc-account-hero-avatar-placeholder", children: initial }),
2938
+ _optionalChain([user, 'optionalAccess', _84 => _84.avatarUrl]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: user.avatarUrl, alt: "", className: "fc-account-hero-avatar" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-account-hero-avatar fc-account-hero-avatar-placeholder", children: initial }),
2941
2939
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-account-hero-info", children: [
2942
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-account-hero-name", children: _nullishCoalesce(_optionalChain([user, 'optionalAccess', _82 => _82.displayName]), () => ( "Your account")) }),
2943
- _optionalChain([user, 'optionalAccess', _83 => _83.primaryEmail]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-account-hero-email", children: user.primaryEmail })
2940
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-account-hero-name", children: _nullishCoalesce(_optionalChain([user, 'optionalAccess', _85 => _85.displayName]), () => ( "Your account")) }),
2941
+ _optionalChain([user, 'optionalAccess', _86 => _86.primaryEmail]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-account-hero-email", children: user.primaryEmail })
2944
2942
  ] })
2945
2943
  ] }),
2946
2944
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-account-tabs", children: TABS.map((tab) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -2978,13 +2976,13 @@ function AccountModal() {
2978
2976
  }
2979
2977
  function ProfileTab() {
2980
2978
  const { user, updateProfile } = useUser();
2981
- const [displayName, setDisplayName] = _react.useState.call(void 0, _nullishCoalesce(_optionalChain([user, 'optionalAccess', _84 => _84.displayName]), () => ( "")));
2982
- const [avatarUrl, setAvatarUrl] = _react.useState.call(void 0, _nullishCoalesce(_optionalChain([user, 'optionalAccess', _85 => _85.avatarUrl]), () => ( "")));
2979
+ const [displayName, setDisplayName] = _react.useState.call(void 0, _nullishCoalesce(_optionalChain([user, 'optionalAccess', _87 => _87.displayName]), () => ( "")));
2980
+ const [avatarUrl, setAvatarUrl] = _react.useState.call(void 0, _nullishCoalesce(_optionalChain([user, 'optionalAccess', _88 => _88.avatarUrl]), () => ( "")));
2983
2981
  const [loading, setLoading] = _react.useState.call(void 0, false);
2984
2982
  const [msg, setMsg] = _react.useState.call(void 0, null);
2985
2983
  _react.useEffect.call(void 0, () => {
2986
- setDisplayName(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _86 => _86.displayName]), () => ( "")));
2987
- setAvatarUrl(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _87 => _87.avatarUrl]), () => ( "")));
2984
+ setDisplayName(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _89 => _89.displayName]), () => ( "")));
2985
+ setAvatarUrl(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _90 => _90.avatarUrl]), () => ( "")));
2988
2986
  }, [user]);
2989
2987
  const handleSave = async () => {
2990
2988
  setLoading(true);
@@ -3049,7 +3047,7 @@ function LoginsTab({ onLink, refreshKey }) {
3049
3047
  msg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: msg }),
3050
3048
  loading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Loading..." }),
3051
3049
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", children: "Ways you can sign in to your account." }),
3052
- _optionalChain([authMethods, 'optionalAccess', _88 => _88.map, 'call', _89 => _89((m) => {
3050
+ _optionalChain([authMethods, 'optionalAccess', _91 => _91.map, 'call', _92 => _92((m) => {
3053
3051
  const display = getMethodDisplay(m.provider);
3054
3052
  const detail = m.provider === "email" ? m.providerId : m.provider.endsWith("_wallet") ? truncate(m.providerId) : m.providerId;
3055
3053
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-account-item", children: [
@@ -3064,7 +3062,7 @@ function LoginsTab({ onLink, refreshKey }) {
3064
3062
  ] })
3065
3063
  ] }, m.id);
3066
3064
  })]),
3067
- _optionalChain([authMethods, 'optionalAccess', _90 => _90.length]) === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-empty", children: "No login methods yet" }),
3065
+ _optionalChain([authMethods, 'optionalAccess', _93 => _93.length]) === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-empty", children: "No login methods yet" }),
3068
3066
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-secondary", onClick: onLink, style: { marginTop: 8 }, children: "+ Add login method" })
3069
3067
  ] });
3070
3068
  }
@@ -3087,8 +3085,8 @@ function WalletsTab({ onLink, refreshKey }) {
3087
3085
  msg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-error", children: msg }),
3088
3086
  loading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Loading..." }),
3089
3087
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-section-desc", children: "Crypto wallets connected to your account." }),
3090
- _optionalChain([wallets, 'optionalAccess', _91 => _91.map, 'call', _92 => _92((w) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-account-item", children: [
3091
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SvgIcon, { svg: _nullishCoalesce(_optionalChain([METHOD_DISPLAY, 'access', _93 => _93[`${w.chain}_wallet`], 'optionalAccess', _94 => _94.iconHtml]), () => ( "")), className: "fc-account-item-icon" }),
3088
+ _optionalChain([wallets, 'optionalAccess', _94 => _94.map, 'call', _95 => _95((w) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-account-item", children: [
3089
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SvgIcon, { svg: _nullishCoalesce(_optionalChain([METHOD_DISPLAY, 'access', _96 => _96[`${w.chain}_wallet`], 'optionalAccess', _97 => _97.iconHtml]), () => ( "")), className: "fc-account-item-icon" }),
3092
3090
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-account-item-info", children: [
3093
3091
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "fc-account-item-label", children: [
3094
3092
  w.chain.charAt(0).toUpperCase() + w.chain.slice(1),
@@ -3098,7 +3096,7 @@ function WalletsTab({ onLink, refreshKey }) {
3098
3096
  ] }),
3099
3097
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-account-item-actions", children: !w.isPrimary && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn-primary-sm", onClick: () => handleSetPrimary(w.id), children: "Make primary" }) })
3100
3098
  ] }, w.id))]),
3101
- _optionalChain([wallets, 'optionalAccess', _95 => _95.length]) === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-empty", children: "No wallets connected" }),
3099
+ _optionalChain([wallets, 'optionalAccess', _98 => _98.length]) === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-empty", children: "No wallets connected" }),
3102
3100
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn fc-btn-secondary", onClick: onLink, style: { marginTop: 8 }, children: "+ Connect wallet" })
3103
3101
  ] });
3104
3102
  }
@@ -3133,7 +3131,7 @@ function SecurityTab() {
3133
3131
  refreshStatus();
3134
3132
  refreshPasskeyCount();
3135
3133
  }, [fetchSessions, fetchAuthMethods, refreshStatus, refreshPasskeyCount]);
3136
- const hasPassword = _optionalChain([userAuthMethods, 'optionalAccess', _96 => _96.some, 'call', _97 => _97((m) => m.provider === "email")]);
3134
+ const hasPassword = _optionalChain([userAuthMethods, 'optionalAccess', _99 => _99.some, 'call', _100 => _100((m) => m.provider === "email")]);
3137
3135
  const handleRevoke = async (id) => {
3138
3136
  setMsg("");
3139
3137
  try {
@@ -3167,7 +3165,7 @@ function SecurityTab() {
3167
3165
  ] }),
3168
3166
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChevronRight, {})
3169
3167
  ] }),
3170
- _optionalChain([user, 'optionalAccess', _98 => _98.primaryEmail]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3168
+ _optionalChain([user, 'optionalAccess', _101 => _101.primaryEmail]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3171
3169
  "button",
3172
3170
  {
3173
3171
  type: "button",
@@ -3188,7 +3186,7 @@ function SecurityTab() {
3188
3186
  ),
3189
3187
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-divider", style: { margin: "16px 0" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "active sessions" }) }),
3190
3188
  loading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "Loading..." }),
3191
- _optionalChain([sessions, 'optionalAccess', _99 => _99.map, 'call', _100 => _100((s) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-account-item", children: [
3189
+ _optionalChain([sessions, 'optionalAccess', _102 => _102.map, 'call', _103 => _103((s) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-account-item", children: [
3192
3190
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "fc-account-item-icon", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", children: [
3193
3191
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "3", width: "16", height: "11", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
3194
3192
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M7 17h6M10 14v3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
@@ -3204,7 +3202,7 @@ function SecurityTab() {
3204
3202
  ] }),
3205
3203
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-account-item-actions", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "fc-btn-danger-sm", onClick: () => handleRevoke(s.id), children: "Sign out" }) })
3206
3204
  ] }, s.id))]),
3207
- _optionalChain([sessions, 'optionalAccess', _101 => _101.length]) === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-empty", children: "No active sessions" }),
3205
+ _optionalChain([sessions, 'optionalAccess', _104 => _104.length]) === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-account-empty", children: "No active sessions" }),
3208
3206
  sessions && sessions.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3209
3207
  "button",
3210
3208
  {
@@ -3251,7 +3249,7 @@ function SecurityTab() {
3251
3249
  onCountChange: (count) => setPasskeyCount(count)
3252
3250
  }
3253
3251
  ),
3254
- _optionalChain([user, 'optionalAccess', _102 => _102.primaryEmail]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3252
+ _optionalChain([user, 'optionalAccess', _105 => _105.primaryEmail]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3255
3253
  PasswordModal,
3256
3254
  {
3257
3255
  isOpen: showPasswordModal,
@@ -3296,7 +3294,7 @@ function LinkAuthModal() {
3296
3294
  if (!linkModal.isOpen) return;
3297
3295
  const handleMessage = (event) => {
3298
3296
  if (event.origin !== window.location.origin) return;
3299
- if (_optionalChain([event, 'access', _103 => _103.data, 'optionalAccess', _104 => _104.type]) === "fc_oauth_link_success") {
3297
+ if (_optionalChain([event, 'access', _106 => _106.data, 'optionalAccess', _107 => _107.type]) === "fc_oauth_link_success") {
3300
3298
  setStep("success");
3301
3299
  setTimeout(() => {
3302
3300
  handleClose();
@@ -3307,7 +3305,7 @@ function LinkAuthModal() {
3307
3305
  return () => window.removeEventListener("message", handleMessage);
3308
3306
  }, [linkModal.isOpen]);
3309
3307
  if (!linkModal.isOpen) return null;
3310
- const theme = _nullishCoalesce(_optionalChain([config, 'access', _105 => _105.appearance, 'optionalAccess', _106 => _106.theme]), () => ( "light"));
3308
+ const theme = _nullishCoalesce(_optionalChain([config, 'access', _108 => _108.appearance, 'optionalAccess', _109 => _109.theme]), () => ( "light"));
3311
3309
  const handleClose = () => {
3312
3310
  setStep("method-select");
3313
3311
  closeLinkModal();
@@ -3330,7 +3328,7 @@ function LinkAuthModal() {
3330
3328
  "div",
3331
3329
  {
3332
3330
  className: "fc-modal-content",
3333
- style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _107 => _107.appearance, 'optionalAccess', _108 => _108.accentColor]), () => ( "#8b5cf6")) },
3331
+ style: { "--fc-accent": _nullishCoalesce(_optionalChain([config, 'access', _110 => _110.appearance, 'optionalAccess', _111 => _111.accentColor]), () => ( "#8b5cf6")) },
3334
3332
  "data-theme": theme,
3335
3333
  children: step === "success" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SuccessView2, {}) : step === "error" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3336
3334
  ErrorView,
@@ -3346,7 +3344,7 @@ function LinkAuthModal() {
3346
3344
  AuthMethodSelectStep,
3347
3345
  {
3348
3346
  config,
3349
- connectedProviders: _nullishCoalesce(_optionalChain([authMethods, 'optionalAccess', _109 => _109.map, 'call', _110 => _110((m) => m.provider)]), () => ( [])),
3347
+ connectedProviders: _nullishCoalesce(_optionalChain([authMethods, 'optionalAccess', _112 => _112.map, 'call', _113 => _113((m) => m.provider)]), () => ( [])),
3350
3348
  onSelectEmail: () => setStep("email"),
3351
3349
  onSelectOtp: () => setStep("otp"),
3352
3350
  onOAuth: handleOAuthDirect
@@ -3565,20 +3563,21 @@ function WalletLinkStep({ onBack, onSuccess, onFatalError }) {
3565
3563
  const [coldWallet, setColdWallet] = _react.useState.call(void 0, false);
3566
3564
  const mobile = _react.useMemo.call(void 0, () => isMobile(), []);
3567
3565
  const walletConfig = config.walletConfig;
3568
- const preferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _111 => _111.preferredWallets]), () => ( []));
3569
- const onlyPreferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _112 => _112.onlyPreferred]), () => ( false));
3566
+ const preferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _114 => _114.preferredWallets]), () => ( []));
3567
+ const onlyPreferred = _nullishCoalesce(_optionalChain([walletConfig, 'optionalAccess', _115 => _115.onlyPreferred]), () => ( false));
3570
3568
  const coldWalletRef = _react.useRef.call(void 0, coldWallet);
3571
3569
  coldWalletRef.current = coldWallet;
3572
3570
  const buildSignTxFnForAdapter = _react.useCallback.call(void 0, (adapter) => {
3573
3571
  if (!adapter.signTransaction) return void 0;
3572
+ const TxClass = _optionalChain([walletConfig, 'optionalAccess', _116 => _116.Transaction]);
3573
+ if (!TxClass) return void 0;
3574
3574
  return async (txBase64) => {
3575
- const { Transaction } = await importSolanaWeb3();
3576
3575
  const bytes = Uint8Array.from(atob(txBase64), (c) => c.charCodeAt(0));
3577
- const tx = Transaction.from(bytes);
3576
+ const tx = TxClass.from(bytes);
3578
3577
  const signedTx = await adapter.signTransaction(tx);
3579
3578
  return btoa(String.fromCharCode(...new Uint8Array(signedTx.serialize())));
3580
3579
  };
3581
- }, []);
3580
+ }, [_optionalChain([walletConfig, 'optionalAccess', _117 => _117.Transaction])]);
3582
3581
  const handleConnect = async (w) => {
3583
3582
  if (w.readyState !== "Installed") {
3584
3583
  if (mobile) {
@@ -3619,12 +3618,12 @@ function WalletLinkStep({ onBack, onSuccess, onFatalError }) {
3619
3618
  const prefSet = new Set(preferred);
3620
3619
  const others = all.filter((w) => !prefSet.has(w.adapter.name) && w.readyState === "Installed");
3621
3620
  return { preferredWallets: prefList, otherWallets: others };
3622
- }, [_optionalChain([walletAdapter, 'optionalAccess', _113 => _113.wallets]), walletConfig]);
3621
+ }, [_optionalChain([walletAdapter, 'optionalAccess', _118 => _118.wallets]), walletConfig]);
3623
3622
  const mobileExtraWallets = _react.useMemo.call(void 0, () => {
3624
3623
  if (!mobile || !walletAdapter) return [];
3625
3624
  const adapterNames = new Set(walletAdapter.wallets.map((w) => w.adapter.name));
3626
3625
  return MOBILE_WALLETS.filter((mw) => !adapterNames.has(mw.name));
3627
- }, [mobile, _optionalChain([walletAdapter, 'optionalAccess', _114 => _114.wallets])]);
3626
+ }, [mobile, _optionalChain([walletAdapter, 'optionalAccess', _119 => _119.wallets])]);
3628
3627
  if (!walletAdapter && mobile) {
3629
3628
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fc-tab", children: [
3630
3629
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "fc-wallet-list", children: MOBILE_WALLETS.map((mw) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -3720,7 +3719,7 @@ function WalletLinkStep({ onBack, onSuccess, onFatalError }) {
3720
3719
  ] }, w.adapter.name))
3721
3720
  ] }),
3722
3721
  preferredWallets.length === 0 && otherWallets.length === 0 && mobileExtraWallets.length === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "fc-text", children: "No wallet found. Please install a Solana wallet (like Phantom) to continue." }),
3723
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-cold-wallet-toggle", children: [
3722
+ _optionalChain([walletConfig, 'optionalAccess', _120 => _120.Transaction]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "fc-cold-wallet-toggle", children: [
3724
3723
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3725
3724
  "input",
3726
3725
  {
@@ -3821,7 +3820,7 @@ function ForgeConnectProvider({ config, children, onLogin, onLogout, walletAdapt
3821
3820
  }
3822
3821
  const handleMessage = async (event) => {
3823
3822
  if (event.origin !== window.location.origin) return;
3824
- if (_optionalChain([event, 'access', _115 => _115.data, 'optionalAccess', _116 => _116.type]) !== "fc_oauth_code") return;
3823
+ if (_optionalChain([event, 'access', _121 => _121.data, 'optionalAccess', _122 => _122.type]) !== "fc_oauth_code") return;
3825
3824
  const code = event.data.code;
3826
3825
  if (!code) return;
3827
3826
  try {
@@ -3837,7 +3836,7 @@ function ForgeConnectProvider({ config, children, onLogin, onLogout, walletAdapt
3837
3836
  const user = await api.getMe(token);
3838
3837
  setAuth({ status: "authenticated", user, accessToken: token });
3839
3838
  scheduleRefresh(token);
3840
- _optionalChain([onLogin, 'optionalCall', _117 => _117(user)]);
3839
+ _optionalChain([onLogin, 'optionalCall', _123 => _123(user)]);
3841
3840
  setTimeout(() => {
3842
3841
  setModal({ isOpen: false, step: "method-select" });
3843
3842
  }, 1500);
@@ -3863,7 +3862,7 @@ function ForgeConnectProvider({ config, children, onLogin, onLogout, walletAdapt
3863
3862
  setAuth({ status: "authenticated", user, accessToken: token });
3864
3863
  scheduleRefresh(token);
3865
3864
  setModal({ isOpen: true, step: "success" });
3866
- _optionalChain([onLogin, 'optionalCall', _118 => _118(user)]);
3865
+ _optionalChain([onLogin, 'optionalCall', _124 => _124(user)]);
3867
3866
  setTimeout(() => {
3868
3867
  setModal({ isOpen: false, step: "method-select" });
3869
3868
  }, 1500);
@@ -3963,7 +3962,7 @@ function ForgeConnectProvider({ config, children, onLogin, onLogout, walletAdapt
3963
3962
  const token = auth.accessToken;
3964
3963
  if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
3965
3964
  setAuth({ status: "unauthenticated", user: null, accessToken: null });
3966
- _optionalChain([onLogout, 'optionalCall', _119 => _119()]);
3965
+ _optionalChain([onLogout, 'optionalCall', _125 => _125()]);
3967
3966
  if (token) {
3968
3967
  try {
3969
3968
  await api.logout(token);
@@ -4017,7 +4016,7 @@ function ForgeConnectProvider({ config, children, onLogin, onLogout, walletAdapt
4017
4016
  const token = auth.accessToken;
4018
4017
  if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
4019
4018
  setAuth({ status: "unauthenticated", user: null, accessToken: null });
4020
- _optionalChain([onLogout, 'optionalCall', _120 => _120()]);
4019
+ _optionalChain([onLogout, 'optionalCall', _126 => _126()]);
4021
4020
  if (token) {
4022
4021
  try {
4023
4022
  await api.logoutAll(token);
@@ -4202,11 +4201,11 @@ function useAdmin() {
4202
4201
  const token = getAccessToken();
4203
4202
  if (!token) throw new Error("Please sign in to continue.");
4204
4203
  await api.adminUpdateUserStatus(token, id, status);
4205
- if (_optionalChain([selectedUser, 'optionalAccess', _121 => _121.id]) === id) {
4204
+ if (_optionalChain([selectedUser, 'optionalAccess', _127 => _127.id]) === id) {
4206
4205
  await getUser(id);
4207
4206
  }
4208
4207
  },
4209
- [api, getAccessToken, _optionalChain([selectedUser, 'optionalAccess', _122 => _122.id]), getUser]
4208
+ [api, getAccessToken, _optionalChain([selectedUser, 'optionalAccess', _128 => _128.id]), getUser]
4210
4209
  );
4211
4210
  const getUserSessions = _react.useCallback.call(void 0,
4212
4211
  async (id) => {
@@ -4322,9 +4321,9 @@ function useRoles() {
4322
4321
  const token = getAccessToken();
4323
4322
  if (!token) throw new Error("Please sign in to continue.");
4324
4323
  await api.adminDeleteRole(token, id);
4325
- if (_optionalChain([selectedRole, 'optionalAccess', _123 => _123.id]) === id) setSelectedRole(null);
4324
+ if (_optionalChain([selectedRole, 'optionalAccess', _129 => _129.id]) === id) setSelectedRole(null);
4326
4325
  },
4327
- [api, getAccessToken, _optionalChain([selectedRole, 'optionalAccess', _124 => _124.id])]
4326
+ [api, getAccessToken, _optionalChain([selectedRole, 'optionalAccess', _130 => _130.id])]
4328
4327
  );
4329
4328
  const getPermissions = _react.useCallback.call(void 0,
4330
4329
  async () => {