diff --git a/packages/client/src/components/transfer/Authorize.tsx b/packages/client/src/components/transfer/Authorize.tsx index 1707b943d..6973b6363 100644 --- a/packages/client/src/components/transfer/Authorize.tsx +++ b/packages/client/src/components/transfer/Authorize.tsx @@ -1,58 +1,36 @@ -import { useEffect, useState } from "react"; -import { FaClipboard, FaExclamationCircle, FaEye, FaEyeSlash, FaInfoCircle, FaTimes, FaUnlink } from "react-icons/fa"; -import { Address, Hex } from "viem"; -import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { requestSessionKey } from "@happy.tech/core"; +import { useState } from "react"; +import { FaInfoCircle, FaTimes } from "react-icons/fa"; -import { STORAGE_PREFIX } from "@primodiumxyz/core"; import { useAccountClient } from "@primodiumxyz/core/react"; import { defaultEntity } from "@primodiumxyz/reactive-tables"; import { Button } from "@/components/core/Button"; import { SecondaryCard } from "@/components/core/Card"; import { TransactionQueueMask } from "@/components/shared/TransactionQueueMask"; -import { useContractCalls } from "@/hooks/useContractCalls"; -import { copyToClipboard } from "@/util/clipboard"; -import { findEntriesWithPrefix } from "@/util/localStorage"; +import { HAPPY_STORAGE_PREFIX, isHappySessionKeyRegistered } from "@/util/localStorage"; -const sessionWalletTooltip = - "Bypass annoying confirmation popups by authorizing a session account. This allows you to securely perform certain actions without external confirmation."; +const sessionWalletTooltip = ( + <> + Bypass confirmation popups by authorizing a session key. Powered by{" "} + Happy Wallet, this lets you securely perform actions without repeated + approvals. + +); export function Authorize() { - const { sessionAccount } = useAccountClient(); - const { grantAccessWithSignature, revokeAccess } = useContractCalls(); - const [showDetails, setShowDetails] = useState(false); + const { + playerAccount: { address: playerAddress, worldContract }, + } = useAccountClient(); const [showHelp, setShowHelp] = useState(!localStorage.getItem("hideHelp")); - useEffect(() => { - setShowDetails(false); - }, [sessionAccount]); + const weAreHappySponsored = isHappySessionKeyRegistered(playerAddress); - // Function to handle private key validation and connection - const sessionAddress = sessionAccount?.address; + const handleHappySessionKeyRegister = async () => { + if (!isHappySessionKeyRegistered(playerAddress)) { + await requestSessionKey(worldContract.address); - const submitPrivateKey = async (privateKey: Hex) => { - // Validate the private key format here - // This is a basic example, adjust the validation according to your requirements - const isValid = /^0x[a-fA-F0-9]{64}$/.test(privateKey); - if (!isValid) return; - const account = privateKeyToAccount(privateKey as Hex); - - if (sessionAddress && sessionAddress === account.address) return; - else await grantAccessWithSignature(privateKey, { id: defaultEntity }); - }; - - const handleRandomPress = () => { - const storedKeys = findEntriesWithPrefix(); - const privateKey = storedKeys.length > 0 ? storedKeys[0].privateKey : generatePrivateKey(); - - const account = privateKeyToAccount(privateKey as Hex); - localStorage.setItem(STORAGE_PREFIX + account.address, privateKey); - - return privateKey; - }; - - const removeSessionKey = async (publicKey: Address) => { - await revokeAccess(publicKey); - localStorage.removeItem(STORAGE_PREFIX + publicKey); + localStorage.setItem(HAPPY_STORAGE_PREFIX + playerAddress, "true"); + } else return; }; const hideHelp = () => { @@ -73,75 +51,17 @@ export function Authorize() { )} - {sessionAddress ? ( + {weAreHappySponsored ? (
-

AUTHORIZING

-
- - -
+

+ 🤠 SESSION KEY REGISTERED 🤠 +

- {showDetails && ( - -
-
-
- Session Address: - - -
-

{sessionAddress}

-
-
-
- )}
) : ( - )}
diff --git a/packages/client/src/screens/Enter.tsx b/packages/client/src/screens/Enter.tsx index 59db0889d..0ef3ed79b 100644 --- a/packages/client/src/screens/Enter.tsx +++ b/packages/client/src/screens/Enter.tsx @@ -1,32 +1,32 @@ +import { requestSessionKey } from "@happy.tech/core"; import { useEffect, useState } from "react"; import { FaExclamationTriangle, FaInfoCircle } from "react-icons/fa"; import { useLocation, useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; -import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; -import { STORAGE_PREFIX } from "@primodiumxyz/core"; import { useAccountClient, useCore } from "@primodiumxyz/core/react"; import { defaultEntity } from "@primodiumxyz/reactive-tables"; import { Tooltip } from "@/components/core/Tooltip"; import { TransactionQueueMask } from "@/components/shared/TransactionQueueMask"; import { useContractCalls } from "@/hooks/useContractCalls"; -import { findEntriesWithPrefix } from "@/util/localStorage"; +import { HAPPY_STORAGE_PREFIX, isHappySessionKeyRegistered } from "@/util/localStorage"; import { Landing } from "./Landing"; export const Enter: React.FC = () => { const { tables } = useCore(); const { - playerAccount: { entity: playerEntity }, + playerAccount: { address: playerAddress, worldContract, entity: playerEntity }, sessionAccount, } = useAccountClient(); - const { grantAccessWithSignature, spawn } = useContractCalls(); + const { spawn } = useContractCalls(); const navigate = useNavigate(); const location = useLocation(); const [showingToast, setShowingToast] = useState(false); const [state, setState] = useState<"loading" | "delegate" | "play">("loading"); + const confirmSkip = async () => { toast.dismiss(); if (showingToast) await new Promise((resolve) => setTimeout(resolve, 500)); @@ -37,6 +37,9 @@ export const Enter: React.FC = () => {
Are you sure you want to skip? You will need to confirm every action with your external wallet. +
+
+ You can still enable a session key within the game settings.
@@ -72,8 +75,9 @@ export const Enter: React.FC = () => { }, ); }; + useEffect(() => { - if (!sessionAccount) { + if (!isHappySessionKeyRegistered(playerAddress)) { setState("delegate"); } else { setState("play"); @@ -93,13 +97,14 @@ export const Enter: React.FC = () => { navigate("/game" + location.search); }; - const handleDelegate = async () => { - const storedKeys = findEntriesWithPrefix(); - const privateKey = storedKeys.length > 0 ? storedKeys[0].privateKey : generatePrivateKey(); - const account = privateKeyToAccount(privateKey); - localStorage.setItem(STORAGE_PREFIX + account.address, privateKey); + const handleHappySessionKeyRegister = async () => { + if (!isHappySessionKeyRegistered(playerAddress)) { + // once this resolves, write a status into local storage that this has been done + await requestSessionKey(worldContract.address); - await grantAccessWithSignature(privateKey, { id: defaultEntity }); + localStorage.setItem(HAPPY_STORAGE_PREFIX + playerAddress, "true"); + setState("play"); + } else return; }; return ( @@ -108,7 +113,7 @@ export const Enter: React.FC = () => { {state === "delegate" && (