// src/shared/constants.js
var MESSAGE_SOURCE = "xrpl-wallet-extension";

// src/shared/browser.js
var browserAPI = (() => {
  if (typeof browser !== "undefined" && browser.runtime && browser.runtime.getBrowserInfo) {
    return browser;
  } else if (typeof chrome !== "undefined" && chrome.runtime) {
    return chrome;
  } else if (typeof browser !== "undefined" && browser.runtime) {
    return browser;
  }
  return {
    runtime: void 0,
    storage: void 0,
    tabs: void 0,
    windows: void 0,
    action: void 0,
    browserAction: void 0
  };
})();
var storage = {
  local: {
    get: (keys) => {
      if (!browserAPI.storage || !browserAPI.storage.local) {
        throw new Error("Storage API is not available in this context");
      }
      return new Promise((resolve, reject) => {
        browserAPI.storage.local.get(keys, (result) => {
          const error = browserAPI.runtime.lastError;
          if (error) {
            reject(new Error(error.message || "Storage error"));
          } else {
            resolve(result);
          }
        });
      });
    },
    set: (items) => {
      if (!browserAPI.storage || !browserAPI.storage.local) {
        throw new Error("Storage API is not available in this context");
      }
      return new Promise((resolve, reject) => {
        browserAPI.storage.local.set(items, () => {
          const error = browserAPI.runtime.lastError;
          if (error) {
            reject(new Error(error.message || "Storage error"));
          } else {
            resolve();
          }
        });
      });
    },
    remove: (keys) => {
      if (!browserAPI.storage || !browserAPI.storage.local) {
        throw new Error("Storage API is not available in this context");
      }
      return new Promise((resolve, reject) => {
        browserAPI.storage.local.remove(keys, () => {
          const error = browserAPI.runtime.lastError;
          if (error) {
            reject(new Error(error.message || "Storage error"));
          } else {
            resolve();
          }
        });
      });
    },
    clear: () => {
      if (!browserAPI.storage || !browserAPI.storage.local) {
        throw new Error("Storage API is not available in this context");
      }
      return new Promise((resolve, reject) => {
        browserAPI.storage.local.clear(() => {
          const error = browserAPI.runtime.lastError;
          if (error) {
            reject(new Error(error.message || "Storage error"));
          } else {
            resolve();
          }
        });
      });
    },
    get onChanged() {
      if (!browserAPI.storage) {
        return void 0;
      }
      return browserAPI.storage.onChanged;
    }
  },
  session: {
    get: (keys) => {
      if (!browserAPI.storage) {
        throw new Error("Storage API is not available in this context");
      }
      return new Promise((resolve, reject) => {
        const storageArea = browserAPI.storage.session || browserAPI.storage.local;
        if (!storageArea) {
          reject(new Error("Storage API is not available in this context"));
          return;
        }
        storageArea.get(keys, (result) => {
          const error = browserAPI.runtime.lastError;
          if (error) {
            reject(new Error(error.message || "Storage error"));
          } else {
            resolve(result);
          }
        });
      });
    },
    set: (items) => {
      if (!browserAPI.storage) {
        throw new Error("Storage API is not available in this context");
      }
      return new Promise((resolve, reject) => {
        const storageArea = browserAPI.storage.session || browserAPI.storage.local;
        if (!storageArea) {
          reject(new Error("Storage API is not available in this context"));
          return;
        }
        storageArea.set(items, () => {
          const error = browserAPI.runtime.lastError;
          if (error) {
            reject(new Error(error.message || "Storage error"));
          } else {
            resolve();
          }
        });
      });
    },
    clear: () => {
      if (!browserAPI.storage) {
        throw new Error("Storage API is not available in this context");
      }
      return new Promise((resolve, reject) => {
        const storageArea = browserAPI.storage.session || browserAPI.storage.local;
        if (!storageArea) {
          reject(new Error("Storage API is not available in this context"));
          return;
        }
        storageArea.clear(() => {
          const error = browserAPI.runtime.lastError;
          if (error) {
            reject(new Error(error.message || "Storage error"));
          } else {
            resolve();
          }
        });
      });
    },
    get onChanged() {
      if (!browserAPI.storage) {
        return void 0;
      }
      return browserAPI.storage.session?.onChanged || browserAPI.storage.onChanged;
    }
  }
};
var runtime = {
  get id() {
    if (!browserAPI.runtime) {
      return void 0;
    }
    return browserAPI.runtime.id;
  },
  getURL: (path) => {
    if (!browserAPI.runtime) {
      throw new Error("Runtime API is not available in this context");
    }
    return browserAPI.runtime.getURL(path);
  },
  sendMessage: (message, responseCallback) => {
    if (!browserAPI.runtime) {
      throw new Error("Runtime API is not available in this context");
    }
    return browserAPI.runtime.sendMessage(message, responseCallback);
  },
  get onMessage() {
    if (!browserAPI.runtime) {
      return void 0;
    }
    return browserAPI.runtime.onMessage;
  },
  get onStartup() {
    if (!browserAPI.runtime) {
      return void 0;
    }
    return browserAPI.runtime.onStartup;
  },
  get onInstalled() {
    if (!browserAPI.runtime) {
      return void 0;
    }
    return browserAPI.runtime.onInstalled;
  },
  connect: (connectInfo) => {
    if (!browserAPI.runtime) {
      throw new Error("Runtime API is not available in this context");
    }
    return browserAPI.runtime.connect(connectInfo);
  },
  getPlatformInfo: (callback) => {
    if (!browserAPI.runtime) {
      callback({ os: "unknown", arch: "unknown" });
      return;
    }
    if (browserAPI.runtime.getPlatformInfo) {
      return browserAPI.runtime.getPlatformInfo(callback);
    } else {
      callback({ os: "unknown", arch: "unknown" });
    }
  },
  getManifest: () => {
    if (!browserAPI.runtime) {
      throw new Error("Runtime API is not available in this context");
    }
    return browserAPI.runtime.getManifest();
  },
  get lastError() {
    if (!browserAPI.runtime) {
      return void 0;
    }
    return browserAPI.runtime.lastError;
  },
  openOptionsPage: () => {
    if (!browserAPI.runtime) {
      throw new Error("Runtime API is not available in this context");
    }
    if (browserAPI.runtime.openOptionsPage) {
      browserAPI.runtime.openOptionsPage();
    } else {
      if (browserAPI.tabs) {
        browserAPI.tabs.create({ url: browserAPI.runtime.getURL("options/index.html") });
      } else {
        throw new Error("Tabs API is not available in this context");
      }
    }
  }
};

