From 2aa7ac6d18cac172d7b5309b762c70e981f6d2b7 Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 2 Oct 2025 11:35:03 -0700 Subject: [PATCH 1/2] added upgrade hyper account view --- hyperdrive/src/register-ui/src/App.tsx | 13 ++ hyperdrive/src/register-ui/src/abis/index.ts | 4 + hyperdrive/src/register-ui/src/lib/types.ts | 2 +- .../register-ui/src/pages/HyperdriveHome.tsx | 4 + .../register-ui/src/pages/UpgradeCustom.tsx | 165 ++++++++++++++++++ hyperdrive/src/register.rs | 2 + 6 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 hyperdrive/src/register-ui/src/pages/UpgradeCustom.tsx diff --git a/hyperdrive/src/register-ui/src/App.tsx b/hyperdrive/src/register-ui/src/App.tsx index a6d54658e..90251cf39 100644 --- a/hyperdrive/src/register-ui/src/App.tsx +++ b/hyperdrive/src/register-ui/src/App.tsx @@ -4,6 +4,7 @@ import { Navigate, BrowserRouter as Router, Route, Routes, useParams } from 'rea import CommitDotOsName from "./pages/CommitDotOsName"; import MintDotOsName from "./pages/MintDotOsName"; import MintCustom from "./pages/MintCustom"; +import UpgradeCustom from "./pages/UpgradeCustom"; import SetPassword from "./pages/SetPassword"; import Login from './pages/Login' import ResetName from './pages/ResetName' @@ -24,6 +25,8 @@ function App() { const [reset, setReset] = useState(false); const [direct, setDirect] = useState(false); const [hnsName, setHnsName] = useState(''); + const [tbaAddress, setTbaAddress] = useState(''); + const [implAddress, setImplAddress] = useState(''); const [networkingKey, setNetworkingKey] = useState(''); const [ipAddress, setIpAddress] = useState(0); const [ws_port, setWsPort] = useState(0); @@ -94,6 +97,10 @@ function App() { tcp_port, setTcpPort, routers, setRouters, nodeChainId, + tbaAddress, + setTbaAddress, + implAddress, + setImplAddress } return ( @@ -138,6 +145,12 @@ function App() { } /> + + + + + } /> diff --git a/hyperdrive/src/register-ui/src/abis/index.ts b/hyperdrive/src/register-ui/src/abis/index.ts index 72f8e3ea2..298c49f35 100644 --- a/hyperdrive/src/register-ui/src/abis/index.ts +++ b/hyperdrive/src/register-ui/src/abis/index.ts @@ -31,3 +31,7 @@ export const dotOsAbi = parseAbi([ export const tbaMintAbi = parseAbi([ "function mint(address who, bytes calldata name, bytes calldata initialization, address implementation) external returns (address)" ]); + +export const tbaUpgradeAbi = parseAbi([ + "function upgradeToAndCall(address newImpl, bytes calldata data) external" +]); diff --git a/hyperdrive/src/register-ui/src/lib/types.ts b/hyperdrive/src/register-ui/src/lib/types.ts index a47f5f304..1f279c445 100644 --- a/hyperdrive/src/register-ui/src/lib/types.ts +++ b/hyperdrive/src/register-ui/src/lib/types.ts @@ -21,7 +21,7 @@ export interface PageProps { setReset: React.Dispatch>, pw: string, setPw: React.Dispatch>, - nodeChainId: string, + nodeChainId: string } export type NetworkingInfo = { diff --git a/hyperdrive/src/register-ui/src/pages/HyperdriveHome.tsx b/hyperdrive/src/register-ui/src/pages/HyperdriveHome.tsx index cb1044358..d1bef936c 100644 --- a/hyperdrive/src/register-ui/src/pages/HyperdriveHome.tsx +++ b/hyperdrive/src/register-ui/src/pages/HyperdriveHome.tsx @@ -13,6 +13,7 @@ function HyperdriveHome({ hnsName }: OsHomeProps) { const importKeyfileRedir = () => navigate('/import-keyfile') const loginRedir = () => navigate('/login') const customRegisterRedir = () => navigate('/custom-register') + const customUpgradeRedir = () => navigate('/custom-upgrade') const previouslyBooted = Boolean(hnsName) useEffect(() => { @@ -49,6 +50,9 @@ function HyperdriveHome({ hnsName }: OsHomeProps) { + )} diff --git a/hyperdrive/src/register-ui/src/pages/UpgradeCustom.tsx b/hyperdrive/src/register-ui/src/pages/UpgradeCustom.tsx new file mode 100644 index 000000000..b41b1d3e6 --- /dev/null +++ b/hyperdrive/src/register-ui/src/pages/UpgradeCustom.tsx @@ -0,0 +1,165 @@ +import { useState, useEffect, FormEvent, useCallback } from "react"; +import Loader from "../components/Loader"; +import { PageProps } from "../lib/types"; +import { useAccount, useWaitForTransactionReceipt, useSendTransaction } from "wagmi"; +import { useConnectModal, useAddRecentTransaction } from "@rainbow-me/rainbowkit"; +import { tbaUpgradeAbi } from "../abis"; +import { encodeFunctionData, stringToHex } from "viem"; +import BackButton from "../components/BackButton"; + +interface UpgradeCustomNameProps extends PageProps { } + +function UpgradeCustom({ }: UpgradeCustomNameProps) { + const { address } = useAccount(); + const { openConnectModal } = useConnectModal(); + + const [tbaAddress, setTbaAddress] = useState(""); + const [implAddress, setImplAddress] = useState(""); + const [showSuccess, setShowSuccess] = useState(false); + + const { data: hash, sendTransaction, isPending, isError, error } = useSendTransaction({ + mutation: { + onSuccess: (data) => { + addRecentTransaction({ hash: data, description: `Upgrade implementation` }); + }, + }, + }); + + const { isLoading: isConfirming, isSuccess: isConfirmed } = + useWaitForTransactionReceipt({ hash }); + + const addRecentTransaction = useAddRecentTransaction(); + + useEffect(() => { + document.title = "Upgrade Hyper Account"; + }, []); + + useEffect(() => { + if (!address) { + openConnectModal?.(); + } + }, [address, openConnectModal]); + + const handleUpgrade = useCallback( + async (e: FormEvent) => { + e.preventDefault(); + e.stopPropagation(); + + if (!address) { + openConnectModal?.(); + return; + } + + const tba = tbaAddress as `0x${string}`; + const impl = implAddress as `0x${string}`; + + const data = encodeFunctionData({ + abi: tbaUpgradeAbi, + functionName: "upgradeToAndCall", + args: [impl, stringToHex("")], + }); + + try { + sendTransaction({ + to: tba, + data, + gas: 1000000n, + }); + } catch (error) { + console.error("Failed to send transaction:", error); + } + }, + [address, sendTransaction, openConnectModal, tbaAddress, implAddress], + ); + + const isFormValid = tbaAddress.trim() !== "" && implAddress.trim() !== ""; + + // show success screen and reset form on confirmation + useEffect(() => { + if (isConfirmed) { + setTbaAddress(""); + setImplAddress(""); + setShowSuccess(true); + } + }, [isConfirmed]); + + const handleUpgradeNew = () => { + setShowSuccess(false); + }; + + return ( +
+
+
+ {isPending || isConfirming ? ( + + ) : showSuccess ? ( + <> +

+ ✅ Upgrade Successful! +

+

+ Your Hyper Account has been successfully upgraded. +

+
+ + +
+ + ) : ( + <> +

+ + Upgrade an existing Hyper Account +

+ + This will fail if the account or implementation does not support ERC-1967 + +
+ +

+ setTbaAddress(e.target.value)} + /> + setImplAddress(e.target.value)} + /> + +
+ + +
+ + )} + {isError && !showSuccess && ( +

+ Error: {error?.message || "There was an error on upgrade"} +

+ )} + +
+
+ ); +} + +export default UpgradeCustom; \ No newline at end of file diff --git a/hyperdrive/src/register.rs b/hyperdrive/src/register.rs index a0fa844b8..7342fe7cf 100644 --- a/hyperdrive/src/register.rs +++ b/hyperdrive/src/register.rs @@ -115,6 +115,7 @@ pub async fn register( .or(warp::path("import-keyfile")) .or(warp::path("set-password")) .or(warp::path("custom-register")) + .or(warp::path("custom-upgrade")) .and(warp::get()) .map(move |_| warp::reply::html(include_str!("register-ui/build/index.html"))); #[cfg(target_os = "windows")] @@ -127,6 +128,7 @@ pub async fn register( .or(warp::path("import-keyfile")) .or(warp::path("set-password")) .or(warp::path("custom-register")) + .or(warp::path("custom-upgrade")) .and(warp::get()) .map(move |_| warp::reply::html(include_str!("register-ui\\build\\index.html"))); From 5255d743ae89983f53a4acfd5b599c0d71530e7f Mon Sep 17 00:00:00 2001 From: Pax G Date: Thu, 9 Oct 2025 02:53:28 -0700 Subject: [PATCH 2/2] added more info on upgrade page --- .../register-ui/src/pages/UpgradeCustom.tsx | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/hyperdrive/src/register-ui/src/pages/UpgradeCustom.tsx b/hyperdrive/src/register-ui/src/pages/UpgradeCustom.tsx index b41b1d3e6..d5e7dac9b 100644 --- a/hyperdrive/src/register-ui/src/pages/UpgradeCustom.tsx +++ b/hyperdrive/src/register-ui/src/pages/UpgradeCustom.tsx @@ -115,26 +115,40 @@ function UpgradeCustom({ }: UpgradeCustomNameProps) { ) : ( <>

- - Upgrade an existing Hyper Account -

- - This will fail if the account or implementation does not support ERC-1967 - -
- + Upgrade Hyper Account Implementation

+ +
+

+ What is "Upgrade Hyper Account"? +

+

+ When minting a Hyper Account, you can make it upgradable. This allows the operator + to update the contract implementation and add or remove various functions without + changing the account address. +

+

+ This page allows you to upgrade an existing upgradable Hyper Account (TBA - Token Bound Account) + to a new implementation contract. The new implementation can include additional features, + bug fixes, or optimizations. +

+

+ ⚠️ In the default implementation, only the operator can call upgradeToAndCall. + This operation requires ERC-1967 support in both the account and implementation contracts. +

+
+ setTbaAddress(e.target.value)} /> setImplAddress(e.target.value)} />