From 2f7b17c987427bcaa9ad04bf01edfd321ad00b88 Mon Sep 17 00:00:00 2001 From: Starknet Dev Date: Fri, 19 Jan 2024 12:55:40 +0000 Subject: [PATCH 1/3] - fix equip and drop ordering - close tx cart after submission - add new top up screen --- .../components/navigation/TransactionCart.tsx | 1 + ui/src/app/containers/TopUp.tsx | 875 ++++++++++++++++++ ui/src/app/lib/utils/syscalls.ts | 227 ++--- ui/src/app/page.tsx | 31 +- 4 files changed, 970 insertions(+), 164 deletions(-) create mode 100644 ui/src/app/containers/TopUp.tsx diff --git a/ui/src/app/components/navigation/TransactionCart.tsx b/ui/src/app/components/navigation/TransactionCart.tsx index 2383f52f5..5fed12049 100644 --- a/ui/src/app/components/navigation/TransactionCart.tsx +++ b/ui/src/app/components/navigation/TransactionCart.tsx @@ -480,6 +480,7 @@ const TransactionCart = ({ upgradeTx = newUpgradeTx; } } + setDisplayCart(false); await multicall(loadingMessage, notification, upgradeTx); handleResetCalls(); }} diff --git a/ui/src/app/containers/TopUp.tsx b/ui/src/app/containers/TopUp.tsx new file mode 100644 index 000000000..5b096a0af --- /dev/null +++ b/ui/src/app/containers/TopUp.tsx @@ -0,0 +1,875 @@ +import { useState, useEffect, ChangeEvent } from "react"; +import { MdClose } from "react-icons/md"; +import { + CompleteIcon, + InfoIcon, + SoundOffIcon, + SoundOnIcon, +} from "@/app/components/icons/Icons"; +import { Button } from "@/app/components/buttons/Button"; +import { getArcadeConnectors, getWalletConnectors } from "@/app/lib/connectors"; +import { + useAccount, + useConnect, + useDisconnect, + Connector, + ConnectVariables, +} from "@starknet-react/core"; +import { + Account, + AccountInterface, + Contract, + DeclareTransactionReceiptResponse, + RevertedTransactionReceiptResponse, + RejectedTransactionReceiptResponse, +} from "starknet"; +import { ETH_PREFUND_AMOUNT } from "@/app/lib/burner"; +import Eth from "public/icons/eth-2.svg"; +import Arcade from "public/icons/arcade.svg"; +import { formatCurrency, displayAddress } from "@/app/lib/utils"; +import { useBurner } from "@/app/lib/burner"; +import ArcadeLoader from "@/app/components/animations/ArcadeLoader"; +import useUIStore, { ScreenPage } from "@/app/hooks/useUIStore"; +import { useUiSounds, soundSelector } from "@/app/hooks/useUiSound"; +import { ETH_INCREMENT } from "@/app/lib/constants"; +import Storage from "@/app/lib/storage"; +import { BurnerStorage } from "@/app/types"; + +type Section = "connect" | "eth" | "lords" | "arcade"; + +const openInNewTab = (url: string) => { + const newWindow = window.open(url, "_blank", "noopener,noreferrer"); + if (newWindow) newWindow.opener = null; +}; + +interface SectionContentProps { + section: Section; + setSection: (section: Section) => void; + step: number; + address: string | undefined; + walletConnectors: Connector[]; + disconnect: () => void; + connect: (args?: ConnectVariables | undefined) => void; + eth: number; + lords: number; + lordsGameCost: number; + onMainnet: boolean; + network: string; + mintLords: (lordsAmount: number) => Promise; + prefundGames: number; + setPrefundGames: (games: number) => void; + setFullDeployment: (value: boolean) => void; + connector: Connector | undefined; + create: ( + connector: Connector, + lordsAmount: number + ) => Promise; + listConnectors: () => any[]; + updateConnectors: () => void; + handleOnboarded: () => void; + setScreen: (value: ScreenPage) => void; + masterConnected: boolean; + topUpEth: ( + address: string, + account: AccountInterface, + ethAmount?: number | undefined + ) => Promise< + | DeclareTransactionReceiptResponse + | RevertedTransactionReceiptResponse + | RejectedTransactionReceiptResponse + | undefined + >; + isToppingUpEth: boolean; + topUpAccount: string; + setTopUpAccount: (account: string) => void; + walletAccount: AccountInterface; + arcadeConnector: Connector; + showTopUpDialog: (value: boolean) => void; +} + +const SectionContent = ({ + section, + setSection, + step, + address, + walletConnectors, + disconnect, + connect, + eth, + lords, + lordsGameCost, + onMainnet, + network, + mintLords, + prefundGames, + setPrefundGames, + setFullDeployment, + connector, + create, + listConnectors, + updateConnectors, + handleOnboarded, + setScreen, + masterConnected, + topUpEth, + isToppingUpEth, + topUpAccount, + setTopUpAccount, + walletAccount, + arcadeConnector, + showTopUpDialog, +}: SectionContentProps) => { + const [inputValue, setInputValue] = useState(0); + + const handleChange = ( + e: ChangeEvent + ) => { + const { value } = e.target; + setInputValue(parseInt(value)); + }; + + const handleIncrement = () => { + const newInputValue = + inputValue + (onMainnet ? ETH_INCREMENT : ETH_INCREMENT / 10); + if (newInputValue >= 0) { + setInputValue(newInputValue); + } + }; + + const handleDecrement = () => { + const newInputValue = + inputValue - (onMainnet ? ETH_INCREMENT : ETH_INCREMENT / 10); + if (newInputValue >= 0) { + setInputValue(newInputValue); + } + }; + + const notEnoughDefaultBalance = eth < (onMainnet ? 0.01 : 0.001) * 10 ** 18; + const notEnoughCustomBalance = eth < inputValue * 10 ** 18; + + switch (section) { + case "connect": + return ( +
+ {step !== 1 && ( + <> +
+ {step > 1 && ( +
+

Connected {displayAddress(address!)}

+ +
+ )} + + )} +
+

Connect Starknet Wallet

+

+ In order to play LOOT SURVIVOR you are required to connect a + Starknet wallet. +

+ setSection("connect")} + > + +

No Wallet

+ + + +
+
+
+ {walletConnectors.map((connector, index) => ( + + ))} +
+
+ {walletConnectors.map((connector, index) => ( + + ))} +
+
+
+ ); + case "eth": + return ( +
+ {step !== 2 && ( + <> +
+ {step > 2 ? ( +
+ + You have {formatCurrency(eth)} ETH + + +
+ ) : ( +
+ Complete {step} +
+ )} + + )} +
+

Get ETH

+ + {onMainnet ? ( +

+ We are on {network} so you + are required to bridge from Ethereum or directly purchase + through one of the wallets. +

+ ) : ( +

+ We are on {network} so you + are able to get some test ETH from the faucet. +

+ )} + setSection("eth")} + > + +

More Info

+ + + +
+
+ + + +
+
+ ); + case "arcade": + return ( +
+ {step !== 3 && ( + <> +
+
+ Complete {step} +
+ + )} +
+

Top Up

+ +

Top up the Arcade Account with the acquired ETH.

+ +

+ Top Up Custom Amount +

+
+ e.preventDefault()} // Disable mouse wheel for the input + disabled={!masterConnected} + /> +
+ + +
+
+
+ + + {onMainnet ? "0.001 ETH Required" : "0.0001 ETH Required"} + + + + +
+
+
+ ); + default: + return <>; + } +}; + +const sectionInfo = (section: Section, lordsGameCost: number) => { + switch (section) { + case "connect": + return ( +
+

+ Starknet is an non-EVM Ethereum L2 that supports seperate wallets. +

+

Please install a wallet from the list below:

+
+ + +
+
+ ); + case "eth": + return ( +
+

+ ETH is required to pay gas for transactions on the Starknet network. +

+

This step will complete once you have at least 0.001 ETH.

+
+ ); + case "arcade": + return ( +
+

+ In order to get signerless txs you must create an Arcade Account. +

+

+ An Arcade Account is an acount which keys are stored in the browser. + The game can then sign txs without the need for the users wallet to + popup, saving time. +

+

+ In order to create the Arcade Account you will be asked to sign 2 + transactions: +

+
    +
  • Prefund the Account with LORDS & ETH
  • +
  • + Set permissions to allow the Arcade to play LOOT SURVIVOR and + withdraw to your main wallet +
  • +
+
+ ); + default: + return "Default content for unknown section"; + } +}; + +interface InfoBoxProps { + section: Section | undefined; + setSection: (section: Section | undefined) => void; + lordsGameCost: number; +} + +const InfoBox = ({ section, setSection, lordsGameCost }: InfoBoxProps) => { + return ( +
+ + + + + {sectionInfo(section!, lordsGameCost)} +
+ ); +}; + +interface TopUpProps { + ethBalance: bigint; + lordsBalance: bigint; + costToPlay: bigint; + mintLords: (lordsAmount: number) => Promise; + gameContract: Contract; + lordsContract: Contract; + ethContract: Contract; + updateConnectors: () => void; + showTopUpDialog: (value: boolean) => void; +} + +const TopUp = ({ + ethBalance, + lordsBalance, + costToPlay, + mintLords, + gameContract, + lordsContract, + ethContract, + updateConnectors, + showTopUpDialog, +}: TopUpProps) => { + const { account, address, connector } = useAccount(); + const { connect, connectors } = useConnect(); + const { disconnect } = useDisconnect(); + const walletConnectors = getWalletConnectors(connectors); + const arcadeConnectors = getArcadeConnectors(connectors); + + const isMuted = useUIStore((state) => state.isMuted); + const setIsMuted = useUIStore((state) => state.setIsMuted); + const topUpAccount = useUIStore((state) => state.topUpAccount); + const setTopUpAccount = useUIStore((state) => state.setTopUpAccount); + + const { play: clickPlay } = useUiSounds(soundSelector.click); + + const { + create, + isPrefunding, + isDeploying, + isSettingPermissions, + listConnectors, + showLoader, + topUpEth, + isToppingUpEth, + } = useBurner({ + walletAccount: account, + gameContract, + lordsContract, + ethContract, + }); + + const [section, setSection] = useState
(); + const [fullDeployment, setFullDeployment] = useState(false); + + const [step, setStep] = useState(1); + + const handleOnboarded = useUIStore((state) => state.handleOnboarded); + const setScreen = useUIStore((state) => state.setScreen); + + const eth = Number(ethBalance); + const lords = Number(lordsBalance); + const lordsGameCost = Number(costToPlay); + const [prefundGames, setPrefundGames] = useState(1); + + const checkEnoughEth = eth >= parseInt(ETH_PREFUND_AMOUNT); + const checkEnoughLords = lords > lordsGameCost; + + const network = process.env.NEXT_PUBLIC_NETWORK; + const onMainnet = process.env.NEXT_PUBLIC_NETWORK === "mainnet"; + + let storage: BurnerStorage = Storage.get("burners") || {}; + const masterConnected = address === storage[topUpAccount]?.masterAccount; + + const arcadeConnector = arcadeConnectors.find( + (connector) => connector.name === topUpAccount + ); + + useEffect(() => { + if (account && checkEnoughEth) { + setStep(3); + } else if (masterConnected) { + setStep(2); + } else { + setStep(1); + } + }, [account, checkEnoughEth, checkEnoughLords]); + + return ( +
+ + {section && ( + + )} + + +
+

Top Up Required

+

+ You have run out of ETH for gas on your Arcade Account, follow the + steps below to top up: +

+
+
+

1

+ +
+
+

2

+ +
+
+

3

+ +
+
+
+ {step == 1 && ( + + )} + {step == 2 && ( + + )} + {step == 3 && ( + + )} +
+
+
+
= 1 + ? "bg-terminal-green text-terminal-black" + : "border border-terminal-green" + }`} + > + {step > 1 ? : 1} +
+
= 2 + ? "bg-terminal-green text-terminal-black" + : "border border-terminal-green" + }`} + > + {step > 2 ? : 2} +
+
= 3 + ? "bg-terminal-green text-terminal-black" + : "border border-terminal-green" + }`} + > + 3 +
+
+
+
+
+ ); +}; + +export default TopUp; diff --git a/ui/src/app/lib/utils/syscalls.ts b/ui/src/app/lib/utils/syscalls.ts index a3ae97b7f..392338c21 100644 --- a/ui/src/app/lib/utils/syscalls.ts +++ b/ui/src/app/lib/utils/syscalls.ts @@ -484,10 +484,7 @@ export function syscalls({ ); const droppedItems = handleDrop(events, setData, setAdventurer); - const filteredDrops = queryData.itemsByAdventurerQuery?.items.filter( - (item: Item) => !droppedItems.includes(item.item ?? "") - ); - const filteredEquips = filteredDrops?.filter( + const filteredEquips = queryData.itemsByAdventurerQuery?.items?.filter( (item: Item) => !equippedItems.some((equippedItem) => equippedItem.item == item.item) ); @@ -495,12 +492,13 @@ export function syscalls({ (item: Item) => !unequippedItems.some((droppedItem) => droppedItem.item == item.item) ); + const filteredDrops = [ + ...(filteredUnequips ?? []), + ...equippedItems, + ...unequippedItems, + ]?.filter((item: Item) => !droppedItems.includes(item.item ?? "")); setData("itemsByAdventurerQuery", { - items: [ - ...(filteredUnequips ?? []), - ...equippedItems, - ...unequippedItems, - ], + items: [...filteredDrops], }); const discoveries: Discovery[] = []; @@ -761,10 +759,7 @@ export function syscalls({ ); const droppedItems = handleDrop(events, setData, setAdventurer); - const filteredDrops = queryData.itemsByAdventurerQuery?.items.filter( - (item: Item) => !droppedItems.includes(item.item ?? "") - ); - const filteredEquips = filteredDrops?.filter( + const filteredEquips = queryData.itemsByAdventurerQuery?.items?.filter( (item: Item) => !equippedItems.some((equippedItem) => equippedItem.item == item.item) ); @@ -772,12 +767,13 @@ export function syscalls({ (item: Item) => !unequippedItems.some((droppedItem) => droppedItem.item == item.item) ); + const filteredDrops = [ + ...(filteredUnequips ?? []), + ...equippedItems, + ...unequippedItems, + ]?.filter((item: Item) => !droppedItems.includes(item.item ?? "")); setData("itemsByAdventurerQuery", { - items: [ - ...(filteredUnequips ?? []), - ...equippedItems, - ...unequippedItems, - ], + items: [...filteredDrops], }); const battles = []; @@ -1027,10 +1023,7 @@ export function syscalls({ ); const droppedItems = handleDrop(events, setData, setAdventurer); - const filteredDrops = queryData.itemsByAdventurerQuery?.items.filter( - (item: Item) => !droppedItems.includes(item.item ?? "") - ); - const filteredEquips = filteredDrops?.filter( + const filteredEquips = queryData.itemsByAdventurerQuery?.items?.filter( (item: Item) => !equippedItems.some((equippedItem) => equippedItem.item == item.item) ); @@ -1038,12 +1031,13 @@ export function syscalls({ (item: Item) => !unequippedItems.some((droppedItem) => droppedItem.item == item.item) ); + const filteredDrops = [ + ...(filteredUnequips ?? []), + ...equippedItems, + ...unequippedItems, + ]?.filter((item: Item) => !droppedItems.includes(item.item ?? "")); setData("itemsByAdventurerQuery", { - items: [ - ...(filteredUnequips ?? []), - ...equippedItems, - ...unequippedItems, - ], + items: [...filteredDrops], }); const battles = []; @@ -1263,14 +1257,13 @@ export function syscalls({ for (let equippedItemsEvent of equippedItemsEvents) { for (let equippedItem of equippedItemsEvent.data[1]) { let item = purchasedItems.find((item) => item.item === equippedItem); - item.equipped = true; + if (item) { + item.equipped = true; + } } } - const filteredDrops = queryData.itemsByAdventurerQuery?.items.filter( - (item: Item) => !droppedItems.includes(item.item ?? "") - ); - const filteredEquips = filteredDrops?.filter( + const filteredEquips = queryData.itemsByAdventurerQuery?.items?.filter( (item: Item) => !equippedItems.some((equippedItem) => equippedItem.item == item.item) ); @@ -1278,13 +1271,13 @@ export function syscalls({ (item: Item) => !unequippedItems.some((droppedItem) => droppedItem.item == item.item) ); + const filteredDrops = [ + ...(filteredUnequips ?? []), + ...equippedItems, + ...unequippedItems, + ]?.filter((item: Item) => !droppedItems.includes(item.item ?? "")); setData("itemsByAdventurerQuery", { - items: [ - ...(filteredUnequips ?? []), - ...equippedItems, - ...unequippedItems, - ...purchasedItems, - ], + items: [...filteredDrops, ...purchasedItems], }); const adventurerDiedEvents = events.filter( @@ -1387,10 +1380,7 @@ export function syscalls({ ); const droppedItems = handleDrop(events, setData, setAdventurer); - const filteredDrops = queryData.itemsByAdventurerQuery?.items.filter( - (item: Item) => !droppedItems.includes(item.item ?? "") - ); - const filteredEquips = filteredDrops?.filter( + const filteredEquips = queryData.itemsByAdventurerQuery?.items?.filter( (item: Item) => !equippedItems.some((equippedItem) => equippedItem.item == item.item) ); @@ -1398,12 +1388,13 @@ export function syscalls({ (item: Item) => !unequippedItems.some((droppedItem) => droppedItem.item == item.item) ); + const filteredDrops = [ + ...(filteredUnequips ?? []), + ...equippedItems, + ...unequippedItems, + ]?.filter((item: Item) => !droppedItems.includes(item.item ?? "")); setData("itemsByAdventurerQuery", { - items: [ - ...(filteredUnequips ?? []), - ...equippedItems, - ...unequippedItems, - ], + items: [...filteredDrops], }); stopLoading(`You have slain all idle adventurers!`); @@ -1474,20 +1465,6 @@ export function syscalls({ adventurers: [equippedItemsEvent.data[0]], }); setAdventurer(equippedItemsEvent.data[0]); - for (let equippedItem of equippedItemsEvent.data[1]) { - const ownedItemIndex = - queryData.itemsByAdventurerQuery?.items.findIndex( - (item: Item) => item.item == equippedItem - ); - setData("itemsByAdventurerQuery", true, "equipped", ownedItemIndex); - } - for (let unequippedItem of equippedItemsEvent.data[2]) { - const ownedItemIndex = - queryData.itemsByAdventurerQuery?.items.findIndex( - (item: Item) => item.item == unequippedItem - ); - setData("itemsByAdventurerQuery", false, "equipped", ownedItemIndex); - } } const battles = []; @@ -1517,14 +1494,6 @@ export function syscalls({ adventurers: [droppedItemsEvent.data[0]], }); setAdventurer(droppedItemsEvent.data[0]); - let droppedItems: string[] = []; - for (let droppedItem of droppedItemsEvent.data[1]) { - droppedItems.push(droppedItem); - } - const newItems = queryData.itemsByAdventurerQuery?.items.filter( - (item: Item) => !droppedItems.includes(item?.item ?? "") - ); - setData("itemsByAdventurerQuery", { items: newItems }); } const adventurerDiedEvents = events.filter( @@ -1585,94 +1554,60 @@ export function syscalls({ (event) => event.name === "AdventurerUpgraded" ); for (let upgradeEvent of upgradeEvents) { - // If there are any equip or drops, do them first - const { equippedItems, unequippedItems } = handleEquip( - events, - setData, - setAdventurer, - queryData - ); // Update adventurer setData("adventurerByIdQuery", { adventurers: [upgradeEvent.data], }); setAdventurer(upgradeEvent.data); - const droppedItems = handleDrop(events, setData, setAdventurer); + // Reset items to no availability + setData("latestMarketItemsQuery", null); + setScreen("play"); + setUpdateDeathPenalty(true); + } - // Add purchased items - const purchaseItemsEvents = events.filter( - (event) => event.name === "PurchasedItems" - ); - const purchasedItems = []; - for (let purchasedItemEvent of purchaseItemsEvents) { - for (let purchasedItem of purchasedItemEvent.data[1]) { - purchasedItems.push(purchasedItem); - } + const droppedItems = handleDrop(events, setData, setAdventurer); + + // Add purchased items + const purchaseItemsEvents = events.filter( + (event) => event.name === "PurchasedItems" + ); + const purchasedItems = []; + for (let purchasedItemEvent of purchaseItemsEvents) { + for (let purchasedItem of purchasedItemEvent.data[1]) { + purchasedItems.push(purchasedItem); } - const equippedItemsEvents = events.filter( - (event) => event.name === "EquippedItems" - ); - for (let equippedItemsEvent of equippedItemsEvents) { - for (let equippedItem of equippedItemsEvent.data[1]) { - let item = purchasedItems.find( - (item) => item.item === equippedItem - ); + } + // If there are any equip or drops, do them first + const { equippedItems, unequippedItems } = handleEquip( + events, + setData, + setAdventurer, + queryData + ); + for (let equippedItemsEvent of equippedItemsEvents) { + for (let equippedItem of equippedItemsEvent.data[1]) { + let item = purchasedItems.find((item) => item.item === equippedItem); + if (item) { item.equipped = true; } } - let unequipIndexes = []; - for (let equippedItemsEvent of equippedItemsEvents) { - for (let unequippedItem of equippedItemsEvent.data[2]) { - const ownedItemIndex = - queryData.itemsByAdventurerQuery?.items.findIndex( - (item: Item) => item.item == unequippedItem - ); - let item = purchasedItems.find( - (item) => item.item === unequippedItem - ); - if (item) { - item.equipped = false; - } else { - unequipIndexes.push(ownedItemIndex); - } - } - } - const filteredDrops = queryData.itemsByAdventurerQuery?.items.filter( - (item: Item) => !droppedItems.includes(item.item ?? "") - ); - const filteredEquips = filteredDrops?.filter( - (item: Item) => - !equippedItems.some( - (equippedItem) => equippedItem.item == item.item - ) - ); - const filteredUnequips = filteredEquips?.filter( - (item: Item) => - !unequippedItems.some( - (droppedItem) => droppedItem.item == item.item - ) - ); - setData("itemsByAdventurerQuery", { - items: [ - ...(filteredUnequips ?? []), - ...equippedItems, - ...unequippedItems, - ...purchasedItems, - ], - }); - for (let i = 0; i < unequipIndexes.length; i++) { - setData( - "itemsByAdventurerQuery", - false, - "equipped", - unequipIndexes[i] - ); - } - // Reset items to no availability - setData("latestMarketItemsQuery", null); - setScreen("play"); - setUpdateDeathPenalty(true); } + const filteredEquips = queryData.itemsByAdventurerQuery?.items?.filter( + (item: Item) => + !equippedItems.some((equippedItem) => equippedItem.item == item.item) + ); + const filteredUnequips = filteredEquips?.filter( + (item: Item) => + !unequippedItems.some((droppedItem) => droppedItem.item == item.item) + ); + const filteredDrops = [ + ...(filteredUnequips ?? []), + ...equippedItems, + ...unequippedItems, + ]?.filter((item: Item) => !droppedItems.includes(item.item ?? "")); + setData("itemsByAdventurerQuery", { + items: [...filteredDrops, ...purchasedItems], + }); stopLoading(notification, false, "Multicall"); getEthBalance(); diff --git a/ui/src/app/page.tsx b/ui/src/app/page.tsx index f92de01d6..18f38ab42 100644 --- a/ui/src/app/page.tsx +++ b/ui/src/app/page.tsx @@ -49,14 +49,12 @@ import { getGoldenTokensByOwner, } from "@/app/hooks/graphql/queries"; import { ArcadeDialog } from "@/app/components/ArcadeDialog"; -import { TopUpDialog } from "@/app/components/TopUpDialog"; import NetworkSwitchError from "@/app/components/navigation/NetworkSwitchError"; import { syscalls } from "@/app/lib/utils/syscalls"; import Game from "@/app/abi/Game.json"; import Lords from "@/app/abi/Lords.json"; import EthBalanceFragment from "@/app/abi/EthBalanceFragment.json"; import Beasts from "@/app/abi/Beasts.json"; -// import { ArcadeIntro } from "@/app/components/intro/ArcadeIntro"; import ScreenMenu from "@/app/components/menu/ScreenMenu"; import { getArcadeConnectors, @@ -71,6 +69,7 @@ import { useBurner } from "@/app/lib/burner"; import { connectors } from "@/app/lib/connectors"; import Storage from "@/app/lib/storage"; import Onboarding from "./containers/Onboarding"; +import TopUp from "./containers/TopUp"; const allMenuItems: Menu[] = [ { id: 1, label: "Start", screen: "start", disabled: false }, @@ -514,15 +513,6 @@ function Home({ updateConnectors }: HomeProps) { <> {screen === "onboarding" ? ( - // + ) : status == "connected" && topUpDialog ? ( + ) : ( <>
@@ -572,13 +574,6 @@ function Home({ updateConnectors }: HomeProps) { costToPlay={costToPlay!} /> )} - {status == "connected" && topUpDialog && ( - - )} {introComplete ? (
From f18ea3e17592c3c0f98df828a84bc6c6dce1415f Mon Sep 17 00:00:00 2001 From: Starknet Dev Date: Fri, 19 Jan 2024 16:31:21 +0000 Subject: [PATCH 2/3] - remove notification after topup - get account balance after withdrawal --- ui/src/app/components/ArcadeDialog.tsx | 10 +- ui/src/app/containers/TopUp.tsx | 576 +++++++++++++------------ ui/src/app/page.tsx | 1 + 3 files changed, 306 insertions(+), 281 deletions(-) diff --git a/ui/src/app/components/ArcadeDialog.tsx b/ui/src/app/components/ArcadeDialog.tsx index c688f4de1..497349e25 100644 --- a/ui/src/app/components/ArcadeDialog.tsx +++ b/ui/src/app/components/ArcadeDialog.tsx @@ -35,6 +35,7 @@ interface ArcadeDialogProps { lordsBalance: number; ethBalance: number; costToPlay: bigint; + getAccountBalances: () => Promise; } export const ArcadeDialog = ({ @@ -45,6 +46,7 @@ export const ArcadeDialog = ({ lordsBalance, ethBalance, costToPlay, + getAccountBalances, }: ArcadeDialogProps) => { const [fetchedBalances, setFetchedBalances] = useState(false); const [recoverArcade, setRecoverArcade] = useState(false); @@ -117,7 +119,7 @@ export const ArcadeDialog = ({ setFetchedBalances(true); }; - const getAccountBalances = async (account: string) => { + const getArcadeBalances = async (account: string) => { const balances = await fetchBalances( account, ethContract!, @@ -234,7 +236,7 @@ export const ArcadeDialog = ({ genNewKey={genNewKey} setPermissions={setPermissions} balances={arcadebalances[account.name]} - getAccountBalances={getAccountBalances} + getAccountBalances={getArcadeBalances} topUpEth={topUpEth} topUpLords={topUpLords} withdraw={withdraw} @@ -242,6 +244,7 @@ export const ArcadeDialog = ({ lordsBalance={lordsBalance} ethBalance={ethBalance} lordsGameCost={lordsGameCost} + getBalances={getAccountBalances} /> ); })} @@ -305,6 +308,7 @@ interface ArcadeAccountCardProps { lordsBalance: number; ethBalance: number; lordsGameCost: number; + getBalances: () => Promise; } export const ArcadeAccountCard = ({ @@ -326,6 +330,7 @@ export const ArcadeAccountCard = ({ lordsBalance, ethBalance, lordsGameCost, + getBalances, }: ArcadeAccountCardProps) => { const { connect, connectors } = useConnect(); const [isCopied, setIsCopied] = useState(false); @@ -502,6 +507,7 @@ export const ArcadeAccountCard = ({ balances?.lords ); await getAccountBalances(account.name); + await getBalances(); }} disabled={isWithdrawing || minimalBalance} > diff --git a/ui/src/app/containers/TopUp.tsx b/ui/src/app/containers/TopUp.tsx index 5b096a0af..b09d9b034 100644 --- a/ui/src/app/containers/TopUp.tsx +++ b/ui/src/app/containers/TopUp.tsx @@ -30,10 +30,12 @@ import { formatCurrency, displayAddress } from "@/app/lib/utils"; import { useBurner } from "@/app/lib/burner"; import ArcadeLoader from "@/app/components/animations/ArcadeLoader"; import useUIStore, { ScreenPage } from "@/app/hooks/useUIStore"; +import useLoadingStore from "@/app/hooks/useLoadingStore"; import { useUiSounds, soundSelector } from "@/app/hooks/useUiSound"; import { ETH_INCREMENT } from "@/app/lib/constants"; import Storage from "@/app/lib/storage"; import { BurnerStorage } from "@/app/types"; +import TokenLoader from "@/app/components/animations/TokenLoader"; type Section = "connect" | "eth" | "lords" | "arcade"; @@ -85,6 +87,7 @@ interface SectionContentProps { walletAccount: AccountInterface; arcadeConnector: Connector; showTopUpDialog: (value: boolean) => void; + resetNotification: () => void; } const SectionContent = ({ @@ -118,6 +121,7 @@ const SectionContent = ({ walletAccount, arcadeConnector, showTopUpDialog, + resetNotification, }: SectionContentProps) => { const [inputValue, setInputValue] = useState(0); @@ -373,6 +377,7 @@ const SectionContent = ({ disconnect(); connect({ connector: arcadeConnector! }); showTopUpDialog(false); + resetNotification(); } else { onMainnet ? window.open( @@ -526,6 +531,8 @@ const TopUp = ({ const topUpAccount = useUIStore((state) => state.topUpAccount); const setTopUpAccount = useUIStore((state) => state.setTopUpAccount); + const resetNotification = useLoadingStore((state) => state.resetNotification); + const { play: clickPlay } = useUiSounds(soundSelector.click); const { @@ -581,294 +588,305 @@ const TopUp = ({ }, [account, checkEnoughEth, checkEnoughLords]); return ( -
- - {section && ( - + {isToppingUpEth && } +
+ - )} - - -
-

Top Up Required

-

- You have run out of ETH for gas on your Arcade Account, follow the - steps below to top up: -

-
-
-

1

- -
-
-

2

- -
-
-

3

- -
-
-
- {step == 1 && ( - - )} - {step == 2 && ( - - )} - {step == 3 && ( - +
-
-
-
= 1 - ? "bg-terminal-green text-terminal-black" - : "border border-terminal-green" - }`} - > - {step > 1 ? : 1} + + +
+