// src/shared/runtime.js
function extractErrorMessage(error) {
  if (!error) return "Unknown error";
  try {
    if (error.message !== void 0 && error.message !== null) {
      const msg = String(error.message);
      if (msg && msg.trim()) {
        return msg;
      }
    }
  } catch (e) {
  }
  if (typeof error === "string") {
    return error;
  }
  try {
    if (error.code !== void 0) {
      return `Error code: ${error.code}`;
    }
    if (error.name !== void 0) {
      return `Error: ${error.name}`;
    }
  } catch (e) {
  }
  if (error.toString && typeof error.toString === "function") {
    try {
      const str = error.toString();
      if (str && str !== "[object Object]" && str !== "[object Error]" && str !== "Error" && str.length > 10) {
        return str;
      }
    } catch (e) {
    }
  }
  try {
    const extracted = {};
    const props = ["message", "code", "name", "stack", "description"];
    let foundAny = false;
    for (const prop of props) {
      try {
        if (error[prop] !== void 0) {
          extracted[prop] = String(error[prop]);
          foundAny = true;
        }
      } catch (e) {
      }
    }
    if (foundAny) {
      if (extracted.message) {
        return extracted.message;
      }
      return JSON.stringify(extracted);
    }
  } catch (e) {
  }
  const errorType = error.constructor?.name || typeof error;
  return `Browser Runtime Error (${errorType}) - Unable to extract message. Check runtime.lastError.message directly.`;
}
function sendMessage(message, timeoutMs = 3e4) {
  return new Promise((resolve, reject) => {
    try {
      if (!isRuntimeAvailable()) {
        reject(new Error("Extension context invalidated. Please reload the page."));
        return;
      }
      if (!runtime || typeof runtime.sendMessage !== "function") {
        reject(new Error("Extension context invalidated. Please reload the page."));
        return;
      }
      let timeoutId = null;
      let responded = false;
      let callbackFired = false;
      const cleanup = () => {
        if (timeoutId) {
          clearTimeout(timeoutId);
          timeoutId = null;
        }
        responded = true;
      };
      timeoutId = setTimeout(() => {
        if (!responded && !callbackFired) {
          cleanup();
          console.error("[XRP Universe Runtime] Message timeout:", {
            method: message.method,
            id: message.id,
            timeoutMs,
            callbackFired
          });
          reject(new Error(`Extension did not respond within ${timeoutMs}ms. Please try again or reload the page.`));
        } else if (!responded && callbackFired) {
          console.warn("[XRP Universe Runtime] Timeout fired but callback already fired, waiting a bit longer:", {
            method: message.method,
            id: message.id
          });
        }
      }, timeoutMs);
      const wakeUpTimeout = message.method === "provider.connect" ? 100 : 50;
      ensureServiceWorkerActive(wakeUpTimeout).catch(() => {
        console.warn("[XRP Universe Runtime] Service worker wake-up failed, but continuing");
      });
      console.log("[XRP Universe Runtime] Sending message via runtime.sendMessage:", {
        method: message.method,
        id: message.id,
        runtimeId: runtime.id
      });
      runtime.sendMessage(message, (response) => {
        callbackFired = true;
        const callbackTime = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
        console.log("[Content] <- BG callback", message.id, callbackTime);
        let lastErrorMsg = null;
        let errorType = "none";
        if (runtime.lastError) {
          try {
            lastErrorMsg = runtime.lastError.message || null;
            errorType = typeof runtime.lastError;
          } catch (e) {
            lastErrorMsg = extractErrorMessage(runtime.lastError);
            errorType = "extracted";
          }
          const directMsg = (() => {
            try {
              return runtime.lastError?.message || null;
            } catch (e) {
              return null;
            }
          })();
          const errorString = lastErrorMsg || directMsg || "UNKNOWN ERROR - Unable to extract message";
          const directMsgString = directMsg || "NO MESSAGE PROPERTY";
          console.error(
            "[XRP Universe Runtime] Immediate error in sendMessage callback:",
            `method: ${message.method}, id: ${message.id}, error: ${errorString}, errorMessageDirect: ${directMsgString}, errorType: ${errorType}, timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}`
          );
        }
        console.log("[XRP Universe Runtime] runtime.sendMessage callback invoked:", {
          method: message.method,
          id: message.id,
          hasResponse: !!response,
          responseValue: response,
          responseKeys: response ? Object.keys(response) : [],
          hasError: !!runtime.lastError,
          errorMessage: lastErrorMsg || runtime.lastError?.message || "none",
          responseType: response ? typeof response : "null",
          responded
        });
        if (responded) {
          console.log("[XRP Universe Runtime] Callback fired but already responded (timeout), ignoring");
          return;
        }
        cleanup();
        try {
          if (runtime.lastError) {
            let errorMsg = null;
            try {
              errorMsg = runtime.lastError.message || null;
            } catch (e) {
              errorMsg = extractErrorMessage(runtime.lastError);
            }
            if (!errorMsg) {
              errorMsg = extractErrorMessage(runtime.lastError);
            }
            const directMsg = (() => {
              try {
                return runtime.lastError?.message || null;
              } catch (e) {
                return null;
              }
            })();
            const errorString = errorMsg || directMsg || "UNKNOWN ERROR - Unable to extract message";
            const directMsgString = directMsg || "NO MESSAGE PROPERTY";
            const errorTypeString = (() => {
              try {
                return typeof runtime.lastError;
              } catch (e) {
                return "unknown";
              }
            })();
            console.error(
              "[XRP Universe Runtime] runtime.lastError detected:",
              `method: ${message.method}, id: ${message.id}, error: ${errorString}, errorMessageDirect: ${directMsgString}, errorType: ${errorTypeString}, timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}`
            );
            if (errorMsg.includes("Extension context invalidated") || errorMsg.includes("message port closed") || errorMsg.includes("Receiving end does not exist") || errorMsg.includes("No SW") || errorMsg.includes("Could not establish connection") || errorMsg.includes("The message port closed") || errorMsg.includes("Could not establish connection. Receiving end does not exist") || errorMsg.includes("message channel closed") || errorMsg.includes("A listener indicated an asynchronous response")) {
              reject(new Error("Extension context invalidated. Please reload the page."));
              return;
            }
            reject(new Error(errorMsg || "Runtime error"));
            return;
          }
          if (!response) {
            console.error("[XRP Universe Runtime] No response received:", {
              method: message.method,
              id: message.id,
              hasLastError: !!runtime.lastError,
              responseValue: response,
              responseType: typeof response
            });
            reject(new Error("No response from extension. The extension may not be responding. Please check if the extension service worker is running."));
            return;
          }
          console.log("[XRP Universe Runtime] Resolving promise with response:", {
            method: message.method,
            id: message.id,
            responseOk: response?.ok,
            hasResult: !!response?.result,
            hasError: !!response?.error
          });
          resolve(response);
        } catch (error) {
          reject(new Error("Extension context invalidated. Please reload the page."));
        }
      });
    } catch (error) {
      reject(new Error("Extension context invalidated. Please reload the page."));
    }
  });
}
function getRuntimeURL(path) {
  try {
    if (!runtime?.getURL) {
      throw new Error("Extension runtime is not available");
    }
    return runtime.getURL(path);
  } catch (error) {
    console.error("Failed to get runtime URL:", error);
    return path;
  }
}
async function ensureServiceWorkerActive(timeoutMs = 3e3) {
  if (!isRuntimeAvailable()) {
    return false;
  }
  try {
    const wakeUpPromises = [
      storage.local.set({ "wakeUp": Date.now() }).catch(() => {
      }),
      storage.session.set({ "wakeUp": Date.now() }).catch(() => {
      })
    ];
    await Promise.allSettled(wakeUpPromises);
    try {
      await new Promise((resolve, reject) => {
        const timeout = setTimeout(() => {
          resolve(false);
        }, timeoutMs);
        runtime.sendMessage(
          { source: MESSAGE_SOURCE, method: "ping", id: "wakeup-check" },
          (response) => {
            clearTimeout(timeout);
            if (runtime.lastError) {
              resolve(false);
            } else {
              resolve(true);
            }
          }
        );
      });
    } catch (error) {
      console.warn("[XRP Universe] Service worker ping failed, but continuing:", extractErrorMessage(error));
    }
    return true;
  } catch (error) {
    console.warn("[XRP Universe] Service worker wake-up failed:", extractErrorMessage(error));
    return false;
  }
}
function isRuntimeAvailable() {
  try {
    if (!runtime) {
      return false;
    }
    if (!runtime.id) {
      return false;
    }
    if (typeof runtime.sendMessage !== "function") {
      return false;
    }
    return true;
  } catch (error) {
    return false;
  }
}

