diff --git a/next.config.mjs b/next.config.mjs index 65729ee..5c5c2e4 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -83,6 +83,27 @@ const securityHeaders = [ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=(), payment=()", }, + { + key: "Cross-Origin-Opener-Policy", + value: "same-origin", + }, + { + key: "Cross-Origin-Embedder-Policy", + value: "credentialless", + }, + { + key: "Cross-Origin-Resource-Policy", + value: "same-origin", + }, + // HSTS only in production so local HTTP development keeps working. + ...(isDev + ? [] + : [ + { + key: "Strict-Transport-Security", + value: "max-age=63072000; includeSubDomains; preload", + }, + ]), ]; const nextConfig = { diff --git a/src/components/shared/wallet-error-banner.tsx b/src/components/shared/wallet-error-banner.tsx index a5a78bf..86cec42 100644 --- a/src/components/shared/wallet-error-banner.tsx +++ b/src/components/shared/wallet-error-banner.tsx @@ -1,7 +1,9 @@ "use client"; +import { useEffect, useState } from "react"; import { AlertTriangle, X, ExternalLink } from "lucide-react"; import type { WalletError } from "@/lib/hooks/use-auth"; +import { getSelectedWalletId, type WalletProviderId } from "@/lib/stellar/wallet"; interface WalletErrorBannerProps { error: WalletError; @@ -9,11 +11,41 @@ interface WalletErrorBannerProps { onRetry?: () => void; } +const WALLET_INSTALL_LINKS: Record< + WalletProviderId, + { name: string; url: string } +> = { + freighter: { name: "Freighter", url: "https://www.freighter.app/" }, + lobstr: { name: "LOBSTR", url: "https://lobstr.co/" }, + rabet: { name: "Rabet", url: "https://rabet.io/" }, +}; + +const ALL_WALLETS = Object.values(WALLET_INSTALL_LINKS); + +function resolveInstallLinks( + walletId: string | null +): Array<{ name: string; url: string }> { + if (walletId && walletId in WALLET_INSTALL_LINKS) { + return [ + WALLET_INSTALL_LINKS[walletId as WalletProviderId], + ]; + } + return ALL_WALLETS; +} + export function WalletErrorBanner({ error, onDismiss, onRetry, }: WalletErrorBannerProps) { + const [walletId, setWalletId] = useState(null); + + useEffect(() => { + setWalletId(getSelectedWalletId()); + }, []); + + const installLinks = resolveInstallLinks(walletId); + return (
{error.message}

{error.resolution}

{error.type === "not_installed" && ( - - Get Freighter - - +
+ {installLinks.map((wallet) => ( + + Get {wallet.name} + + + ))} +
)} {onRetry && (