diff --git a/client/src/_components/settings/backup-account-modal.tsx b/client/src/_components/settings/backup-account-modal.tsx index befd90d..6972208 100644 --- a/client/src/_components/settings/backup-account-modal.tsx +++ b/client/src/_components/settings/backup-account-modal.tsx @@ -15,12 +15,31 @@ import { AlertTriangle, Copy, Download } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; -export function BackupAccountModal() { +interface BackupAccountModalProps { + open?: boolean; + onOpenChange?: (open: boolean) => void; + onBackupSuccess?: () => void; + trigger?: React.ReactNode; +} + +export function BackupAccountModal({ + open: controlledOpen, + onOpenChange: controlledOnOpenChange, + onBackupSuccess, + trigger, +}: BackupAccountModalProps = {}) { const { getMnemonic } = useAuth(); - const [isOpen, setIsOpen] = useState(false); + const [internalOpen, setInternalOpen] = useState(false); const [confirmExport, setConfirmExport] = useState(false); + // Support both controlled and uncontrolled modes + const isControlled = controlledOpen !== undefined; + const isOpen = isControlled ? controlledOpen : internalOpen; + const setIsOpen = isControlled + ? (open: boolean) => controlledOnOpenChange?.(open) + : setInternalOpen; + function waitForWindowFocus(): Promise { return new Promise((resolve) => { // If window is already focused, resolve immediately @@ -56,6 +75,7 @@ export function BackupAccountModal() { await copyToClipboard(exportData); toast.success("Account backup copied to clipboard!"); + onBackupSuccess?.(); setIsOpen(false); resetForm(); } catch (error) { @@ -77,6 +97,7 @@ export function BackupAccountModal() { downloadAsJson(exportData); toast.success("Account backup downloaded!"); + onBackupSuccess?.(); setIsOpen(false); resetForm(); } catch (error) { @@ -98,9 +119,11 @@ export function BackupAccountModal() { }} > - + {trigger || ( + + )} @@ -117,7 +140,7 @@ export function BackupAccountModal() {

Anyone with access to this backup can control all of your - account. Keep it secure. + assets. Keep it secure.

diff --git a/client/src/_components/status/experimental-banner.tsx b/client/src/_components/status/experimental-banner.tsx new file mode 100644 index 0000000..4ec85bd --- /dev/null +++ b/client/src/_components/status/experimental-banner.tsx @@ -0,0 +1,50 @@ +import { BackupAccountModal } from "@/_components/settings/backup-account-modal"; +import { useAuth } from "@/_providers/auth-provider"; +import { AlertTriangle } from "lucide-react"; +import { useEffect, useState } from "react"; + +const BACKUP_STORAGE_KEY = "commbank-account-backed-up"; + +export function ExperimentalBanner() { + const { isSignedIn } = useAuth(); + const [hasBackedUp, setHasBackedUp] = useState(true); // Default to true to prevent flash + + useEffect(() => { + const backed = localStorage.getItem(BACKUP_STORAGE_KEY); + setHasBackedUp(backed === "true"); + }, []); + + const handleBackupSuccess = () => { + localStorage.setItem(BACKUP_STORAGE_KEY, "true"); + setHasBackedUp(true); + }; + + // Don't show if not signed in or already backed up + if (!isSignedIn || hasBackedUp) { + return null; + } + + return ( +
+
+ +
+

+ commbank.eth is experimental +

+

+ Please practise caution and{" "} + + backup your account secret + + } + /> +

+
+
+
+ ); +} diff --git a/client/src/lib/gas.ts b/client/src/lib/gas.ts index bf11427..18e3939 100644 --- a/client/src/lib/gas.ts +++ b/client/src/lib/gas.ts @@ -18,6 +18,6 @@ export async function getAdjustedGasPrice( return parseUnits("2", "gwei"); } - // Add 20% buffer to handle base fee increases between estimation and inclusion - return (basePrice * 120n) / 100n; + // Add 50% buffer to handle base fee increases between estimation and inclusion + return (basePrice * 150n) / 100n; } diff --git a/client/src/pages/account.tsx b/client/src/pages/account.tsx index 51dc03f..820a8a4 100644 --- a/client/src/pages/account.tsx +++ b/client/src/pages/account.tsx @@ -4,11 +4,14 @@ import { BalanceCard } from "@/_components/account/balance-card"; import { Transactions } from "@/_components/account/transactions"; import PageContainer from "@/_providers/page-container"; import { PAGE_METADATA } from "@/_constants/seo-config"; +import { ExperimentalBanner } from "@/_components/status/experimental-banner"; export default function AccountPage() { return (
+ + {/* Navigation Buttons */}