// src/shared/notifications.js
function showToast(message, type = "info", duration = 3e3) {
  const toast = document.createElement("div");
  toast.className = `toast toast-${type}`;
  toast.textContent = message;
  if (!document.getElementById("toast-styles")) {
    const style = document.createElement("style");
    style.id = "toast-styles";
    style.textContent = `
      .toast {
        position: fixed;
        top: 20px;
        left: 50%;
        transform: translateX(-50%);
        padding: 12px 20px;
        border-radius: 12px;
        background: rgba(15, 23, 42, 0.95);
        border: 1px solid rgba(255, 255, 255, 0.1);
        color: #ffffff;
        font-size: 14px;
        font-weight: 500;
        z-index: 10000;
        box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6);
        backdrop-filter: blur(12px);
        animation: toastSlideIn 0.3s ease-out;
        max-width: 90%;
        text-align: center;
      }
      .toast-error {
        background: rgba(239, 68, 68, 0.2);
        border-color: rgba(239, 68, 68, 0.4);
        color: #fca5a5;
      }
      .toast-success {
        background: rgba(34, 197, 94, 0.2);
        border-color: rgba(34, 197, 94, 0.4);
        color: #86efac;
      }
      .toast-warning {
        background: rgba(245, 158, 11, 0.2);
        border-color: rgba(245, 158, 11, 0.4);
        color: #fcd34d;
      }
      .toast-info {
        background: rgba(34, 211, 238, 0.2);
        border-color: rgba(34, 211, 238, 0.4);
        color: #7dd3fc;
      }
      @keyframes toastSlideIn {
        from {
          opacity: 0;
          transform: translateX(-50%) translateY(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(-50%) translateY(0);
        }
      }
      @keyframes toastSlideOut {
        from {
          opacity: 1;
          transform: translateX(-50%) translateY(0);
        }
        to {
          opacity: 0;
          transform: translateX(-50%) translateY(-20px);
        }
      }
    `;
    document.head.appendChild(style);
  }
  document.body.appendChild(toast);
  setTimeout(() => {
    toast.style.animation = "toastSlideOut 0.3s ease-out";
    setTimeout(() => {
      if (toast.parentNode) {
        toast.parentNode.removeChild(toast);
      }
    }, 300);
  }, duration);
  return toast;
}
function showError(message, duration = 5e3) {
  return showToast(message, "error", duration);
}
function showSuccess(message, duration = 3e3) {
  return showToast(message, "success", duration);
}

