From f7392c329edcd78846362508ea3e9c0c303c32c1 Mon Sep 17 00:00:00 2001 From: Justin <328965+justinbarry@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:20:32 -0700 Subject: [PATCH] Add account migration feature to Abstraxion dashboard This commit introduces a new feature to the Abstraxion dashboard allowing users to migrate their accounts when needed. The `AbstraxionMigrate` component was created to handle the migration process. Also, this introduces corresponding conditions in `AbstraxionContext` and `useAbstraxionSigningClient.ts` files. Furthermore, logic added to `Abstraxion` component to continue to next step post migration. --- apps/abstraxion-dashboard/app/page.tsx | 9 ++- .../components/Abstraxion/index.tsx | 30 +++++-- .../components/AbstraxionContext/index.tsx | 20 ++++- .../components/AbstraxionMigrate/index.tsx | 81 +++++++++++++++++++ .../hooks/useAbstraxionSigningClient.ts | 9 +-- 5 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 apps/abstraxion-dashboard/components/AbstraxionMigrate/index.tsx diff --git a/apps/abstraxion-dashboard/app/page.tsx b/apps/abstraxion-dashboard/app/page.tsx index 53adba9f..32c201a5 100644 --- a/apps/abstraxion-dashboard/app/page.tsx +++ b/apps/abstraxion-dashboard/app/page.tsx @@ -12,19 +12,22 @@ import type { AbstraxionAccount } from "@/types"; export default function Home() { const searchParams = useSearchParams(); - const { data: account } = useAbstraxionAccount(); + const { isConnected, data: account } = useAbstraxionAccount(); const contracts = searchParams.get("contracts"); const stake = Boolean(searchParams.get("stake")); const bank = searchParams.get("bank"); const grantee = searchParams.get("grantee"); - const { isOpen, setIsOpen, isMainnet } = useContext(AbstraxionContext); + const { isOpen, setIsOpen, isMainnet, accountNeedsToMigrate } = + useContext(AbstraxionContext); const [showMobileSiderbar, setShowMobileSiderbar] = useState(false); return ( <> - {!account?.id || (grantee && (contracts || stake || bank)) ? ( + {!account?.id || + (grantee && (contracts || stake || bank)) || + accountNeedsToMigrate ? (
null} isOpen={true} />
diff --git a/apps/abstraxion-dashboard/components/Abstraxion/index.tsx b/apps/abstraxion-dashboard/components/Abstraxion/index.tsx index 3fe4a26d..d06011e3 100644 --- a/apps/abstraxion-dashboard/components/Abstraxion/index.tsx +++ b/apps/abstraxion-dashboard/components/Abstraxion/index.tsx @@ -10,12 +10,13 @@ import { import { apolloClient, stytchClient } from "@/lib"; import { Dialog, DialogContent } from "@burnt-labs/ui"; import { AbstraxionSignin } from "@/components/AbstraxionSignin"; -import { useAbstraxionAccount } from "@/hooks"; +import { useAbstraxionAccount, useAbstraxionSigningClient } from "@/hooks"; import { AbstraxionWallets } from "@/components/AbstraxionWallets"; import { ErrorDisplay } from "@/components/ErrorDisplay"; import { useSearchParams } from "next/navigation"; import { AbstraxionGrant } from "../AbstraxionGrant"; import Image from "next/image"; +import { AbstraxionMigrate } from "@/components/AbstraxionMigrate"; export interface ModalProps { onClose: VoidFunction; @@ -25,11 +26,15 @@ export interface ModalProps { export const Abstraxion = ({ isOpen, onClose }: ModalProps) => { const searchParams = useSearchParams(); - const { abstraxionError, isMainnet } = useContext( - AbstraxionContext, - ) as AbstraxionContextProps; + const { + abstraxionError, + isMainnet, + setAccountNeedsToMigrate, + accountNeedsToMigrate, + } = useContext(AbstraxionContext) as AbstraxionContextProps; const { isConnected, data: account } = useAbstraxionAccount(); + const { client } = useAbstraxionSigningClient(); const contracts = searchParams.get("contracts"); const stake = Boolean(searchParams.get("stake")); @@ -60,6 +65,17 @@ export const Abstraxion = ({ isOpen, onClose }: ModalProps) => { }; }, [onClose]); + async function getMetaAccountCodeID() { + if (client) { + const { codeId } = await client.getContract(account.id); + setAccountNeedsToMigrate(codeId === 21); + } + } + + useEffect(() => { + if (account && client) getMetaAccountCodeID(); + }, [account, isConnected, client]); + if (!isOpen) return null; return ( @@ -79,7 +95,11 @@ export const Abstraxion = ({ isOpen, onClose }: ModalProps) => { stake={stake} /> ) : isConnected ? ( - + accountNeedsToMigrate ? ( + + ) : ( + + ) ) : ( )} diff --git a/apps/abstraxion-dashboard/components/AbstraxionContext/index.tsx b/apps/abstraxion-dashboard/components/AbstraxionContext/index.tsx index 65ae5fa9..175671a2 100644 --- a/apps/abstraxion-dashboard/components/AbstraxionContext/index.tsx +++ b/apps/abstraxion-dashboard/components/AbstraxionContext/index.tsx @@ -1,4 +1,4 @@ -import { ReactNode, createContext, useState } from "react"; +import { createContext, ReactNode, useState } from "react"; import { getEnvStringOrThrow } from "@/utils"; import { ChainInfo } from "@burnt-labs/constants"; @@ -16,6 +16,8 @@ export interface AbstraxionContextProps { isMainnet: boolean; isOpen: boolean; setIsOpen: React.Dispatch>; + setAccountNeedsToMigrate: React.Dispatch>; + accountNeedsToMigrate: boolean; } export const AbstraxionContext = createContext( @@ -34,15 +36,26 @@ export const AbstraxionContextProvider = ({ const [abstraxionError, setAbstraxionError] = useState(""); const [isOpen, setIsOpen] = useState(false); + const [accountNeedsToMigrate, setAccountNeedsToMigrate] = useState(false); + const serializedChainInfo = getEnvStringOrThrow( "NEXT_PUBLIC_DEFAULT_CHAIN_INFO", process.env.NEXT_PUBLIC_DEFAULT_CHAIN_INFO, ); const chainInfo = JSON.parse(serializedChainInfo); - const apiUrl = getEnvStringOrThrow( + + const oldApiUrl = getEnvStringOrThrow( "NEXT_PUBLIC_DEFAULT_API_URL", process.env.NEXT_PUBLIC_DEFAULT_API_URL, ); + + const migratedApiUrl = getEnvStringOrThrow( + "NEXT_PUBLIC_MIGRATED_API_URL", + process.env.NEXT_PUBLIC_MIGRATED_API_URL, + ); + + const apiUrl = accountNeedsToMigrate ? oldApiUrl : migratedApiUrl; + const isMainnet = getEnvStringOrThrow( "NEXT_PUBLIC_DEPLOYMENT_ENV", @@ -50,10 +63,11 @@ export const AbstraxionContextProvider = ({ ) === "mainnet" ? true : false; - return ( Promise; +}; + +export const AbstraxionMigrate = ({ + updateContractCodeID, +}: AbstraxionMigrateProps) => { + const { setAbstraxionError } = useContext( + AbstraxionContext, + ) as AbstraxionContextProps; + + const { client } = useAbstraxionSigningClient(); + const { data: account } = useAbstraxionAccount(); + const [inProgress, setInProgress] = useState(false); + const [failed, setFailed] = useState(false); + + const migrateAccount = async () => { + if (!client) return; + try { + setInProgress(true); + + await client.migrate( + account.id, + account.id, + 793, + {}, + { + amount: [{ amount: "0", denom: "uxion" }], + gas: "500000", + }, + ); + + void updateContractCodeID(); + } catch (error) { + console.log("something went wrong: ", error); + setFailed(true); + } finally { + setInProgress(false); + } + }; + + if (failed) { + setAbstraxionError("Failed to migrate account."); + return null; + } + + if (inProgress) { + return ( +
+ +
+ ); + } + + return ( +
+
+

+ Congratulations! +

+

+ Your account is due for an upgrade! Please click below to begin the + process. +

+
+
+ +
+
+ ); +}; diff --git a/apps/abstraxion-dashboard/hooks/useAbstraxionSigningClient.ts b/apps/abstraxion-dashboard/hooks/useAbstraxionSigningClient.ts index 31f78bfd..6c6b4c22 100644 --- a/apps/abstraxion-dashboard/hooks/useAbstraxionSigningClient.ts +++ b/apps/abstraxion-dashboard/hooks/useAbstraxionSigningClient.ts @@ -3,6 +3,7 @@ import { useStytch } from "@stytch/nextjs"; import { AAClient, AADirectSigner, + AAEthSigner, AbstractAccountJWTSigner, GasPrice, } from "@burnt-labs/signers"; @@ -12,11 +13,10 @@ import { } from "@/components/AbstraxionContext"; import { getKeplr, useOfflineSigners } from "graz"; import { testnetChainInfo } from "@burnt-labs/constants"; -import { AAEthSigner } from "@burnt-labs/signers"; import { getEnvStringOrThrow } from "@/utils"; export const useAbstraxionSigningClient = () => { - const { connectionType, abstractAccount, chainInfo } = useContext( + const { connectionType, abstractAccount, chainInfo, apiUrl } = useContext( AbstraxionContext, ) as AbstraxionContextProps; @@ -71,10 +71,7 @@ export const useAbstraxionSigningClient = () => { "NEXT_PUBLIC_DEFAULT_INDEXER_URL", process.env.NEXT_PUBLIC_DEFAULT_INDEXER_URL, ), - getEnvStringOrThrow( - "NEXT_PUBLIC_DEFAULT_API_URL", - process.env.NEXT_PUBLIC_DEFAULT_API_URL, - ), + apiUrl, ); break; case "graz":