UNPKG

@avalabs/avacloud-waas-react

Version:
1,439 lines (1,418 loc) 192 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { AvaCloudWalletProvider: () => AvaCloudWalletProvider, ExportView: () => ExportView, GaslessProvider: () => GaslessProvider, LoginButton: () => LoginButton, ReceiveView: () => ReceiveView, SendView: () => SendView, ThemeProvider: () => ThemeProvider, TokensView: () => TokensView, UserProfile: () => UserProfile, VM: () => VM, WalletButton: () => WalletButton, WalletCard: () => WalletCard, WalletDisplay: () => WalletDisplay, avaCloudWallet: () => avaCloudWallet, useAuth: () => useAuth, useAvaCloudWallet: () => useAvaCloudWallet, useBlockchain: () => useBlockchain, useChainId: () => useChainId, useGaslessTransaction: () => useGaslessTransaction, useGlacier: () => useGlacier, usePostMessage: () => usePostMessage, useSignMessage: () => useSignMessage, useSignTransaction: () => useSignTransaction, useThemeMode: () => useThemeMode, useTransferTokens: () => useTransferTokens, useUserWallets: () => useUserWallets }); module.exports = __toCommonJS(index_exports); // src/AvaCloudWalletProvider.tsx var import_react9 = require("react"); var import_react_query2 = require("@tanstack/react-query"); var import_cubesigner_sdk = require("@cubist-labs/cubesigner-sdk"); // src/types/vm.ts var VM = /* @__PURE__ */ ((VM2) => { VM2["EVM"] = "EVM"; VM2["AVM"] = "AVM"; VM2["PVM"] = "PVM"; return VM2; })(VM || {}); // src/utils/derivationPath.ts var getCoinIndexForVm = (vm) => { switch (vm) { case "EVM" /* EVM */: return 60; case "AVM" /* AVM */: case "PVM" /* PVM */: return 9e3; default: throw new Error(`Unknown coin index for vm: ${vm}`); } }; function getDerivationPath(vm, accountIndex) { if (accountIndex < 0 || Math.round(accountIndex) !== accountIndex) { throw new Error("Account index must be a non-negative integer"); } const coinIndex = getCoinIndexForVm(vm); return `m/44'/${coinIndex}'/0'/0/${accountIndex}`; } // src/hooks/usePostMessage.ts var import_react = require("react"); // src/constants/storage.ts var OIDC_TOKEN_KEY = "avacloud-auth-oidc-token"; var AUTH_TOKENS_KEY = "auth_tokens"; var AUTH0_STORAGE_KEYS = { IS_AUTHENTICATED: "auth0.is.authenticated", ACCESS_TOKEN: "auth0.access_token", ID_TOKEN: "auth0.id_token", EXPIRES_AT: "auth0.expires_at" }; var CUBIST_USER_ID_KEY = "cubist_user_id"; var ORG_CONFIG_CACHE_KEY = "avacloud-org-config-cache"; // src/hooks/usePostMessage.ts var globalAuthState = { signupInProgress: false, loginInProgress: false, lastSignupTimestamp: 0, lastLoginTimestamp: 0, processingMessageIds: /* @__PURE__ */ new Set() }; function cleanupProcessedMessageIds() { if (globalAuthState.processingMessageIds.size > 100) { const messageIds = Array.from(globalAuthState.processingMessageIds); globalAuthState.processingMessageIds = new Set(messageIds.slice(-50)); } } function usePostMessage({ authServiceUrl, orgId, environment, iframe, isIframeReady, onAuthSuccess, onAuthError, onOidcReceived, onOrgConfigUpdate, setIsAuthenticated, setUser, setIsLoading, setIsIframeReady, cubistClient }) { const lastAuthStateRef = (0, import_react.useRef)({ isAuthenticated: false, userId: null, lastUpdateTime: 0 }); const hasRequestedOidcRef = (0, import_react.useRef)(false); const isHandlingMessageRef = (0, import_react.useRef)(false); const hasLoadedCacheRef = (0, import_react.useRef)(false); (0, import_react.useEffect)(() => { if (orgId && onOrgConfigUpdate && !hasLoadedCacheRef.current) { hasLoadedCacheRef.current = true; try { const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`; const cachedConfigJson = localStorage.getItem(cachedConfigKey); if (cachedConfigJson) { const cachedConfig = JSON.parse(cachedConfigJson); const timestamp = cachedConfig._timestamp || 0; const isExpired = Date.now() - timestamp > 30 * 60 * 1e3; if (!isExpired) { const { _timestamp, ...configWithoutTimestamp } = cachedConfig; onOrgConfigUpdate(configWithoutTimestamp); } } } catch (error) { } } }, [orgId, environment, onOrgConfigUpdate]); const sendMessage = (0, import_react.useCallback)((message) => { if (iframe == null ? void 0 : iframe.contentWindow) { try { if (message.type === "SIGNUP_REQUEST") { if (globalAuthState.signupInProgress) { return; } const now = Date.now(); if (now - globalAuthState.lastSignupTimestamp < 3e3) { return; } globalAuthState.signupInProgress = true; globalAuthState.lastSignupTimestamp = now; let finalMessage = message; if (!message.requestId) { finalMessage = { ...message, requestId: `signup-${now}` }; } let messageToSend = finalMessage; if (finalMessage.payload && typeof finalMessage.payload.email === "string" && typeof finalMessage.payload.password === "string") { messageToSend = { type: "SIGNUP_REQUEST", email: finalMessage.payload.email, password: finalMessage.payload.password, requestId: finalMessage.requestId || `signup-${now}` }; } if ("requestId" in messageToSend && messageToSend.requestId) { globalAuthState.processingMessageIds.add(messageToSend.requestId); } iframe.contentWindow.postMessage(messageToSend, authServiceUrl); return; } if (message.type === "LOGIN_REQUEST") { if (globalAuthState.loginInProgress) { return; } const now = Date.now(); if (now - globalAuthState.lastLoginTimestamp < 3e3) { return; } globalAuthState.loginInProgress = true; globalAuthState.lastLoginTimestamp = now; let finalMessage = message; if (!message.requestId) { finalMessage = { ...message, requestId: `login-${now}` }; } if (finalMessage.requestId) { globalAuthState.processingMessageIds.add(finalMessage.requestId); } iframe.contentWindow.postMessage(finalMessage, authServiceUrl); return; } iframe.contentWindow.postMessage(message, authServiceUrl); } catch (error) { if (message.type === "SIGNUP_REQUEST") { globalAuthState.signupInProgress = false; } if (message.type === "LOGIN_REQUEST") { globalAuthState.loginInProgress = false; } } } }, [iframe, authServiceUrl]); (0, import_react.useEffect)(() => { const handleMessage = async (event) => { var _a, _b, _c, _d, _e, _f, _g; if (isHandlingMessageRef.current) { return; } if (event.origin !== new URL(authServiceUrl).origin) { return; } if (typeof ((_a = event.data) == null ? void 0 : _a.type) !== "string") { return; } if (event.data.requestId && globalAuthState.processingMessageIds.has(event.data.requestId)) { return; } try { isHandlingMessageRef.current = true; if (event.data.type === "ERROR") { globalAuthState.signupInProgress = false; globalAuthState.loginInProgress = false; } else if (event.data.type === "AUTH_STATUS" && event.data.isAuthenticated) { globalAuthState.signupInProgress = false; globalAuthState.loginInProgress = false; cleanupProcessedMessageIds(); } else if (event.data.type === "RECEIVE_OIDC") { globalAuthState.signupInProgress = false; globalAuthState.loginInProgress = false; } switch (event.data.type) { case "IFRAME_READY": setIsIframeReady(true); break; case "RECEIVE_OIDC": if (typeof ((_b = event.data.payload) == null ? void 0 : _b.idToken) === "string") { const oidcToken = event.data.payload.idToken; hasRequestedOidcRef.current = false; onOidcReceived == null ? void 0 : onOidcReceived(oidcToken); } else { hasRequestedOidcRef.current = false; } break; case "AUTH_STATUS": { const newIsAuthenticated = !!event.data.isAuthenticated; const newUserId = (_d = (_c = event.data.user) == null ? void 0 : _c.sub) != null ? _d : null; const now = Date.now(); if (now - lastAuthStateRef.current.lastUpdateTime < 500) { return; } const authStateChanged = lastAuthStateRef.current.isAuthenticated !== newIsAuthenticated || lastAuthStateRef.current.userId !== newUserId; if (authStateChanged) { setIsAuthenticated(newIsAuthenticated); if (event.data.user) { const userInfo = { email: event.data.user.email, sub: event.data.user.sub, configured_mfa: [], displayName: event.data.user.nickname || event.data.user.name || ((_e = event.data.user.email) == null ? void 0 : _e.split("@")[0]) || "User", rawUserData: event.data.user }; setUser(userInfo); if (newIsAuthenticated && !cubistClient && !hasRequestedOidcRef.current) { hasRequestedOidcRef.current = true; sendMessage({ type: "GET_OIDC" }); return; } } else { setUser(null); localStorage.removeItem(AUTH_TOKENS_KEY); localStorage.removeItem(AUTH0_STORAGE_KEYS.IS_AUTHENTICATED); sessionStorage.removeItem(OIDC_TOKEN_KEY); } lastAuthStateRef.current = { isAuthenticated: newIsAuthenticated, userId: newUserId, lastUpdateTime: now }; if (newIsAuthenticated && event.data.user) { if (!hasRequestedOidcRef.current) { if (event.data.tokens) { localStorage.setItem(AUTH_TOKENS_KEY, JSON.stringify(event.data.tokens)); } onAuthSuccess == null ? void 0 : onAuthSuccess(); } } } if (event.data.orgConfig && onOrgConfigUpdate) { onOrgConfigUpdate(event.data.orgConfig); if (orgId) { try { const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`; const configWithTimestamp = { ...event.data.orgConfig, _timestamp: Date.now() }; localStorage.setItem(cachedConfigKey, JSON.stringify(configWithTimestamp)); } catch (error) { } } } if (!hasRequestedOidcRef.current) { setIsLoading(false); } break; } case "REGISTER_SUCCESS": { const userId = (_f = event.data.payload) == null ? void 0 : _f.userId; if (userId) { localStorage.setItem(CUBIST_USER_ID_KEY, userId); if (!hasRequestedOidcRef.current) { hasRequestedOidcRef.current = true; sendMessage({ type: "GET_OIDC" }); } } break; } case "ERROR": if (event.data.error === "User not authenticated in iframe") { isHandlingMessageRef.current = false; return; } onAuthError == null ? void 0 : onAuthError(new Error((_g = event.data.error) != null ? _g : "Unknown error")); setIsLoading(false); break; } } finally { isHandlingMessageRef.current = false; } }; window.addEventListener("message", handleMessage); return () => window.removeEventListener("message", handleMessage); }, [ authServiceUrl, onAuthError, onAuthSuccess, onOidcReceived, onOrgConfigUpdate, setIsAuthenticated, setIsIframeReady, setIsLoading, setUser, sendMessage, cubistClient, orgId, environment ]); (0, import_react.useEffect)(() => { if (isIframeReady && (iframe == null ? void 0 : iframe.contentWindow)) { sendMessage({ type: "CHECK_AUTH_STATUS", payload: { orgId, environment } }); } }, [isIframeReady, iframe, sendMessage, orgId, environment]); return { sendMessage }; } // src/AuthModalContext.tsx var import_react4 = require("react"); var import_core_k2_components4 = require("@avalabs/core-k2-components"); // src/components/Modal.tsx var import_react3 = require("react"); var import_core_k2_components3 = require("@avalabs/core-k2-components"); // src/components/SignInContent.tsx var import_react2 = require("react"); var import_core_k2_components2 = require("@avalabs/core-k2-components"); // src/components/PoweredByAvaCloud.tsx var import_core_k2_components = require("@avalabs/core-k2-components"); var import_jsx_runtime = require("react/jsx-runtime"); function PoweredByAvaCloud() { return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_core_k2_components.Stack, { direction: "row", alignItems: "center", justifyContent: "center", spacing: 1, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core_k2_components.Typography, { variant: "body2", children: "Powered by" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_core_k2_components.Stack, { direction: "row", alignItems: "center", spacing: 0.5, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core_k2_components.AvaCloudConnectIcon, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core_k2_components.Typography, { variant: "body2", children: "AvaCloud" }) ] }) ] }); } // src/constants/legal.ts var TERMS_OF_SERVICE_URL = "https://app.avacloud.io/legal/waas/user-terms"; var PRIVACY_POLICY_URL = "https://www.avalabs.org/privacy-policy"; // src/components/SignInContent.tsx var import_jsx_runtime2 = require("react/jsx-runtime"); function SignInContent({ onEmailLogin, onEmailSignup, onProviderLogin, error, isSubmitting, socialLogins = ["google", "x", "apple"] }) { const [email, setEmail] = (0, import_react2.useState)(""); const [password, setPassword] = (0, import_react2.useState)(""); const [isPasswordStep, setIsPasswordStep] = (0, import_react2.useState)(false); const [isSignupMode, setIsSignupMode] = (0, import_react2.useState)(false); const providerConnectionMap = { "google": "google-oauth2", "x": "twitter", "twitter": "twitter", "facebook": "facebook", "apple": "apple" }; const renderSocialLoginButton = (loginType) => { if (!providerConnectionMap[loginType]) return null; const connectionName = providerConnectionMap[loginType]; let LoginIcon; switch (loginType) { case "google": LoginIcon = import_core_k2_components2.GoogleIcon; break; case "x": case "twitter": LoginIcon = import_core_k2_components2.XTwitterIcon; break; case "facebook": LoginIcon = import_core_k2_components2.FacebookIcon; break; case "apple": LoginIcon = import_core_k2_components2.AppleIcon; break; default: return null; } return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.IconButton, { color: "default", variant: "contained", onClick: () => onProviderLogin(connectionName), disabled: isSubmitting, sx: { display: "flex", padding: "16px", alignItems: "center", gap: "8px", borderRadius: "8px", background: "rgba(0, 0, 0, 0.02)", boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)", width: 72, height: 72, "&:hover": { background: "rgba(0, 0, 0, 0.04)" } }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LoginIcon, { sx: { width: 24, height: 24 } }) }, loginType ); }; const handleEmailSubmit = (e) => { e.preventDefault(); if (!email) return; setIsPasswordStep(true); }; const handlePasswordSubmit = (e) => { e.preventDefault(); if (!password) return; onEmailLogin(email, password); }; const handleSignupSubmit = (e) => { e.preventDefault(); if (!email || !password) return; onEmailSignup(email, password); }; const handleForgotPassword = () => { }; const handleToggleSignup = () => { setIsSignupMode(!isSignupMode); setIsPasswordStep(false); }; const titleTypography = { alignSelf: "stretch", color: (theme) => theme.palette.mode === "dark" ? "#FFFFFF" : "rgba(0, 0, 0, 0.80)", fontFamily: "Inter", fontSize: "16px", fontStyle: "normal", fontWeight: 700, lineHeight: "150%" }; if (isSignupMode) { return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 3, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Typography, { variant: "h6", sx: titleTypography, children: "Sign up with" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Stack, { direction: "row", spacing: 3, sx: { justifyContent: "center" }, children: socialLogins.map((loginType) => renderSocialLoginButton(loginType)) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Divider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Typography, { variant: "body2", color: "text.secondary", children: "or" }) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("form", { onSubmit: handleSignupSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 2, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.TextField, { placeholder: "Enter email", type: "email", value: email, onChange: (e) => setEmail(e.target.value), fullWidth: true, required: true, disabled: isSubmitting, error: !!error, helperText: error, sx: { "& .MuiOutlinedInput-root": { backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50" } } } ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.TextField, { placeholder: "Create password", type: "password", value: password, onChange: (e) => setPassword(e.target.value), fullWidth: true, required: true, disabled: isSubmitting, sx: { "& .MuiOutlinedInput-root": { backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50" } } } ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { type: "submit", variant: "contained", fullWidth: true, disabled: isSubmitting || !email || !password, sx: { height: 48, backgroundColor: "#3A65FF", borderRadius: 24, textTransform: "none", "&:hover": { backgroundColor: "#2952E6" } }, children: "Sign up" } ), /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( import_core_k2_components2.Typography, { variant: "body2", sx: { textAlign: "center", "& a": { color: "#3A65FF", textDecoration: "none", cursor: "pointer", "&:hover": { textDecoration: "underline" } } }, children: [ "Already have an account?", " ", /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", onClick: handleToggleSignup, sx: { color: "#3A65FF", textTransform: "none", padding: "0 4px", minWidth: "auto", fontWeight: 600, "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Sign in" } ) ] } ) ] }) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PoweredByAvaCloud, {}), /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( import_core_k2_components2.Typography, { variant: "body2", sx: { textAlign: "center", color: "text.secondary", fontSize: "0.75rem", "& a": { color: "inherit", textDecoration: "none", "&:hover": { textDecoration: "underline" } } }, children: [ "By connecting, you agree to the", " ", /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", component: "a", href: TERMS_OF_SERVICE_URL, target: "_blank", rel: "noopener noreferrer", sx: { color: "inherit", p: 0, minWidth: "auto", textTransform: "none", fontSize: "inherit", fontWeight: "inherit", "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Terms of Service" } ), " ", "and", " ", /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", component: "a", href: PRIVACY_POLICY_URL, target: "_blank", rel: "noopener noreferrer", sx: { color: "inherit", p: 0, minWidth: "auto", textTransform: "none", fontSize: "inherit", fontWeight: "inherit", "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Privacy Policy" } ) ] } ) ] }); } if (isPasswordStep) { return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 3, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Typography, { variant: "h6", sx: titleTypography, children: "Sign in with" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("form", { onSubmit: handlePasswordSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 2, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.TextField, { placeholder: "Enter password", type: "password", value: password, onChange: (e) => setPassword(e.target.value), fullWidth: true, required: true, disabled: isSubmitting, error: !!error, helperText: error, sx: { "& .MuiOutlinedInput-root": { backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50" } } } ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { type: "submit", variant: "contained", fullWidth: true, disabled: isSubmitting || !password, sx: { height: 48, backgroundColor: "#3A65FF", borderRadius: 24, textTransform: "none", "&:hover": { backgroundColor: "#2952E6" } }, children: "Continue" } ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Typography, { variant: "body2", sx: { textAlign: "center", "& a": { color: "#3A65FF", textDecoration: "none", cursor: "pointer", "&:hover": { textDecoration: "underline" } } }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", onClick: handleForgotPassword, sx: { color: "#3A65FF", textTransform: "none", "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Forget password?" } ) } ) ] }) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PoweredByAvaCloud, {}), /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( import_core_k2_components2.Typography, { variant: "body2", sx: { textAlign: "center", color: "text.secondary", fontSize: "0.75rem", "& a": { color: "inherit", textDecoration: "none", "&:hover": { textDecoration: "underline" } } }, children: [ "By continuing, you agree to our", " ", /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", component: "a", href: TERMS_OF_SERVICE_URL, target: "_blank", rel: "noopener noreferrer", sx: { color: "inherit", p: 0, minWidth: "auto", textTransform: "none", fontSize: "inherit", fontWeight: "inherit", "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Terms of Use" } ), " ", "and", " ", /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", component: "a", href: PRIVACY_POLICY_URL, target: "_blank", rel: "noopener noreferrer", sx: { color: "inherit", p: 0, minWidth: "auto", textTransform: "none", fontSize: "inherit", fontWeight: "inherit", "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Privacy Policy" } ) ] } ) ] }); } return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 3, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Typography, { variant: "h6", sx: titleTypography, children: "Sign in with" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Stack, { direction: "row", spacing: 3, sx: { justifyContent: "center" }, children: socialLogins.map((loginType) => renderSocialLoginButton(loginType)) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Divider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Typography, { variant: "body2", color: "text.secondary", children: "or" }) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("form", { onSubmit: handleEmailSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 2, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.TextField, { placeholder: "Enter email", type: "email", value: email, onChange: (e) => setEmail(e.target.value), fullWidth: true, required: true, disabled: isSubmitting, error: !!error, helperText: error, sx: { "& .MuiOutlinedInput-root": { backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50" } } } ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { type: "submit", variant: "contained", fullWidth: true, disabled: isSubmitting || !email, sx: { height: 48, backgroundColor: "#3A65FF", borderRadius: 24, textTransform: "none", "&:hover": { backgroundColor: "#2952E6" } }, children: "Continue" } ), /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( import_core_k2_components2.Typography, { variant: "body2", sx: { textAlign: "center", "& a": { color: "#3A65FF", textDecoration: "none", cursor: "pointer", "&:hover": { textDecoration: "underline" } } }, children: [ "Don't have an account?", " ", /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", onClick: handleToggleSignup, sx: { color: "#3A65FF", textTransform: "none", padding: "0 4px", minWidth: "auto", fontWeight: 600, "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Sign up" } ) ] } ) ] }) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PoweredByAvaCloud, {}), /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( import_core_k2_components2.Typography, { variant: "body2", sx: { textAlign: "center", color: "text.secondary", fontSize: "0.75rem", "& a": { color: "inherit", textDecoration: "none", "&:hover": { textDecoration: "underline" } } }, children: [ "By connecting, you agree to the", " ", /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", component: "a", href: TERMS_OF_SERVICE_URL, target: "_blank", rel: "noopener noreferrer", sx: { color: "inherit", p: 0, minWidth: "auto", textTransform: "none", fontSize: "inherit", fontWeight: "inherit", "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Terms of Service" } ), " ", "and", " ", /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_core_k2_components2.Button, { variant: "text", component: "a", href: PRIVACY_POLICY_URL, target: "_blank", rel: "noopener noreferrer", sx: { color: "inherit", p: 0, minWidth: "auto", textTransform: "none", fontSize: "inherit", fontWeight: "inherit", "&:hover": { textDecoration: "underline", backgroundColor: "transparent" } }, children: "Privacy Policy" } ) ] } ) ] }); } // src/components/Modal.tsx var import_jsx_runtime3 = require("react/jsx-runtime"); function LoginModal({ open, onClose }) { var _a; const { iframe, orgConfig, signup } = useAvaCloudWallet(); const [isSubmitting, setIsSubmitting] = (0, import_react3.useState)(false); const [error, setError] = (0, import_react3.useState)(""); const timeoutIdRef = (0, import_react3.useRef)(null); const signupInProgressRef = (0, import_react3.useRef)(false); const lastSignupAttemptRef = (0, import_react3.useRef)(0); const socialLogins = (_a = orgConfig == null ? void 0 : orgConfig.adminPortalSettings) == null ? void 0 : _a.socialLogins; (0, import_react3.useEffect)(() => { let requestInProgress = false; const handleMessage = (event) => { if (!event.data || typeof event.data.type !== "string") { return; } if (event.data.type === "ERROR") { if (event.data.payload === "User not authenticated in iframe") { return; } setError(event.data.payload); setIsSubmitting(false); signupInProgressRef.current = false; if (timeoutIdRef.current) { clearTimeout(timeoutIdRef.current); timeoutIdRef.current = null; } } else if (event.data.type === "AUTH_STATUS" && event.data.isAuthenticated) { setIsSubmitting(false); signupInProgressRef.current = false; requestInProgress = false; if (timeoutIdRef.current) { clearTimeout(timeoutIdRef.current); timeoutIdRef.current = null; } onClose(); } else if (event.data.type === "RECEIVE_OIDC") { signupInProgressRef.current = false; requestInProgress = false; } }; window.addEventListener("message", handleMessage); return () => { window.removeEventListener("message", handleMessage); if (timeoutIdRef.current) { clearTimeout(timeoutIdRef.current); timeoutIdRef.current = null; } }; }, [onClose]); const handleProviderLogin = (provider) => { var _a2; setError(""); if (!iframe) { setError("Authentication service not available"); return; } (_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({ type: "LOGIN_REQUEST", connection: provider, requestId: `login-${Date.now()}` }, "*"); onClose(); }; const handleEmailLogin = (email, password) => { var _a2; setError(""); setIsSubmitting(true); if (!iframe) { setError("Authentication service not available"); setIsSubmitting(false); return; } if (timeoutIdRef.current) { clearTimeout(timeoutIdRef.current); timeoutIdRef.current = null; } (_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({ type: "LOGIN_REQUEST", email, password, requestId: `login-${Date.now()}` }, "*"); timeoutIdRef.current = setTimeout(() => { setError("Authentication service timed out"); setIsSubmitting(false); timeoutIdRef.current = null; }, 1e4); }; const handleEmailSignup = (email, password) => { if (signupInProgressRef.current) { return; } const now = Date.now(); if (now - lastSignupAttemptRef.current < 2e3) { return; } lastSignupAttemptRef.current = now; setError(""); setIsSubmitting(true); signupInProgressRef.current = true; if (timeoutIdRef.current) { clearTimeout(timeoutIdRef.current); timeoutIdRef.current = null; } try { signup(email, password); } catch (error2) { setError("Failed to initiate signup"); setIsSubmitting(false); signupInProgressRef.current = false; return; } timeoutIdRef.current = setTimeout(() => { setError("Authentication service timed out"); setIsSubmitting(false); signupInProgressRef.current = false; timeoutIdRef.current = null; }, 1e4); }; return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)( import_core_k2_components3.Dialog, { open, maxWidth: "xs", PaperProps: { sx: { borderRadius: "8px", width: "100%", maxWidth: 400, maxHeight: "calc(100% - 64px)", m: 2, overflow: "visible", bgcolor: (theme) => theme.palette.mode === "dark" ? "#1A1A1A" : "#ffffff", backgroundImage: "none", display: "flex", flexDirection: "column", position: "relative", boxShadow: (theme) => theme.palette.mode === "dark" ? "0px 4px 6px 0px rgba(0, 0, 0, 0.3), 0px 15px 15px 0px rgba(0, 0, 0, 0.25)" : "0px 4px 6px 0px rgba(0, 0, 0, 0.16), 0px 15px 15px 0px rgba(0, 0, 0, 0.15)", transition: "all 0.2s ease-in-out" } }, children: [ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)( import_core_k2_components3.Stack, { direction: "row", sx: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", alignSelf: "stretch", p: 3, pb: 0 }, children: [ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)( "img", { src: "https://images.ctfassets.net/9bazykntljf6/58QaXZf2yQ7MqI9A8MrKiX/d8f986355c6e321e1dee79f6e91575ec/avacloud.png", alt: "AvaCloud", style: { height: 24, objectFit: "contain" } } ), /* @__PURE__ */ (0, import_jsx_runtime3.jsx)( import_core_k2_components3.IconButton, { onClick: onClose, size: "small", sx: { color: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.54)" : "rgba(0, 0, 0, 0.54)", padding: "4px", marginTop: "-4px", marginRight: "-4px", "&:hover": { backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.04)" : "rgba(0, 0, 0, 0.04)" } }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core_k2_components3.XIcon, { sx: { fontSize: 20 } }) } ) ] } ), /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core_k2_components3.DialogContent, { sx: { p: 3 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)( SignInContent, { onEmailLogin: handleEmailLogin, onEmailSignup: handleEmailSignup, onProviderLogin: handleProviderLogin, error, isSubmitting, socialLogins } ) }) ] } ); } // src/AuthModalContext.tsx var import_jsx_runtime4 = require("react/jsx-runtime"); var AuthModalContext = (0, import_react4.createContext)(void 0); function AuthModalProvider({ children }) { const [isModalOpen, setIsModalOpen] = (0, import_react4.useState)(false); const openLoginModal = (0, import_react4.useCallback)(() => setIsModalOpen(true), []); const closeLoginModal = (0, import_react4.useCallback)(() => setIsModalOpen(false), []); return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(AuthModalContext.Provider, { value: { openLoginModal, closeLoginModal, isModalOpen }, children: [ children, /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)( import_core_k2_components4.Dialog, { open: isModalOpen, onClose: closeLoginModal, maxWidth: "xs", children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core_k2_components4.DialogTitle, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: "", alt: "AvaCloud Connect", style: { height: "32px" } }) }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core_k2_components4.DialogContent, { sx: { padding: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( LoginModal, { open: isModalOpen, onClose: closeLoginModal } ) }) ] } ) ] }); } function useAuthModal() { const context = (0, import_react4.useContext)(AuthModalContext); if (context === void 0) { throw new Error("useAuthModal must be used within an AuthModalProvider"); } return context; } // src/AvaCloudWalletProvider.tsx var import_cubesigner_sdk2 = require("@cubist-labs/cubesigner-sdk"); // src/providers/ViemContext.tsx var import_react6 = require("react"); var import_viem = require("viem"); // src/hooks/useAuth.ts var import_react5 = require("react"); function useAuth() { const { isAuthenticated, isLoading, user, wallet, logout, loginWithCubist, cubistClient, cubistError } = useAvaCloudWallet(); const { openLoginModal } = useAuthModal(); const login = (0, import_react5.useCallback)(() => { openLoginModal(); }, [openLoginModal]); return { isAuthenticated, isLoading, user, wallet, login, logout, loginWithCubist, cubistClient, cubistError }; } // src/providers/ViemContext.tsx var import_jsx_runtime5 = require("react/jsx-runtime"); var ViemContext = (0, import_react6.createContext)(null); function ViemProvider({ children, rpcUrl, chainId, explorerUrl }) { var _a, _b; const [publicClient, setPublicClient] = (0, import_react6.useState)(null); const [walletClient, setWalletClient] = (0, import_react6.useState)(null); const [isConnected, setIsConnected] = (0, import_react6.useState)(false); const [error, setError] = (0, import_react6.useState)(null); const { cubistClient, wallet: authWallet } = useAuth(); (0, import_react6.useEffect)(() => { const initClient = async () => { var _a2; try { const transport = (0, import_viem.http)(rpcUrl); const customChain = { id: chainId, name: `Chain ${chainId}`, nativeCurrency: { name: "AVAX", symbol: "AVAX", decimals: 18 }, rpcUrls: { default: { http: [rpcUrl] }, public: { http: [rpcUrl] } }, blockExplorers: explorerUrl ? { default: { name: "Explorer", url: explorerUrl } } : void 0 }; const client = (0, import_viem.createPublicClient)({ transport, chain: customChain }); if ((_a2 = authWallet == null ? void 0 : authWallet.cubistWallet) == null ? void 0 : _a2.address) { const walletInstance = (0, import_viem.createWalletClient)({ transport, chain: customChain, account: authWallet.cubistWallet.address }); setWalletClient(walletInstance); } await client.getBlockNumber(); setPublicClient(client); setIsConnected(true); setError(null); } catch (err) { setError(err instanceof Error ? err : new Error("Failed to connect")); setIsConnected(false); } }; initClient(); }, [rpcUrl, chainId, explorerUrl, (_a = authWallet == null ? void 0 : authWallet.cubistWallet) == null ? void 0 : _a.address]); (0, import_react6.useEffect)(() => { var _a2; if (((_a2 = authWallet == null ? void 0 : authWallet.cubistWallet) == null ? void 0 : _a2.address) && publicClient && walletClient) { setIsConnected(true); } else { setIsConnected(false); } }, [(_b = authWallet == null ? void 0 : authWallet.cubistWallet) == null ? void 0 : _b.address, publicClient, walletClient]); const clearError = () => setError(null); return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)( ViemContext.Provider, { value: { publicClient, walletClient, setPublicClient, setWalletClient, chainId, explorerUrl, isConnected, error, clearError }, children } ); } function useViem() { const context = (0, import_react6.useContext)(ViemContext); if (!context) { throw new Error("useViem must be used within a ViemProvider"); } return context; } // src/hooks/useGlacier.ts var import_react_query = require("@tanstack/react-query"); // src/services/glacier/client.ts var GLACIER_API_BASE_URL = "https://glacier-api.avax.network"; var GlacierApiClient = class { constructor() { this.baseUrl = GLACIER_API_BASE_URL; } async getBlockchains() { const response = await fetch(`${this.baseUrl}/v1/chains`); if (!response.ok) { throw new Error("Failed to fetch blockchains"); } return response.json(); } async getValidators(subnetId) { const response = await fetch(`${this.baseUrl}/v1/subnets/${subnetId}/validators`); if (!response.ok) { throw new Error("Failed to fetch validators"); } return response.json(); } async getSubnets() { const response = await fetch(`${this.baseUrl}/v1/subnets`); if (!response.ok) { throw new Error("Failed to fetch subnets"); } return response.json(); } async getBlockchain(chainId) { const response = await fetch(`${this.baseUrl}/v1/chains/${chainId}`); if (!response.ok) { throw new Error("Failed to fetch blockchain"); } return response.json(); } async getBalance(address, chainId) { const chain = await this.getBlockchain(chainId); const response = await fetch(chain.rpcUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_getBalance", params: [address, "latest"] }) }); if (!response.ok) { throw new Error("Failed to fetch balance"); } const data = await response.json(); return data.result; } async getERC20Balances(address, chainId) { const response = await fetch(`${this.baseUrl}/v1/chains/${chainId}/addresses/${address}/balances:listErc20`); if (!response.ok) { throw new Error("Fa