// src/shared/loading.js
function createLoadingSpinner(container = null) {
  const spinner = document.createElement("div");
  spinner.className = "loading-spinner";
  if (!document.getElementById("spinner-styles")) {
    const style = document.createElement("style");
    style.id = "spinner-styles";
    style.textContent = `
      .loading-spinner {
        width: 24px;
        height: 24px;
        border: 3px solid rgba(34, 211, 238, 0.2);
        border-top-color: #22d3ee;
        border-radius: 50%;
        animation: spin 0.8s linear infinite;
      }
      .loading-spinner-large {
        width: 40px;
        height: 40px;
        border-width: 4px;
      }
      @keyframes spin {
        to { transform: rotate(360deg); }
      }
      .loading-overlay {
        position: fixed;
        inset: 0;
        background: rgba(4, 7, 13, 0.8);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 9999;
        backdrop-filter: blur(4px);
      }
      .loading-content {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 16px;
        color: #ffffff;
      }
      .loading-text {
        font-size: 14px;
        color: #a0a7b5;
      }
    `;
    document.head.appendChild(style);
  }
  if (container) {
    container.appendChild(spinner);
  }
  return spinner;
}
function setButtonLoading(button, isLoading, originalText = null) {
  if (!button) return;
  if (isLoading) {
    button.dataset.originalText = originalText || button.textContent;
    button.disabled = true;
    button.style.opacity = "0.6";
    button.style.cursor = "not-allowed";
    const spinner = createLoadingSpinner();
    spinner.style.width = "16px";
    spinner.style.height = "16px";
    spinner.style.borderWidth = "2px";
    button.innerHTML = "";
    button.appendChild(spinner);
  } else {
    button.disabled = false;
    button.style.opacity = "1";
    button.style.cursor = "pointer";
    if (button.dataset.originalText) {
      button.textContent = button.dataset.originalText;
      delete button.dataset.originalText;
    }
  }
}

