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