From 140b5e47a5e39e4829af627055e0eb9c62984fdd Mon Sep 17 00:00:00 2001
From: hooperben
Date: Tue, 20 Jan 2026 18:05:43 +1000
Subject: [PATCH] feat: added account backup + bumped gas estimate back up
---
.../settings/backup-account-modal.tsx | 35 ++++++++++---
.../status/experimental-banner.tsx | 50 +++++++++++++++++++
client/src/lib/gas.ts | 4 +-
client/src/pages/account.tsx | 3 ++
4 files changed, 84 insertions(+), 8 deletions(-)
create mode 100644 client/src/_components/status/experimental-banner.tsx
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 */}