// src/approval/connect.js
var params = new URLSearchParams(window.location.search);
var id = params.get("id");
async function request(method, params2) {
  if (!isRuntimeAvailable()) {
    throw new Error("Extension context invalidated. Please reload the extension.");
  }
  const response = await sendMessage({ source: MESSAGE_SOURCE, method, params: params2 });
  if (!response || !response.ok) {
    throw new Error(response?.error || "Request failed");
  }
  return response.result;
}
function showUnlockForm() {
  const unlockSection = document.getElementById("unlockSection");
  const connectSection = document.getElementById("connectSection");
  if (unlockSection) unlockSection.classList.add("active");
  if (connectSection) connectSection.classList.remove("active");
  const passwordInput = document.getElementById("unlockPassword");
  if (passwordInput) {
    passwordInput.focus();
    passwordInput.value = "";
  }
}
function hideUnlockForm() {
  const unlockSection = document.getElementById("unlockSection");
  const connectSection = document.getElementById("connectSection");
  if (unlockSection) unlockSection.classList.remove("active");
  if (connectSection) connectSection.classList.add("active");
}
async function unlockWallet() {
  const passwordInput = document.getElementById("unlockPassword");
  const unlockButton = document.getElementById("unlockButton");
  const unlockError = document.getElementById("unlockError");
  const password = passwordInput?.value;
  if (!password) {
    if (unlockError) {
      unlockError.textContent = "Please enter your password";
      unlockError.classList.add("show");
    }
    return false;
  }
  if (unlockError) unlockError.classList.remove("show");
  if (unlockButton) setButtonLoading(unlockButton, true, "Unlocking...");
  try {
    await request("vault.unlock", { password });
    showSuccess("Wallet unlocked successfully!");
    if (passwordInput) passwordInput.value = "";
    await loadConnectDataAfterUnlock();
    return true;
  } catch (error) {
    if (unlockError) {
      unlockError.textContent = error.message || "Invalid password";
      unlockError.classList.add("show");
    } else {
      showError(error.message || "Failed to unlock wallet");
    }
    if (unlockButton) setButtonLoading(unlockButton, false);
    return false;
  }
}
async function loadConnectDataAfterUnlock() {
  if (!id) {
    showError("Missing connection request ID");
    showUnlockForm();
    return;
  }
  try {
    let connect = null;
    try {
      connect = await request("connect.get", { id });
      updateSiteInfo(connect.origin);
    } catch (err) {
      console.warn("[Connect] Could not load connection info after unlock:", err);
    }
    let accounts = null;
    try {
      accounts = await request("account.list");
    } catch (err) {
      const errorMsg = err.message || String(err);
      console.error("[Connect] Error loading accounts after unlock:", errorMsg, err);
      if (errorMsg.toLowerCase().includes("locked") || errorMsg.toLowerCase().includes("password") || errorMsg.toLowerCase().includes("vault")) {
        showUnlockForm();
        if (connect?.origin) {
          updateSiteInfo(connect.origin);
        }
        return;
      }
      throw err;
    }
    if (!accounts || accounts.locked) {
      showUnlockForm();
      if (connect?.origin) {
        updateSiteInfo(connect.origin);
      }
      return;
    }
    if (!accounts.accounts || accounts.accounts.length === 0) {
      showError("No accounts found. Please create an account first.");
      showUnlockForm();
      return;
    }
    renderAccounts(accounts.accounts, accounts.activeAccountId);
    hideUnlockForm();
  } catch (error) {
    const errorMsg = error.message || "Failed to load connection data";
    console.error("[Connect] Error loading connection data after unlock:", errorMsg, error);
    showUnlockForm();
    if (errorMsg.toLowerCase().includes("locked") || errorMsg.toLowerCase().includes("password") || errorMsg.toLowerCase().includes("vault")) {
      try {
        const connect = await request("connect.get", { id });
        updateSiteInfo(connect.origin);
      } catch (err) {
      }
    } else {
      showError(errorMsg);
    }
  }
}
async function loadConnectData() {
  if (!id) {
    showError("Missing connection request ID");
    showUnlockForm();
    return;
  }
  showUnlockForm();
  try {
    let connectInfo = null;
    try {
      connectInfo = await request("connect.get", { id });
      updateSiteInfo(connectInfo.origin);
    } catch (err) {
      console.warn("[Connect] Could not load connection info:", err);
    }
    let vaultStatus = null;
    try {
      vaultStatus = await request("vault.status");
    } catch (err) {
      console.warn("[Connect] Could not check vault status, assuming locked:", err);
      if (connectInfo?.origin) {
        updateSiteInfo(connectInfo.origin);
      }
      return;
    }
    if (!vaultStatus || vaultStatus.locked) {
      return;
    }
    if (!connectInfo) {
      try {
        connectInfo = await request("connect.get", { id });
        updateSiteInfo(connectInfo.origin);
      } catch (err) {
        console.warn("[Connect] Could not load connection info after unlock:", err);
      }
    }
    let accounts = null;
    try {
      accounts = await request("account.list");
    } catch (err) {
      console.warn("[Connect] Could not list accounts:", err);
      const errorMsg = err.message || String(err);
      if (errorMsg.toLowerCase().includes("locked")) {
        showUnlockForm();
        return;
      }
      throw err;
    }
    if (accounts.locked) {
      showUnlockForm();
      return;
    }
    if (!accounts.accounts || accounts.accounts.length === 0) {
      showError("No accounts found. Please create an account first.");
      showUnlockForm();
      return;
    }
    renderAccounts(accounts.accounts, accounts.activeAccountId);
    hideUnlockForm();
  } catch (error) {
    const errorMsg = error.message || "Failed to load connection data";
    console.error("[Connect] Error loading connection data:", errorMsg, error);
    showUnlockForm();
    if (errorMsg.toLowerCase().includes("locked") || errorMsg.toLowerCase().includes("password") || errorMsg.toLowerCase().includes("vault")) {
      try {
        const connect = await request("connect.get", { id });
        updateSiteInfo(connect.origin);
      } catch (err) {
      }
    } else {
      showError(errorMsg);
    }
  }
}
function parseFaviconsFromHTML(html, baseUrl) {
  const favicons = [];
  try {
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, "text/html");
    const links = doc.querySelectorAll('link[rel*="icon"], link[rel*="shortcut"], link[rel*="apple-touch-icon"]');
    links.forEach((link) => {
      const href = link.getAttribute("href");
      if (href) {
        try {
          const absoluteUrl = new URL(href, baseUrl).href;
          const rel = link.getAttribute("rel") || "";
          let priority = 3;
          if (rel.includes("icon") && !rel.includes("apple")) priority = 1;
          else if (rel.includes("shortcut")) priority = 2;
          favicons.push({ url: absoluteUrl, priority });
        } catch (e) {
        }
      }
    });
    favicons.sort((a, b) => a.priority - b.priority);
    return favicons.map((f) => f.url);
  } catch (e) {
    return [];
  }
}
async function detectFavicon(origin) {
  try {
    const url = new URL(origin);
    let timeoutId = null;
    try {
      let abortController = null;
      if (typeof AbortSignal !== "undefined" && AbortSignal.timeout) {
        abortController = { signal: AbortSignal.timeout(3e3) };
      } else if (typeof AbortController !== "undefined") {
        abortController = new AbortController();
        timeoutId = setTimeout(() => abortController.abort(), 3e3);
      }
      const fetchOptions = {
        method: "GET",
        headers: {
          "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
        }
      };
      if (abortController && abortController.signal) {
        fetchOptions.signal = abortController.signal;
      }
      const response = await fetch(origin, fetchOptions);
      if (timeoutId) {
        clearTimeout(timeoutId);
        timeoutId = null;
      }
      if (response.ok) {
        const html = await response.text();
        const favicons = parseFaviconsFromHTML(html, origin);
        if (favicons.length > 0) {
          for (const faviconUrl of favicons) {
            try {
              const testImg = new Image();
              const loaded = await new Promise((resolve) => {
                let imgTimeoutId = null;
                testImg.onload = () => {
                  if (imgTimeoutId) clearTimeout(imgTimeoutId);
                  resolve(true);
                };
                testImg.onerror = () => {
                  if (imgTimeoutId) clearTimeout(imgTimeoutId);
                  resolve(false);
                };
                testImg.src = faviconUrl;
                imgTimeoutId = setTimeout(() => {
                  resolve(false);
                }, 2e3);
              });
              if (loaded) {
                return faviconUrl;
              }
            } catch (e) {
              continue;
            }
          }
        }
      }
    } catch (e) {
      if (timeoutId) {
        clearTimeout(timeoutId);
        timeoutId = null;
      }
      if (e.name !== "AbortError" && e.name !== "TimeoutError") {
        console.log("[Connect] Could not fetch page HTML for favicon detection:", e.message || e.name);
      }
    }
    const commonPaths = [
      "/favicon.png",
      "/favicon.ico",
      "/apple-touch-icon.png",
      "/favicon.svg",
      "/favicon-32x32.png",
      "/favicon-16x16.png"
    ];
    for (const path of commonPaths) {
      try {
        const faviconUrl = `${url.origin}${path}`;
        const testImg = new Image();
        const loaded = await new Promise((resolve) => {
          testImg.onload = () => resolve(true);
          testImg.onerror = () => resolve(false);
          testImg.src = faviconUrl;
          setTimeout(() => resolve(false), 2e3);
        });
        if (loaded) {
          return faviconUrl;
        }
      } catch (e) {
        continue;
      }
    }
    return `https://www.google.com/s2/favicons?domain=${url.hostname}&sz=64`;
  } catch (e) {
    return null;
  }
}
function updateSiteInfo(origin) {
  if (!origin) return;
  try {
    const url = new URL(origin);
    const siteNameEl = document.getElementById("siteName");
    const siteUrlEl = document.getElementById("siteUrl");
    const siteIconEl = document.getElementById("siteIcon");
    const siteIconPlaceholder = document.getElementById("siteIconPlaceholder");
    if (siteNameEl) {
      siteNameEl.textContent = url.hostname.replace(/^www\./, "");
    }
    if (siteUrlEl) {
      siteUrlEl.textContent = origin;
    }
    if (siteIconEl && siteIconPlaceholder) {
      detectFavicon(origin).then((faviconUrl) => {
        if (faviconUrl) {
          const img = document.createElement("img");
          img.crossOrigin = "anonymous";
          img.src = faviconUrl;
          img.onload = () => {
            siteIconPlaceholder.style.display = "none";
            const existingImg = siteIconEl.querySelector("img");
            if (existingImg) {
              existingImg.src = faviconUrl;
            } else {
              siteIconEl.appendChild(img);
            }
          };
          img.onerror = () => {
            siteIconPlaceholder.style.display = "flex";
          };
        } else {
          siteIconPlaceholder.style.display = "flex";
        }
      }).catch((e) => {
        console.warn("[Connect] Favicon detection error:", e);
        siteIconPlaceholder.style.display = "flex";
      });
    }
  } catch (e) {
    const siteNameEl = document.getElementById("siteName");
    const siteUrlEl = document.getElementById("siteUrl");
    if (siteNameEl) siteNameEl.textContent = origin;
    if (siteUrlEl) siteUrlEl.textContent = origin;
  }
}
function renderAccounts(accounts, activeAccountId) {
  const container = document.getElementById("accounts");
  if (!container) return;
  container.innerHTML = "";
  accounts.forEach((account) => {
    const isSelected = account.id === activeAccountId;
    const card = document.createElement("div");
    card.className = `account-card ${isSelected ? "selected" : ""}`;
    card.dataset.accountId = account.id;
    const checkbox = document.createElement("div");
    checkbox.className = "account-checkbox";
    const info = document.createElement("div");
    info.className = "account-info";
    const label = document.createElement("div");
    label.className = "account-label";
    label.textContent = account.label || "Account";
    const address = document.createElement("div");
    address.className = "account-address";
    address.textContent = account.address;
    info.appendChild(label);
    info.appendChild(address);
    card.appendChild(checkbox);
    card.appendChild(info);
    if (isSelected) {
      const badge = document.createElement("div");
      badge.className = "account-badge";
      badge.textContent = "Active";
      card.appendChild(badge);
    }
    card.addEventListener("click", () => {
      const wasSelected = card.classList.contains("selected");
      card.classList.toggle("selected");
      if (card.classList.contains("selected")) {
        checkbox.classList.add("selected");
        if (!card.querySelector(".account-badge")) {
          const badge = document.createElement("div");
          badge.className = "account-badge";
          badge.textContent = "Selected";
          card.appendChild(badge);
        }
      } else {
        checkbox.classList.remove("selected");
        const badge = card.querySelector(".account-badge");
        if (badge && badge.textContent === "Selected") {
          badge.remove();
        }
      }
    });
    container.appendChild(card);
  });
}
function collectSelectedAccounts() {
  const selected = [];
  document.querySelectorAll("#accounts .account-card.selected").forEach((card) => {
    const accountId = card.dataset.accountId;
    if (accountId) {
      selected.push(accountId);
    }
  });
  return selected;
}
document.getElementById("approve")?.addEventListener("click", async () => {
  const accountIds = collectSelectedAccounts();
  if (accountIds.length === 0) {
    showError("Please select at least one account");
    return;
  }
  try {
    await storage.local.set({
      [`connectResult:${id}`]: {
        requestId: id,
        status: "APPROVED",
        accountIds,
        timestamp: Date.now()
      }
    });
    try {
      await request("connect.respond", { id, approved: true, accountIds });
    } catch (error) {
      console.warn("[Connect] Direct response failed, but result written to storage:", error);
    }
    window.close();
  } catch (error) {
    showError(error.message || "Failed to approve connection");
  }
});
document.getElementById("reject")?.addEventListener("click", async () => {
  try {
    await storage.local.set({
      [`connectResult:${id}`]: {
        requestId: id,
        status: "REJECTED",
        error: "User rejected",
        timestamp: Date.now()
      }
    });
    try {
      await request("connect.respond", { id, approved: false, accountIds: [] });
    } catch (error) {
      console.warn("[Connect] Direct response failed, but result written to storage:", error);
    }
    window.close();
  } catch (error) {
    showError(error.message || "Failed to reject connection");
  }
});
document.getElementById("unlockButton")?.addEventListener("click", async () => {
  await unlockWallet();
});
document.getElementById("unlockPassword")?.addEventListener("keypress", async (e) => {
  if (e.key === "Enter") {
    await unlockWallet();
  }
});
var walletIcon = document.getElementById("walletIcon");
if (walletIcon && isRuntimeAvailable()) {
  walletIcon.src = getRuntimeURL("public/xrpl universe.png");
  walletIcon.onerror = () => {
    walletIcon.style.display = "none";
  };
}
window.addEventListener("error", (event) => {
  console.error("[Connect] Unhandled error:", event.error || event.message);
  showUnlockForm();
});
window.addEventListener("unhandledrejection", (event) => {
  console.error("[Connect] Unhandled promise rejection:", event.reason);
  showUnlockForm();
  event.preventDefault();
});
loadConnectData();
