diff --git a/ui/src/app/components/ArcadeDialog.tsx b/ui/src/app/components/ArcadeDialog.tsx
index 497349e25..a4b2e2a4e 100644
--- a/ui/src/app/components/ArcadeDialog.tsx
+++ b/ui/src/app/components/ArcadeDialog.tsx
@@ -23,7 +23,8 @@ import ArcadeLoader from "@/app/components/animations/ArcadeLoader";
import TokenLoader from "@/app/components/animations/TokenLoader";
import TopupInput from "@/app/components/arcade/TopupInput";
import RecoverUndeployed from "@/app/components/arcade/RecoverUndeployed";
-import RecoverArcade from "@/app/components//arcade/RecoverArcade";
+import RecoverArcade from "@/app/components/arcade/RecoverArcade";
+import MigrateAA from "@/app/components/arcade/MigrateAA";
import Storage from "@/app/lib/storage";
import { BurnerStorage } from "@/app/types";
@@ -51,6 +52,7 @@ export const ArcadeDialog = ({
const [fetchedBalances, setFetchedBalances] = useState(false);
const [recoverArcade, setRecoverArcade] = useState(false);
const [recoverUndeployed, setRecoverUndeployed] = useState(false);
+ const [migrateAA, setMigrateAA] = useState(false);
const [fullDeployment, setFullDeployment] = useState(false);
const { account: walletAccount, address, connector } = useAccount();
const showArcadeDialog = useUIStore((state) => state.showArcadeDialog);
@@ -177,6 +179,17 @@ export const ArcadeDialog = ({
walletAccount={walletAccount!}
updateConnectors={updateConnectors}
/>
+ ) : migrateAA ? (
+
) : (
<>
@@ -216,6 +229,9 @@ export const ArcadeDialog = ({
+
@@ -463,7 +479,7 @@ export const ArcadeAccountCard = ({
/>
)}
-
+
- {masterAccountAddress == walletAccount?.address && (
- <>
-
-
- >
- )}
{connected && (
+ {masterAccountAddress == walletAccount?.address && (
+
+ await genNewKey(account.name, connector!)}
+ >
+ Create New Keys
+
+ {
+ await setPermissions(account.name, walletAccount, true);
+ }}
+ className={`${currentGamePermissions ? "" : "animate-pulse"}`}
+ >
+ Set Permissions
+
+
+ )}
);
diff --git a/ui/src/app/components/arcade/MigrateAA.tsx b/ui/src/app/components/arcade/MigrateAA.tsx
new file mode 100644
index 000000000..aca41a2b5
--- /dev/null
+++ b/ui/src/app/components/arcade/MigrateAA.tsx
@@ -0,0 +1,182 @@
+import { ChangeEvent, useState, useEffect } from "react";
+import { AccountInterface, CallData, Contract, ec, hash } from "starknet";
+import { Connector, useContract } from "@starknet-react/core";
+import { padAddress, isChecksumAddress } from "@/app/lib/utils";
+import { Button } from "@/app/components/buttons/Button";
+import Storage from "@/app/lib/storage";
+import ArcadeAccount from "@/app/abi/ArcadeAccount.json";
+
+interface MigrateAAProps {
+ setMigrateAA: (migrateAA: boolean) => void;
+ walletAccount: AccountInterface;
+ walletConnectors: Connector[];
+ connector: Connector;
+ gameContract: Contract;
+ connect: any;
+ disconnect: any;
+ updateConnectors: () => void;
+}
+
+const MigrateAA = ({
+ setMigrateAA,
+ walletAccount,
+ walletConnectors,
+ connector,
+ gameContract,
+ connect,
+ disconnect,
+ updateConnectors,
+}: MigrateAAProps) => {
+ const [arcadePrivateKey, setArcadePrivateKey] = useState<
+ string | undefined
+ >();
+ const [arcadeExists, setArcadeExists] = useState(false);
+ const [arcadeAddress, setArcadeAddress] = useState();
+ const [arcadePublicKey, setArcadePublicKey] = useState();
+ const [masterAccount, setMasterAccount] = useState();
+
+ const formattedArcadeAddress = padAddress(padAddress(arcadeAddress ?? ""));
+
+ const storage = Storage.get("burners") || {};
+
+ const handleChange = (
+ e: ChangeEvent
+ ) => {
+ const { value } = e.target;
+ setArcadePrivateKey(value);
+ };
+
+ const { contract: arcadeContract } = useContract({
+ address: formattedArcadeAddress,
+ abi: ArcadeAccount,
+ });
+
+ const getMasterAccount = async () => {
+ try {
+ const masterAccount = await arcadeContract?.call("get_master_account");
+ if (masterAccount) {
+ setArcadeExists(true);
+ setMasterAccount("0x" + masterAccount?.toString(16));
+ }
+ } catch (e) {
+ console.log(e);
+ }
+ };
+
+ const handleGetArcade = () => {
+ if (isChecksumAddress(arcadePrivateKey!)) {
+ const publicKey = ec.starkCurve.getStarkKey(arcadePrivateKey!);
+
+ if (!walletAccount) {
+ throw new Error("wallet account not found");
+ }
+
+ const constructorAACalldata = CallData.compile({
+ _public_key: publicKey,
+ _master_account: walletAccount.address,
+ });
+
+ const address = hash.calculateContractAddressFromHash(
+ publicKey,
+ process.env.NEXT_PUBLIC_ARCADE_ACCOUNT_CLASS_HASH!,
+ constructorAACalldata,
+ 0
+ );
+
+ setArcadeAddress(address);
+ setArcadePublicKey(publicKey);
+ }
+ };
+
+ const importBurner = () => {
+ storage[formattedArcadeAddress!] = {
+ privateKey: arcadePrivateKey,
+ publicKey: arcadePublicKey,
+ masterAccount: walletAccount.address,
+ masterAccountProvider: connector.id,
+ gameContract: gameContract?.address,
+ active: true,
+ };
+
+ Storage.set("burners", storage);
+ };
+
+ const arcadeAccountExists = () => {
+ if (storage) {
+ return Object.keys(storage).includes(formattedArcadeAddress ?? "");
+ } else {
+ return false;
+ }
+ };
+
+ const isMasterAccount =
+ padAddress(walletAccount.address) === padAddress(masterAccount ?? "");
+
+ useEffect(() => {
+ if (arcadePrivateKey) {
+ handleGetArcade();
+ }
+ }, [arcadePrivateKey]);
+
+ useEffect(() => {
+ if (arcadeAddress) {
+ getMasterAccount();
+ }
+ }, [arcadeAddress]);
+
+ return (
+
+
Import Arcade Account
+
+ Please enter the private key of the Arcade Account you would like to
+ import to this client.
+
+
+ {!isMasterAccount && arcadeAddress && (
+ <>
+
Connect Master Account
+ {walletConnectors.map((connector, index) => (
+
{
+ disconnect();
+ connect({ connector });
+ }}
+ key={index}
+ >
+ {connector.id === "braavos" || connector.id === "argentX"
+ ? `Connect ${connector.id}`
+ : "Login With Email"}
+
+ ))}
+ >
+ )}
+
{
+ importBurner();
+ updateConnectors();
+ setMigrateAA(false);
+ }}
+ className="w-1/4"
+ >
+ {!arcadeExists
+ ? "Arcade Doesn't Exist"
+ : arcadeAccountExists()
+ ? "Arcade Already Stored"
+ : "Import Arcade"}
+
+
+ );
+};
+
+export default MigrateAA;