diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ae2b66e..d127910 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,6 +1,6 @@ import { cssObj } from "@fuel-ui/css"; import { Box, BoxCentered, Heading } from "@fuel-ui/react"; -import { useIsConnected, useWallet, useCurrentConnector } from "@fuels/react"; +import { useIsConnected, useWallet } from "@fuels/react"; //Add Analytics import { useState, useEffect, useMemo } from "react"; @@ -22,13 +22,11 @@ function App() { ); const { isConnected } = useIsConnected(); const { wallet } = useWallet(); - const { currentConnector } = useCurrentConnector(); useEffect(() => { const userAgent = navigator.userAgent.toLowerCase(); const mobile = /(iphone|android|windows phone)/.test(userAgent); setIsMobile(mobile); - console.log("currentConnector", currentConnector?.name); }, []); const contract = useMemo(() => { diff --git a/frontend/src/components/NewPlayer.tsx b/frontend/src/components/NewPlayer.tsx index 0329cd0..8bc9b56 100644 --- a/frontend/src/components/NewPlayer.tsx +++ b/frontend/src/components/NewPlayer.tsx @@ -35,7 +35,7 @@ export default function NewPlayer({ "error" | "loading" | "retrying" | "none" >("none"); const [hasFunds, setHasFunds] = useState(false); - + const [showNoFunds, setShowNoFunds] = useState(false); const { wallet } = useWallet(); const paymaster = usePaymaster(); const isGaslessSupported = useGaslessWalletSupported(); @@ -53,11 +53,6 @@ export default function NewPlayer({ if (balanceNum) { setHasFunds(balanceNum > 0); - if (balanceNum > 0) { - toast.success("You have enough funds to play!"); - } else { - toast.error("You need some ETH to play. Please visit the Bridge."); - } } } @@ -146,7 +141,7 @@ export default function NewPlayer({ if (!canUseGasless) { toast.error( "Hourly gasless transaction limit reached. Trying regular transaction...", - { duration: 5000 } + { duration: 5000 }, ); } if (isGaslessSupported && canUseGasless) { @@ -159,11 +154,25 @@ export default function NewPlayer({ ); toast.error("Gas Station error, please sign from wallet."); setStatus("retrying"); - await createPlayerWithoutGasStation(); + if (!hasFunds) { + setShowNoFunds(true); + setTimeout(() => { + setShowNoFunds(false); + }, 5000); + } else { + await createPlayerWithoutGasStation(); + } } } else { - console.log("Using direct transaction method..."); - await createPlayerWithoutGasStation(); + if (!hasFunds) { + setShowNoFunds(true); + setTimeout(() => { + setShowNoFunds(false); + }, 5000); + } else { + console.log("Using direct transaction method..."); + await createPlayerWithoutGasStation(); + } } setStatus("none"); @@ -181,12 +190,12 @@ export default function NewPlayer({ return (
- {status === "none" && ( + {status === "none" && !showNoFunds && ( )} - {status === "none" && !hasFunds && ( + {status === "none" && !hasFunds && showNoFunds && ( You need some ETH to play: @@ -233,7 +242,6 @@ const styles = { fontFamily: "pressStart2P", fontSize: "14px", gap: "20px", - display: "none", }), link: cssObj({ fontFamily: "pressStart2P", diff --git a/frontend/src/components/modals/BuySeeds.tsx b/frontend/src/components/modals/BuySeeds.tsx index 6df17ee..46e3576 100644 --- a/frontend/src/components/modals/BuySeeds.tsx +++ b/frontend/src/components/modals/BuySeeds.tsx @@ -2,6 +2,8 @@ import { Button, Spinner, BoxCentered } from "@fuel-ui/react"; import { type BytesLike, Address, bn, Provider } from "fuels"; import type { Dispatch, SetStateAction } from "react"; import { useState } from "react"; +import { useWalletFunds } from "../../hooks/useWalletFunds"; +import { NoFundsMessage } from "./NoFundsMessage"; import { FUEL_PROVIDER_URL, useGaslessWalletSupported } from "../../constants"; import { buttonStyle, FoodTypeInput } from "../../constants"; import type { FarmContract } from "../../sway-api/contracts/FarmContract"; @@ -28,6 +30,8 @@ export default function BuySeeds({ const { wallet } = useWallet(); const paymaster = usePaymaster(); const isGaslessSupported = useGaslessWalletSupported(); + const { hasFunds, showNoFunds, getBalance, showNoFundsMessage } = + useWalletFunds(contract); async function buyWithGasStation() { if (!wallet) { @@ -88,7 +92,7 @@ export default function BuySeeds({ estimateTxDependencies: false, }); if (tx) { - console.log("tx", tx); + toast.success("Successfully bought seeds!"); updatePageNum(); } } @@ -116,6 +120,8 @@ export default function BuySeeds({ .call(); if (tx) { + toast.success("Successfully bought seeds!"); + updatePageNum(); } return tx; @@ -130,11 +136,12 @@ export default function BuySeeds({ setStatus("loading"); setCanMove(false); const canUseGasless = await paymaster.shouldUseGasless(); - if(!canUseGasless) { - toast.error("Hourly gasless transaction limit reached. Trying regular transaction...", - { duration: 5000 }); + if (!canUseGasless) { + toast.error( + "Hourly gasless transaction limit reached. Trying regular transaction...", + { duration: 5000 }, + ); } - if (isGaslessSupported && canUseGasless) { try { await buyWithGasStation(); @@ -143,16 +150,24 @@ export default function BuySeeds({ "Gas station failed, trying direct transaction...", error, ); + toast.error("Gas Station error, please sign from wallet."); setStatus("retrying"); - await buyWithoutGasStation(); + if (!hasFunds) { + showNoFundsMessage(); + } else { + await buyWithoutGasStation(); + } } } else { - console.log("Using direct transaction method..."); - await buyWithoutGasStation(); + if (!hasFunds) { + showNoFundsMessage(); + } else { + console.log("Using direct transaction method..."); + await buyWithoutGasStation(); + } } setStatus("none"); - toast.success("Successfully bought seeds!"); } catch (err) { console.log("Error in BuySeeds:", err); setStatus("error"); @@ -193,7 +208,7 @@ export default function BuySeeds({
)} - {status === "none" && ( + {status === "none" && !showNoFunds && ( <>
Buy Seeds
)} + {status === "none" && !hasFunds && showNoFunds && ( + + )} ); } diff --git a/frontend/src/components/modals/HarvestModal.tsx b/frontend/src/components/modals/HarvestModal.tsx index e0bb708..040afd6 100644 --- a/frontend/src/components/modals/HarvestModal.tsx +++ b/frontend/src/components/modals/HarvestModal.tsx @@ -1,6 +1,7 @@ import { Spinner, Button, BoxCentered } from "@fuel-ui/react"; import type { Dispatch, SetStateAction } from "react"; import { useState } from "react"; +import { cssObj } from "@fuel-ui/css"; import { buttonStyle, @@ -13,6 +14,8 @@ import { useWallet } from "@fuels/react"; import { Address, Provider } from "fuels"; import { usePaymaster } from "../../hooks/usePaymaster"; import { toast } from "react-hot-toast"; +import { useWalletFunds } from "../../hooks/useWalletFunds"; +import { NoFundsMessage } from "./NoFundsMessage"; interface HarvestProps { contract: FarmContract | null; @@ -37,6 +40,8 @@ export default function HarvestModal({ const { wallet } = useWallet(); const paymaster = usePaymaster(); const isGaslessSupported = useGaslessWalletSupported(); + const { hasFunds, showNoFunds, getBalance, showNoFundsMessage } = + useWalletFunds(contract); async function harvestWithoutGasStation() { if (!wallet || !contract) throw new Error("Wallet or contract not found"); @@ -79,7 +84,7 @@ export default function HarvestModal({ request.addCoinOutput( gasCoin.owner, gasCoin.amount.sub(maxValuePerCoin), - provider.getBaseAssetId() + provider.getBaseAssetId(), ); request.addChangeOutput(gasCoin.owner, provider.getBaseAssetId()); @@ -113,7 +118,7 @@ export default function HarvestModal({ if (!canUseGasless) { toast.error( "Hourly gasless transaction limit reached. Trying regular transaction...", - { duration: 5000 } + { duration: 5000 }, ); } if (isGaslessSupported && canUseGasless) { @@ -122,17 +127,23 @@ export default function HarvestModal({ } catch (error) { console.log( "Gas station failed, trying direct transaction...", - error - ); - toast.error( - "Failed to harvest the seed :( Retrying with alternate method..." + error, ); + toast.error("Gas Station error, please sign from wallet."); setStatus("retrying"); - await harvestWithoutGasStation(); + if (!hasFunds) { + showNoFundsMessage(); + } else { + await harvestWithoutGasStation(); + } } } else { - console.log("Using direct transaction method..."); - await harvestWithoutGasStation(); + if (!hasFunds) { + showNoFundsMessage(); + } else { + console.log("Using direct transaction method..."); + await harvestWithoutGasStation(); + } } setStatus("none"); @@ -176,7 +187,10 @@ export default function HarvestModal({ )} - {status === "none" && ( + {status === "none" && !hasFunds && showNoFunds && ( + + )} + {status === "none" && !hasFunds && !showNoFunds && ( <>
Harvest this item?
+ + + + ); +} + +const styles = { + container: cssObj({ + flexDirection: "column", + fontFamily: "pressStart2P", + fontSize: "14px", + gap: "20px", + }), + link: cssObj({ + fontFamily: "pressStart2P", + fontSize: "14px", + }), +}; diff --git a/frontend/src/components/modals/PlantModal.tsx b/frontend/src/components/modals/PlantModal.tsx index 32a688c..cd63b97 100644 --- a/frontend/src/components/modals/PlantModal.tsx +++ b/frontend/src/components/modals/PlantModal.tsx @@ -1,6 +1,8 @@ import { Button } from "@fuel-ui/react"; import type { Dispatch, SetStateAction } from "react"; import { useState } from "react"; +import { useWalletFunds } from "../../hooks/useWalletFunds"; +import { NoFundsMessage } from "./NoFundsMessage"; import { buttonStyle, @@ -41,6 +43,8 @@ export default function PlantModal({ const { wallet } = useWallet(); const paymaster = usePaymaster(); const isGaslessSupported = useGaslessWalletSupported(); + const { hasFunds, showNoFunds, getBalance, showNoFundsMessage } = + useWalletFunds(contract); async function plantWithoutGasStation() { if (!wallet || !contract) throw new Error("Wallet or contract not found"); @@ -59,7 +63,7 @@ export default function PlantModal({ if (tx) { onPlantSuccess(tileArray[0]); setModal("none"); - toast.success("Planted the seed!"); + toast.success("Seed planted!"); updatePageNum(); } return tx; @@ -106,7 +110,7 @@ export default function PlantModal({ onPlantSuccess(tileArray[0]); setModal("none"); updatePageNum(); - toast.success("Planted the seed!"); + toast.success("Seed planted!"); } } @@ -122,7 +126,7 @@ export default function PlantModal({ if (!canUseGasless) { toast.error( "Hourly gasless transaction limit reached. Trying regular transaction...", - { duration: 5000 } + { duration: 5000 }, ); } if (isGaslessSupported && canUseGasless) { @@ -133,15 +137,21 @@ export default function PlantModal({ "Gas station failed, trying direct transaction...", error, ); + toast.error("Gas Station error, please sign from wallet."); setStatus("retrying"); - toast.error( - "Failed to plant the seed :( Retrying with alternate method...", - ); - await plantWithoutGasStation(); + if (!hasFunds) { + showNoFundsMessage(); + } else { + await plantWithoutGasStation(); + } } } else { - console.log("Using direct transaction method..."); - await plantWithoutGasStation(); + if (!hasFunds) { + showNoFundsMessage(); + } else { + console.log("Using direct transaction method..."); + await plantWithoutGasStation(); + } } setStatus("none"); @@ -176,7 +186,7 @@ export default function PlantModal({ )} - {status === "none" && ( + {status === "none" && !showNoFunds && ( <> {seeds > 0 ? ( <> @@ -190,6 +200,9 @@ export default function PlantModal({ )} )} + {status === "none" && !hasFunds && showNoFunds && ( + + )} ); } diff --git a/frontend/src/components/modals/SellItem.tsx b/frontend/src/components/modals/SellItem.tsx index 7dbf019..20df473 100644 --- a/frontend/src/components/modals/SellItem.tsx +++ b/frontend/src/components/modals/SellItem.tsx @@ -2,6 +2,8 @@ import { Button } from "@fuel-ui/react"; import { Address, InputType, Provider, bn } from "fuels"; import type { Dispatch, SetStateAction } from "react"; import { useState } from "react"; +import { useWalletFunds } from "../../hooks/useWalletFunds"; +import { NoFundsMessage } from "./NoFundsMessage"; import { buttonStyle, @@ -34,6 +36,8 @@ export default function SellItem({ const { wallet } = useWallet(); const paymaster = usePaymaster(); const isGaslessSupported = useGaslessWalletSupported(); + const { hasFunds, showNoFunds, getBalance, showNoFundsMessage } = + useWalletFunds(contract); async function sellWithoutGasStation() { if (!wallet || !contract) throw new Error("Wallet or contract not found"); @@ -128,7 +132,7 @@ export default function SellItem({ if (!canUseGasless) { toast.error( "Hourly gasless transaction limit reached. Trying regular transaction...", - { duration: 5000 } + { duration: 5000 }, ); } if (isGaslessSupported && canUseGasless) { @@ -139,12 +143,21 @@ export default function SellItem({ "Gas station failed, trying direct transaction...", error, ); + toast.error("Gas Station error, please sign from wallet."); setStatus("retrying"); - await sellWithoutGasStation(); + if (!hasFunds) { + showNoFundsMessage(); + } else { + await sellWithoutGasStation(); + } } } else { - console.log("Using direct transaction method..."); - await sellWithoutGasStation(); + if (!hasFunds) { + showNoFundsMessage(); + } else { + console.log("Using direct transaction method..."); + await sellWithoutGasStation(); + } } setStatus("none"); @@ -181,11 +194,14 @@ export default function SellItem({ )} - {status === "none" && ( + {status === "none" && !showNoFunds && ( )} + {status === "none" && !hasFunds && showNoFunds && ( + + )} ); } diff --git a/frontend/src/hooks/useWalletFunds.ts b/frontend/src/hooks/useWalletFunds.ts new file mode 100644 index 0000000..b228981 --- /dev/null +++ b/frontend/src/hooks/useWalletFunds.ts @@ -0,0 +1,38 @@ +import { useEffect, useState } from "react"; +import { useWallet } from "@fuels/react"; +import type { FarmContract } from "../sway-api"; + +export function useWalletFunds(contract: FarmContract | null) { + const [hasFunds, setHasFunds] = useState(false); + const [showNoFunds, setShowNoFunds] = useState(false); + const { wallet } = useWallet(); + + useEffect(() => { + getBalance(); + }, [wallet]); + + async function getBalance() { + const thisWallet = wallet ?? contract?.account; + const baseAssetId = thisWallet?.provider.getBaseAssetId(); + const balance = await thisWallet!.getBalance(baseAssetId); + const balanceNum = balance?.toNumber(); + + if (balanceNum) { + setHasFunds(balanceNum > 0); + } + } + + const showNoFundsMessage = (duration = 15000) => { + setShowNoFunds(true); + setTimeout(() => { + setShowNoFunds(false); + }, duration); + }; + + return { + hasFunds, + showNoFunds, + getBalance, + showNoFundsMessage, + }; +}