+ Top Up Required +

+

+ You have run out of ETH for gas on your Arcade Account, follow the + steps below to top up: +

+
+
+

1

+
-
= 2 - ? "bg-terminal-green text-terminal-black" - : "border border-terminal-green" - }`} - > - {step > 2 ? : 2} +
+

2

+
-
= 3 - ? "bg-terminal-green text-terminal-black" - : "border border-terminal-green" - }`} - > - 3 +
+

3

+ +
+
+
+ {step == 1 && ( + + )} + {step == 2 && ( + + )} + {step == 3 && ( + + )} +
+
+
+
= 1 + ? "bg-terminal-green text-terminal-black" + : "border border-terminal-green" + }`} + > + {step > 1 ? : 1} +
+
= 2 + ? "bg-terminal-green text-terminal-black" + : "border border-terminal-green" + }`} + > + {step > 2 ? : 2} +
+
= 3 + ? "bg-terminal-green text-terminal-black" + : "border border-terminal-green" + }`} + > + 3 +
-
+ ); }; diff --git a/ui/src/app/page.tsx b/ui/src/app/page.tsx index 18f38ab42..13b544280 100644 --- a/ui/src/app/page.tsx +++ b/ui/src/app/page.tsx @@ -572,6 +572,7 @@ function Home({ updateConnectors }: HomeProps) { lordsBalance={Number(lordsBalance)} ethBalance={Number(ethBalance)} costToPlay={costToPlay!} + getAccountBalances={getBalances} /> )} From 6b588517371fe40820d7e94cf0149c6ce7f16c5c Mon Sep 17 00:00:00 2001 From: Starknet Dev Date: Fri, 19 Jan 2024 18:49:01 +0000 Subject: [PATCH 3/3] - add auto arcade account connection (first created) - switch to screen player is in game - add eth topup difference in testnet --- ui/src/app/components/arcade/TopupInput.tsx | 8 +++-- .../app/components/start/AdventurersList.tsx | 6 ++-- ui/src/app/page.tsx | 32 +++++++++++++++++-- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/ui/src/app/components/arcade/TopupInput.tsx b/ui/src/app/components/arcade/TopupInput.tsx index 0e0b01dba..acf94592f 100644 --- a/ui/src/app/components/arcade/TopupInput.tsx +++ b/ui/src/app/components/arcade/TopupInput.tsx @@ -33,6 +33,8 @@ const TopupInput = ({ const [showInput, setShowInput] = useState(false); const [inputValue, setInputValue] = useState(0); + const onMainnet = process.env.NEXT_PUBLIC_NETWORK === "mainnet"; + const handleChange = ( e: ChangeEvent ) => { @@ -76,7 +78,7 @@ const TopupInput = ({ const mainTopupDisabled = balanceType === "eth" - ? ethBalance < 0.01 * 10 ** 18 + ? ethBalance < (onMainnet ? 0.01 : 0.001) * 10 ** 18 : lordsBalance < lordsGameCost; const inputTopupInvalid = inputValue * 10 ** 18 > (balanceType === "eth" ? ethBalance : lordsBalance); @@ -138,7 +140,9 @@ const TopupInput = ({ disabled={disabled || mainTopupDisabled} > {balanceType === "eth" - ? "Add 0.01 ETH" + ? onMainnet + ? "Add 0.01 ETH" + : "Add 0.001 ETH" : `Add ${formatCurrency(lordsGameCost)} LORDS`}