diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 32e84eaf1..df69a0416 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,13 +26,13 @@ jobs: uses: actions/checkout@master - name: Install scarb - run: curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh -s -- -v 2.8.5 + run: curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh -s -- -v 2.9.2 - name: Install snfoundryup run: curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | sh - name: Install snforge - run: snfoundryup -v 0.33.0 + run: snfoundryup -v 0.34.0 - name: Run snforge tests run: snforge test diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29bb..000000000 diff --git a/.tool-versions b/.tool-versions index 40fcaab27..d9a702a02 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -scarb 2.8.5 -starknet-foundry 0.33.0 -starknet-devnet 0.2.0 +scarb 2.9.2 +starknet-foundry 0.34.0 +starknet-devnet 0.2.3 diff --git a/README.md b/README.md index ac9fba99a..7c96c7db8 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,11 @@ Before you begin, you need to install the following tools: ### Compatible versions -- Starknet-devnet - v0.2.0 -- Scarb - v2.8.5 -- Snforge - v0.33.0 -- Cairo - v2.8.5 -- RPC - v0.7.1 +- Starknet-devnet - v0.2.3 +- Scarb - v2.9.2 +- Snforge - v0.34.0 +- Cairo - v2.9.2 +- Rpc - v0.7.1 Make sure you have the compatible versions otherwise refer to [Scaffold-Stark Requirements](https://github.com/Scaffold-Stark/scaffold-stark-2?.tab=readme-ov-file#requirements) diff --git a/package.json b/package.json index 4321fdce4..4126dd272 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ss-2", - "version": "0.3.2", + "version": "0.3.13", "author": "Q3 Labs", "license": "MIT", "private": true, @@ -13,7 +13,7 @@ "scripts": { "chain": "yarn workspace @ss-2/snfoundry chain", "deploy": "yarn workspace @ss-2/snfoundry deploy", - "deploy:reset": "yarn workspace @ss-2/snfoundry deploy:reset", + "deploy:no-reset": "yarn workspace @ss-2/snfoundry deploy --no-reset", "test": "yarn workspace @ss-2/snfoundry test", "compile": "yarn workspace @ss-2/snfoundry compile", "start": "yarn workspace @ss-2/nextjs dev", diff --git a/packages/nextjs/.env.example b/packages/nextjs/.env.example index a207edc11..b469dd895 100644 --- a/packages/nextjs/.env.example +++ b/packages/nextjs/.env.example @@ -1 +1 @@ -NEXT_PUBLIC_PROVIDER_URL=https://starknet-sepolia.public.blastapi.io/rpc/v0_7 +NEXT_PUBLIC_PROVIDER_URL=https://starknet-sepolia.blastapi.io/64168c77-3fa5-4e1e-9fe4-41675d212522/rpc/v0_7 diff --git a/packages/nextjs/.eslintrc.json b/packages/nextjs/.eslintrc.json index bffb357a7..15b1ed91a 100644 --- a/packages/nextjs/.eslintrc.json +++ b/packages/nextjs/.eslintrc.json @@ -1,3 +1,3 @@ { - "extends": "next/core-web-vitals" + "extends": "next" } diff --git a/packages/nextjs/app/configure/_components/DownloadContracts.tsx b/packages/nextjs/app/configure/_components/DownloadContracts.tsx index affc55f94..709419421 100644 --- a/packages/nextjs/app/configure/_components/DownloadContracts.tsx +++ b/packages/nextjs/app/configure/_components/DownloadContracts.tsx @@ -1,25 +1,24 @@ "use client"; import { useProvider } from "@starknet-react/core"; -import React, { useState } from "react"; +import { useCallback, useState } from "react"; import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork"; import configExternalContracts from "~~/contracts/configExternalContracts"; import { deepMergeContracts } from "~~/utils/scaffold-stark/contract"; import { ArrowDownTrayIcon } from "@heroicons/react/24/outline"; import Link from "next/link"; +import prettier from "prettier/standalone"; +import parserTypescript from "prettier/plugins/typescript"; +import prettierPluginEstree from "prettier/plugins/estree"; export default function DownloadContracts() { const { provider } = useProvider(); const [address, setAddress] = useState(""); const { targetNetwork } = useTargetNetwork(); - const [symbol, setSymbol] = useState(""); - const handleInputChange: React.ChangeEventHandler = (e) => { - const value = e.target.value; - setSymbol(value); - }; + const [contractName, setContractName] = useState(""); - const handleDownload = async () => { + const handleDownload = useCallback(async () => { if (!address) return; try { const [apiResponse, classHash] = await Promise.all([ @@ -29,7 +28,7 @@ export default function DownloadContracts() { const contractData = { [targetNetwork.network]: { - [symbol]: { + [contractName]: { address, classHash, abi: apiResponse.abi, @@ -46,17 +45,23 @@ export default function DownloadContracts() { console.error(error); return; } - }; + }, [address, provider, contractName, targetNetwork.network]); - const generateContractsFile = (contractsData: Object) => { + const generateContractsFile = async (contractsData: Object) => { const generatedContractComment = `/** * This file is autogenerated by Scaffold-Stark. * You should not edit it manually or your changes might be overwritten. */`; - const fileContent = JSON.stringify(contractsData, null, 2); - const configExternalContracts = `${generatedContractComment}\n\nconst configExternalContracts = ${fileContent} as const;\n\nexport default configExternalContracts;`; - + const configExternalContracts = await prettier.format( + `${generatedContractComment}\n\nconst configExternalContracts = ${JSON.stringify( + contractsData, + )} as const;\n\nexport default configExternalContracts;`, + { + parser: "typescript", + plugins: [parserTypescript, prettierPluginEstree], + }, + ); const blob = new Blob([configExternalContracts], { type: "text/typescript", }); @@ -78,49 +83,35 @@ export default function DownloadContracts() {
Instructions

- This tool allows you to fetch the ABI of a contract by entering - its address. It will download a configuration file that can be - used to replace or append to your local{" "} + This tool generate a contract configuration file by entering a + contract address and name. The downloaded file can be used to + replace your local{" "} configExternalContracts.ts{" "} - file, allowing you to debug in the{" "} - /debug page. + for debugging.

    +
  1. Enter contract name and address
  2. - Enter the contract address and name within the designated input - fields. -
  3. -
  4. - Click the{" "} + Click{" "} Download Contract File - {" "} - button. -
  5. -
  6. - The tool will fetch the ABI, address, and classHash from the - network and generate a configuration file. +
  7. - Download the file and replace it to your local{" "} + Replace your{" "} configExternalContracts.ts {" "} - file. + file
  8. - Use the{" "} + Debug your contract at{" "} /debug {" "} - page to interact with and test the contract using the scaffold - hooks. + and use hooks with the downloaded contract
-

- Ensure that the format of the ABI matches the expected format in - your project before replacing the file. -

{targetNetwork && ( @@ -136,8 +127,8 @@ export default function DownloadContracts() { Contract
setContractName(e.target.value)} list="symbols" className="input bg-input input-ghost rounded-none focus-within:border-transparent focus:outline-none h-[2.2rem] min-h-[2.2rem] px-4 border w-full text-sm placeholder:text-[#9596BF] text-neutral" placeholder="Enter contract name" diff --git a/packages/nextjs/app/configure/page.tsx b/packages/nextjs/app/configure/page.tsx index 661e8c25d..693c83f65 100644 --- a/packages/nextjs/app/configure/page.tsx +++ b/packages/nextjs/app/configure/page.tsx @@ -8,11 +8,7 @@ export const metadata = getMetadata({ }); const Configure: NextPage = () => { - return ( - <> - - - ); + return ; }; export default Configure; diff --git a/packages/nextjs/app/debug/_components/contract/ContractUI.tsx b/packages/nextjs/app/debug/_components/contract/ContractUI.tsx index 691a86d32..e49b7cfae 100644 --- a/packages/nextjs/app/debug/_components/contract/ContractUI.tsx +++ b/packages/nextjs/app/debug/_components/contract/ContractUI.tsx @@ -10,7 +10,10 @@ import { useNetworkColor, } from "~~/hooks/scaffold-stark"; import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork"; -import { ContractName } from "~~/utils/scaffold-stark/contract"; +import { + ContractCodeStatus, + ContractName, +} from "~~/utils/scaffold-stark/contract"; import { ContractVariables } from "./ContractVariables"; import { ClassHash } from "~~/components/scaffold-stark/ClassHash"; @@ -40,23 +43,18 @@ export const ContractUI = ({ false, ); const { targetNetwork } = useTargetNetwork(); - const { data: deployedContractData, isLoading: deployedContractLoading } = - useDeployedContractInfo(contractName); + const { + raw: deployedContractData, + isLoading: deployedContractLoading, + status, + } = useDeployedContractInfo(contractName); const tabs = [ { id: "read", label: "Read" }, { id: "write", label: "Write" }, ]; - if (deployedContractLoading) { - return ( -
- -
- ); - } - - if (!deployedContractData) { + if (status === ContractCodeStatus.NOT_FOUND) { return (

{`No contract found by the name of "${contractName}" on chain "${targetNetwork.name}"!`} @@ -79,7 +77,7 @@ export const ContractUI = ({ classHash={deployedContractData.classHash} size="xs" /> -

diff --git a/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx b/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx index 23f2107cb..b6dc0cfe7 100644 --- a/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx +++ b/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx @@ -59,7 +59,9 @@ export const DisplayVariable = ({

{abiFunction.name}

diff --git a/packages/nextjs/app/debug/_components/contract/Struct.tsx b/packages/nextjs/app/debug/_components/contract/Struct.tsx index 7f493ffb2..699598d26 100644 --- a/packages/nextjs/app/debug/_components/contract/Struct.tsx +++ b/packages/nextjs/app/debug/_components/contract/Struct.tsx @@ -69,11 +69,15 @@ export const Struct = ({ return (
{!isDisabled && }

{abiMember.type}

diff --git a/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx b/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx index 59f1c6589..df595cbd4 100644 --- a/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx +++ b/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx @@ -27,6 +27,7 @@ export const TxReceipt = ( aria-hidden="true" /> ) : ( + //@ts-ignore coponent works but some typing issue came up, ts-expect-error does not work { diff --git a/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx b/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx index a2ced2a2f..5537971d1 100644 --- a/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx +++ b/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx @@ -1,5 +1,5 @@ import { getChecksumAddress, Uint256 } from "starknet"; -import { replacer } from "~~/utils/scaffold-stark/common"; +import { feltToHex, replacer } from "~~/utils/scaffold-stark/common"; import { AbiOutput } from "~~/utils/scaffold-stark/contract"; import { isCairoArray, @@ -139,11 +139,11 @@ const _decodeContractResponseItem = ( abiType.type && abiType.type === "core::starknet::contract_address::ContractAddress" ) { - return getChecksumAddress(`0x${respItem.toString(16)}`); + return getChecksumAddress(feltToHex(respItem)); } if (abiType.type && baseHexType.has(abiType.type)) { - const hexString = `0x${respItem.toString(16)}`; + const hexString = feltToHex(respItem); if (showAsString) { return hexToAscii(hexString) || hexString; } diff --git a/packages/nextjs/app/debug/page.tsx b/packages/nextjs/app/debug/page.tsx index eb2beb583..a675135ea 100644 --- a/packages/nextjs/app/debug/page.tsx +++ b/packages/nextjs/app/debug/page.tsx @@ -9,11 +9,7 @@ export const metadata = getMetadata({ }); const Debug: NextPage = () => { - return ( - <> - - - ); + return ; }; export default Debug; diff --git a/packages/nextjs/app/layout.tsx b/packages/nextjs/app/layout.tsx index 541f3f851..c14ec5719 100644 --- a/packages/nextjs/app/layout.tsx +++ b/packages/nextjs/app/layout.tsx @@ -2,11 +2,9 @@ import type { Metadata } from "next"; import { ScaffoldStarkAppWithProviders } from "~~/components/ScaffoldStarkAppWithProviders"; import "~~/styles/globals.css"; import { ThemeProvider } from "~~/components/ThemeProvider"; -import { Space_Grotesk } from "next/font/google"; -const spaceGrotesk = Space_Grotesk({ subsets: ["latin"] }); export const metadata: Metadata = { - title: "Speedrun Stark", + title: "Scaffold-Stark", description: "Fast track your starknet journey", icons: "/logo.ico", }; @@ -14,7 +12,7 @@ export const metadata: Metadata = { const ScaffoldStarkApp = ({ children }: { children: React.ReactNode }) => { return ( - + {children} diff --git a/packages/nextjs/components/ConnectedAddress.tsx b/packages/nextjs/components/ConnectedAddress.tsx new file mode 100644 index 000000000..39eee6131 --- /dev/null +++ b/packages/nextjs/components/ConnectedAddress.tsx @@ -0,0 +1,14 @@ +"use client"; +import { useAccount } from "~~/hooks/useAccount"; +import { Address } from "./scaffold-stark"; +import { Address as AddressType } from "@starknet-react/chains"; + +export const ConnectedAddress = () => { + const connectedAddress = useAccount(); + return ( +
+

Connected Address:

+
+
+ ); +}; diff --git a/packages/nextjs/components/Footer.tsx b/packages/nextjs/components/Footer.tsx index ca71b5552..cf126f2f7 100644 --- a/packages/nextjs/components/Footer.tsx +++ b/packages/nextjs/components/Footer.tsx @@ -1,5 +1,3 @@ -import React, { useEffect } from "react"; - import { Cog8ToothIcon, CurrencyDollarIcon } from "@heroicons/react/24/outline"; import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork"; import { useGlobalState } from "~~/services/store/store"; @@ -34,14 +32,6 @@ export const Footer = () => {
- {nativeCurrencyPrice > 0 && ( -
-
- - {nativeCurrencyPrice} -
-
- )} {isSepoliaNetwork && ( <> @@ -66,6 +56,14 @@ export const Footer = () => { Configure Contracts + {nativeCurrencyPrice > 0 && ( +
+
+ + {nativeCurrencyPrice} +
+
+ )}
diff --git a/packages/nextjs/components/Header.tsx b/packages/nextjs/components/Header.tsx index 442ad8773..9ad7191ff 100644 --- a/packages/nextjs/components/Header.tsx +++ b/packages/nextjs/components/Header.tsx @@ -65,7 +65,7 @@ export const HeaderMenuLinks = () => { passHref className={`${ isActive - ? "!bg-gradient-nav !text-white active:bg-gradient-nav shadow-md " + ? "!bg-gradient-nav !text-white active:bg-gradient-nav shadow-md" : "" } py-1.5 px-3 text-sm rounded-full gap-2 grid grid-flow-col hover:bg-gradient-nav hover:text-white`} > @@ -85,10 +85,13 @@ export const HeaderMenuLinks = () => { export const Header = () => { const [isDrawerOpen, setIsDrawerOpen] = useState(false); const burgerMenuRef = useRef(null); + useOutsideClick( + //@ts-expect-error refs are supposed to be null by default burgerMenuRef, useCallback(() => setIsDrawerOpen(false), []), ); + const { targetNetwork } = useTargetNetwork(); const isLocalNetwork = targetNetwork.network === devnet.network; @@ -128,14 +131,16 @@ export const Header = () => { ]); return ( -
-
+
+
-
+
{status === "connected" && !isDeployed ? ( Wallet Not Deployed @@ -186,7 +191,7 @@ export const Header = () => { {/* */}
diff --git a/packages/nextjs/components/SwitchTheme.tsx b/packages/nextjs/components/SwitchTheme.tsx index 1e080ea36..31df4be8d 100644 --- a/packages/nextjs/components/SwitchTheme.tsx +++ b/packages/nextjs/components/SwitchTheme.tsx @@ -1,14 +1,11 @@ "use client"; -import { useEffect, useState } from "react"; +import { useMemo } from "react"; import { useTheme } from "next-themes"; import { MoonIcon, SunIcon } from "@heroicons/react/24/outline"; export const SwitchTheme = ({ className }: { className?: string }) => { const { setTheme, resolvedTheme } = useTheme(); - const [mounted, setMounted] = useState(false); - - const isDarkMode = resolvedTheme === "dark"; const handleToggle = () => { if (isDarkMode) { @@ -18,11 +15,9 @@ export const SwitchTheme = ({ className }: { className?: string }) => { setTheme("dark"); }; - useEffect(() => { - setMounted(true); - }, []); - - if (!mounted) return null; + const isDarkMode = useMemo(() => { + return resolvedTheme === "dark"; + }, [resolvedTheme]); return (
{ - const [ens, setEns] = useState(); const [ensAvatar, setEnsAvatar] = useState(); const [addressCopied, setAddressCopied] = useState(false); const { targetNetwork } = useTargetNetwork(); - const { data: profile } = useConditionalStarkProfile(address); + const { data: fetchedProfile, isLoading } = useScaffoldStarkProfile(address); const checkSumAddress = useMemo(() => { if (!address) return undefined; return getChecksumAddress(address); }, [address]); - // const checkSumAddress = address ? address : undefined; + const blockExplorerAddressLink = getBlockExplorerAddressLink( + targetNetwork, + checkSumAddress || address || "", + ); + + const [displayAddress, setDisplayAddress] = useState( + checkSumAddress?.slice(0, 6) + "..." + checkSumAddress?.slice(-4), + ); - // TODO add starkprofile | not working on devnet now - //const { data: fetchedProfile } = useStarkProfile({ address }); + useEffect(() => { + const addressWithFallback = checkSumAddress || address || ""; - // We need to apply this pattern to avoid Hydration errors. - // useEffect(() => { - // if (fetchedProfile) { - // setEns(fetchedProfile.name); - // setEnsAvatar(fetchedProfile.profilePicture); - // } - // }, [fetchedProfile]); + if (fetchedProfile?.name) { + setDisplayAddress(fetchedProfile.name); + } else if (format === "long") { + setDisplayAddress(addressWithFallback || ""); + } else { + setDisplayAddress( + addressWithFallback.slice(0, 6) + "..." + addressWithFallback.slice(-4), + ); + } + }, [fetchedProfile, checkSumAddress, address, format]); // Skeleton UI - if (!checkSumAddress) { + if (isLoading) { return (
@@ -83,51 +90,43 @@ export const Address = ({ ); } - if (!validateChecksumAddress(checkSumAddress)) { - return Wrong address; + if (!checkSumAddress) { + return ( +
Wallet not connected
+ ); } - const blockExplorerAddressLink = getBlockExplorerAddressLink( - targetNetwork, - checkSumAddress, - ); - let displayAddress = - checkSumAddress?.slice(0, 6) + "..." + checkSumAddress?.slice(-4); - - if (ens) { - displayAddress = ens; - } else if (format === "long") { - displayAddress = checkSumAddress; + if (!validateChecksumAddress(checkSumAddress)) { + return Wrong address; } return (
- {getStarknetPFPIfExists(profile?.profilePicture) ? ( - //eslint-disable-next-line @next/next/no-img-element - Profile Picture ) : ( )}
{disableAddressLink ? ( - {profile?.name || displayAddress} + {fetchedProfile?.name || displayAddress} ) : targetNetwork.network === devnet.network ? ( - {profile?.name || displayAddress} + {fetchedProfile?.name || displayAddress} ) : ( @@ -137,7 +136,7 @@ export const Address = ({ href={blockExplorerAddressLink} rel="noopener noreferrer" > - {profile?.name || displayAddress} + {fetchedProfile?.name || displayAddress} )} {addressCopied ? ( @@ -146,6 +145,7 @@ export const Address = ({ aria-hidden="true" /> ) : ( + //@ts-ignore { diff --git a/packages/nextjs/components/scaffold-stark/BlockExplorer.tsx b/packages/nextjs/components/scaffold-stark/BlockExplorer.tsx index 822ff3fd1..ad321ea03 100644 --- a/packages/nextjs/components/scaffold-stark/BlockExplorer.tsx +++ b/packages/nextjs/components/scaffold-stark/BlockExplorer.tsx @@ -67,7 +67,9 @@ export const BlockExplorer = () => {
@@ -75,6 +77,7 @@ export const BlockExplorer = () => { alt="Starknet Developers Hub" className="cursor-pointer" fill + sizes="1.5rem" src={blockexplorer.img} />
diff --git a/packages/nextjs/components/scaffold-stark/BlockExplorerSepolia.tsx b/packages/nextjs/components/scaffold-stark/BlockExplorerSepolia.tsx index b49a7bb6f..bc45fc4da 100644 --- a/packages/nextjs/components/scaffold-stark/BlockExplorerSepolia.tsx +++ b/packages/nextjs/components/scaffold-stark/BlockExplorerSepolia.tsx @@ -68,7 +68,9 @@ export const BlockExplorerSepolia = () => {
@@ -76,6 +78,7 @@ export const BlockExplorerSepolia = () => { alt="Starknet Developers Hub" className="cursor-pointer" fill + sizes="1.5rem" src={blockexplorer.img} />
diff --git a/packages/nextjs/components/scaffold-stark/ClassHash.tsx b/packages/nextjs/components/scaffold-stark/ClassHash.tsx index 32b3e501d..74b681737 100644 --- a/packages/nextjs/components/scaffold-stark/ClassHash.tsx +++ b/packages/nextjs/components/scaffold-stark/ClassHash.tsx @@ -65,6 +65,7 @@ export const ClassHash = ({ aria-hidden="true" /> ) : ( + // @ts-ignore { diff --git a/packages/nextjs/components/scaffold-stark/CustomConnectButton/AddressInfoDropdown.tsx b/packages/nextjs/components/scaffold-stark/CustomConnectButton/AddressInfoDropdown.tsx index ef73586e5..e630d9f4e 100644 --- a/packages/nextjs/components/scaffold-stark/CustomConnectButton/AddressInfoDropdown.tsx +++ b/packages/nextjs/components/scaffold-stark/CustomConnectButton/AddressInfoDropdown.tsx @@ -15,13 +15,12 @@ import { import { useLocalStorage } from "usehooks-ts"; import { BlockieAvatar, isENS } from "~~/components/scaffold-stark"; import { useOutsideClick } from "~~/hooks/scaffold-stark"; -import { BurnerConnector } from "~~/services/web3/stark-burner/BurnerConnector"; +import { BurnerConnector, burnerAccounts } from "@scaffold-stark/stark-burner"; import { getTargetNetworks } from "~~/utils/scaffold-stark"; -import { burnerAccounts } from "~~/utils/devnetAccounts"; import { Address } from "@starknet-react/chains"; import { useDisconnect, useNetwork, useConnect } from "@starknet-react/core"; import { getStarknetPFPIfExists } from "~~/utils/profile"; -import useConditionalStarkProfile from "~~/hooks/useConditionalStarkProfile"; +import { useScaffoldStarkProfile } from "~~/hooks/scaffold-stark/useScaffoldStarkProfile"; import { useTheme } from "next-themes"; import { default as NextImage } from "next/image"; @@ -42,7 +41,7 @@ export const AddressInfoDropdown = ({ }: AddressInfoDropdownProps) => { const { disconnect } = useDisconnect(); const [addressCopied, setAddressCopied] = useState(false); - const { data: profile } = useConditionalStarkProfile(address); + const { data: profile } = useScaffoldStarkProfile(address); const { chain } = useNetwork(); const [showBurnerAccounts, setShowBurnerAccounts] = useState(false); const [selectingNetwork, setSelectingNetwork] = useState(false); @@ -54,16 +53,16 @@ export const AddressInfoDropdown = ({ setSelectingNetwork(false); dropdownRef.current?.removeAttribute("open"); }; + + // @ts-expect-error ref are initialized with null by default useOutsideClick(dropdownRef, closeDropdown); function handleConnectBurner( e: React.MouseEvent, ix: number, ) { - const connector = connectors.find( - (it) => it.id == "burner-wallet", - ) as BurnerConnector; - if (connector) { + const connector = connectors.find((it) => it.id == "burner-wallet"); + if (connector && connector instanceof BurnerConnector) { connector.burnerAccount = burnerAccounts[ix]; connect({ connector }); setLastConnector({ id: connector.id, ix }); @@ -122,6 +121,7 @@ export const AddressInfoDropdown = ({ Copy address
) : ( + //@ts-ignore { @@ -222,14 +222,21 @@ export const AddressInfoDropdown = ({ className="w-full flex flex-col" >
))} diff --git a/packages/nextjs/components/scaffold-stark/CustomConnectButton/ConnectModal.tsx b/packages/nextjs/components/scaffold-stark/CustomConnectButton/ConnectModal.tsx index 12b2db186..8c61c53c5 100644 --- a/packages/nextjs/components/scaffold-stark/CustomConnectButton/ConnectModal.tsx +++ b/packages/nextjs/components/scaffold-stark/CustomConnectButton/ConnectModal.tsx @@ -2,12 +2,10 @@ import { Connector, useConnect } from "@starknet-react/core"; import { useRef, useState } from "react"; import Wallet from "~~/components/scaffold-stark/CustomConnectButton/Wallet"; import { useLocalStorage } from "usehooks-ts"; -import { burnerAccounts } from "~~/utils/devnetAccounts"; -import { BurnerConnector } from "~~/services/web3/stark-burner/BurnerConnector"; +import { BurnerConnector, burnerAccounts } from "@scaffold-stark/stark-burner"; import { useTheme } from "next-themes"; import { BlockieAvatar } from "../BlockieAvatar"; import GenericModal from "./GenericModal"; -import scaffoldConfig from "~~/scaffold.config"; import { LAST_CONNECTED_TIME_LOCALSTORAGE_KEY } from "~~/utils/Constants"; const loader = ({ src }: { src: string }) => { @@ -56,10 +54,8 @@ const ConnectModal = () => { e: React.MouseEvent, ix: number, ) { - const connector = connectors.find( - (it) => it.id == "burner-wallet", - ) as BurnerConnector; - if (connector) { + const connector = connectors.find((it) => it.id == "burner-wallet"); + if (connector && connector instanceof BurnerConnector) { connector.burnerAccount = burnerAccounts[ix]; connect({ connector }); setLastConnector({ id: connector.id, ix }); @@ -117,14 +113,19 @@ const ConnectModal = () => { className="w-full flex flex-col" >
))} diff --git a/packages/nextjs/components/scaffold-stark/CustomConnectButton/Wallet.tsx b/packages/nextjs/components/scaffold-stark/CustomConnectButton/Wallet.tsx index b6ab9adbb..89eba9a40 100644 --- a/packages/nextjs/components/scaffold-stark/CustomConnectButton/Wallet.tsx +++ b/packages/nextjs/components/scaffold-stark/CustomConnectButton/Wallet.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import { Connector } from "@starknet-react/core"; import Image from "next/image"; import { useTheme } from "next-themes"; @@ -16,19 +16,29 @@ const Wallet = ({ ) => void; }) => { const [clicked, setClicked] = useState(false); + const [isMounted, setIsMounted] = useState(false); const { resolvedTheme } = useTheme(); const isDarkMode = resolvedTheme === "dark"; // connector has two : dark and light icon - const icon = - typeof connector.icon === "object" + const icon = useMemo(() => { + return typeof connector.icon === "object" ? resolvedTheme === "dark" ? (connector.icon.dark as string) : (connector.icon.light as string) : (connector.icon as string); - return ( + }, [connector, resolvedTheme]); + useEffect(() => { + setIsMounted(true); + }, []); + + return isMounted ? (
{connector.name} - ); + ) : null; }; export default Wallet; diff --git a/packages/nextjs/components/scaffold-stark/CustomConnectButton/index.tsx b/packages/nextjs/components/scaffold-stark/CustomConnectButton/index.tsx index 55987c7fb..084150568 100644 --- a/packages/nextjs/components/scaffold-stark/CustomConnectButton/index.tsx +++ b/packages/nextjs/components/scaffold-stark/CustomConnectButton/index.tsx @@ -10,8 +10,9 @@ import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork"; import { getBlockExplorerAddressLink } from "~~/utils/scaffold-stark"; import { useAccount, useNetwork } from "@starknet-react/core"; import { Address } from "@starknet-react/chains"; -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import ConnectModal from "./ConnectModal"; +import scaffoldConfig from "~~/scaffold.config"; /** * Custom Connect Button (watch balance + custom design) @@ -24,9 +25,12 @@ export const CustomConnectButton = () => { const [accountChainId, setAccountChainId] = useState(0n); const { chain } = useNetwork(); - const blockExplorerAddressLink = accountAddress - ? getBlockExplorerAddressLink(targetNetwork, accountAddress) - : undefined; + const blockExplorerAddressLink = useMemo(() => { + return ( + accountAddress && + getBlockExplorerAddressLink(targetNetwork, accountAddress) + ); + }, [accountAddress, targetNetwork]); // effect to get chain id and address from account useEffect(() => { diff --git a/packages/nextjs/components/scaffold-stark/Faucet.tsx b/packages/nextjs/components/scaffold-stark/Faucet.tsx index e0eae30ce..0f5c57ccf 100644 --- a/packages/nextjs/components/scaffold-stark/Faucet.tsx +++ b/packages/nextjs/components/scaffold-stark/Faucet.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useState } from "react"; import { Address as AddressType, devnet } from "@starknet-react/chains"; import { BanknotesIcon } from "@heroicons/react/24/outline"; import { @@ -9,10 +9,8 @@ import { Balance, EtherInput, } from "~~/components/scaffold-stark"; -import { useNetwork } from "@starknet-react/core"; +import { useNetwork, useProvider } from "@starknet-react/core"; import { mintEth } from "~~/services/web3/faucet"; -import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork"; -import { RpcProvider } from "starknet"; import { notification } from "~~/utils/scaffold-stark"; import GenericModal from "./CustomConnectButton/GenericModal"; @@ -28,16 +26,7 @@ export const Faucet = () => { const [sendValue, setSendValue] = useState(""); const { chain: ConnectedChain } = useNetwork(); - const { targetNetwork } = useTargetNetwork(); - - const publicNodeUrl = targetNetwork.rpcUrls.public.http[0]; - - // Use useMemo to memoize the publicClient object - const publicClient = useMemo(() => { - return new RpcProvider({ - nodeUrl: publicNodeUrl, - }); - }, [publicNodeUrl]); + const { provider: publicClient } = useProvider(); useEffect(() => { const checkChain = async () => { diff --git a/packages/nextjs/components/scaffold-stark/FaucetSepolia.tsx b/packages/nextjs/components/scaffold-stark/FaucetSepolia.tsx index 25926aacd..87129ac55 100644 --- a/packages/nextjs/components/scaffold-stark/FaucetSepolia.tsx +++ b/packages/nextjs/components/scaffold-stark/FaucetSepolia.tsx @@ -1,11 +1,9 @@ "use client"; -import { useEffect, useMemo, useState } from "react"; -import { Address as AddressType, sepolia } from "@starknet-react/chains"; +import { useEffect } from "react"; +import { sepolia } from "@starknet-react/chains"; import { BanknotesIcon } from "@heroicons/react/24/outline"; -import { useNetwork } from "@starknet-react/core"; -import { useTargetNetwork } from "~~/hooks/scaffold-stark/useTargetNetwork"; -import { RpcProvider } from "starknet"; +import { useNetwork, useProvider } from "@starknet-react/core"; import { notification } from "~~/utils/scaffold-stark"; import Image from "next/image"; import GenericModal from "./CustomConnectButton/GenericModal"; @@ -16,7 +14,6 @@ import { useTheme } from "next-themes"; */ export const FaucetSepolia = () => { const { chain: ConnectedChain } = useNetwork(); - const { targetNetwork } = useTargetNetwork(); const sepoliaFaucets = [ { @@ -36,15 +33,7 @@ export const FaucetSepolia = () => { }, ]; - const publicNodeUrl = targetNetwork.rpcUrls.public.http[0]; - - // Use useMemo to memoize the publicClient object - const publicClient = useMemo(() => { - return new RpcProvider({ - nodeUrl: publicNodeUrl, - }); - }, [publicNodeUrl]); - + const { provider: publicClient } = useProvider(); useEffect(() => { const checkChain = async () => { try { @@ -126,7 +115,9 @@ export const FaucetSepolia = () => {
@@ -134,6 +125,7 @@ export const FaucetSepolia = () => { alt="Starknet Developers Hub" className="cursor-pointer" fill + sizes="1.5rem" src={faucet.img} />
diff --git a/packages/nextjs/hooks/scaffold-stark/useAutoConnect.ts b/packages/nextjs/hooks/scaffold-stark/useAutoConnect.ts index 50fce6f5e..a11df329d 100644 --- a/packages/nextjs/hooks/scaffold-stark/useAutoConnect.ts +++ b/packages/nextjs/hooks/scaffold-stark/useAutoConnect.ts @@ -2,8 +2,7 @@ import { useReadLocalStorage } from "usehooks-ts"; import { useEffect } from "react"; import { useConnect } from "@starknet-react/core"; import scaffoldConfig from "~~/scaffold.config"; -import type { BurnerConnector } from "~~/services/web3/stark-burner/BurnerConnector"; -import { burnerAccounts } from "~~/utils/devnetAccounts"; +import { BurnerConnector, burnerAccounts } from "@scaffold-stark/stark-burner"; import { LAST_CONNECTED_TIME_LOCALSTORAGE_KEY } from "~~/utils/Constants"; /** @@ -33,10 +32,10 @@ export const useAutoConnect = (): void => { if (connector) { if ( connector.id == "burner-wallet" && - savedConnector?.ix !== undefined + savedConnector?.ix !== undefined && + connector instanceof BurnerConnector ) { - (connector as BurnerConnector).burnerAccount = - burnerAccounts[savedConnector.ix]; + connector.burnerAccount = burnerAccounts[savedConnector.ix]; } connect({ connector }); } diff --git a/packages/nextjs/hooks/scaffold-stark/useDataTransaction.ts b/packages/nextjs/hooks/scaffold-stark/useDataTransaction.ts new file mode 100644 index 000000000..a9d829e85 --- /dev/null +++ b/packages/nextjs/hooks/scaffold-stark/useDataTransaction.ts @@ -0,0 +1,170 @@ +import { useMemo, useState, useEffect, useCallback } from "react"; +import { RpcProvider } from "starknet"; +import { useTargetNetwork } from "./useTargetNetwork"; + +interface BlockData { + transaction: number; + blockStatus: string; + blockNumber: number; + blockHash: string; + blockVersion: string; + blockTimestamp: number; + blockTransactions: string[]; + parentBlockHash: string; + totalTransactions: number; + tps: number | null; + gasprice: string; + gaspricefri: string; + timeDiff: number | null; + averageFeeUSD: string; +} + +export const useDataTransaction = (blockNumber: number) => { + const { targetNetwork } = useTargetNetwork(); + const [blockData, setBlockData] = useState(null); + const [error, setError] = useState(null); + const [isEnabled, setIsEnabled] = useState(true); + + const publicClient = useMemo(() => { + return new RpcProvider({ + nodeUrl: targetNetwork.rpcUrls.public.http[0], + }); + }, [targetNetwork.rpcUrls.public.http]); + + const getEstimatedTxTime = useCallback( + async (blockIdentifier: number): Promise => { + try { + if (blockIdentifier <= 0) { + // No previous block exists + return null; + } + + const currentBlock = await publicClient.getBlock(blockIdentifier); + const prevBlockNumber = blockIdentifier - 1; + const prevBlock = await publicClient.getBlock(prevBlockNumber); + + if (!currentBlock || !prevBlock) { + return null; + } + + return currentBlock.timestamp - prevBlock.timestamp; + } catch (error) { + console.error("Error on getting estimated time:", error); + return null; + } + }, + [publicClient], + ); + + const calculateAverageFee = useCallback( + async (blockIdentifier: number): Promise => { + try { + const blockTxHashes = + await publicClient.getBlockWithTxHashes(blockIdentifier); + const txHashes = blockTxHashes.transactions; + + if (!txHashes || txHashes.length === 0) return 0; + + let totalFeeWei = BigInt(0); + for (const txHash of txHashes) { + const receipt: any = await publicClient.getTransactionReceipt(txHash); + if (receipt?.actual_fee) { + totalFeeWei += BigInt(receipt.actual_fee.amount); + } + } + + const totalFeeEther = Number(totalFeeWei) / 1e18; + + const fetchEthPrice = async () => { + try { + const response = await fetch( + "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd", + ); + const data = await response.json(); + return data.ethereum.usd; + } catch (error) { + console.error("Error fetching ETH price:", error); + return 4000; + } + }; + + const ethPriceInUSD = await fetchEthPrice(); + + const averageFeeUSD = (totalFeeEther * ethPriceInUSD) / txHashes.length; + + return averageFeeUSD; + } catch (error) { + console.error("Error calculating average fee:", error); + return 0; + } + }, + [publicClient], + ); + + const fetchBlockData = useCallback(async () => { + try { + setError(null); + const currentBlock = await publicClient.getBlock(blockNumber); + + const prevBlockNumber = blockNumber - 1; + let tps: number | null = null; + + if (prevBlockNumber >= 0) { + const prevBlock = await publicClient.getBlock(prevBlockNumber); + if (currentBlock && prevBlock) { + const currentTxCount = currentBlock.transactions?.length || 0; + const timeDiffBetweenBlocks = + currentBlock.timestamp - prevBlock.timestamp; + + tps = + timeDiffBetweenBlocks > 0 + ? currentTxCount / timeDiffBetweenBlocks + : null; + } + } + + const timeDiff = await getEstimatedTxTime(blockNumber); + const averageFeeUSD = await calculateAverageFee(blockNumber); + + const data: BlockData = { + transaction: currentBlock.transactions?.length || 0, + blockStatus: currentBlock.status, + blockNumber: blockNumber, + blockHash: currentBlock.sequencer_address, + blockVersion: currentBlock.starknet_version, + blockTimestamp: currentBlock.timestamp, + blockTransactions: currentBlock.transactions || [], + parentBlockHash: currentBlock.parent_hash, + totalTransactions: currentBlock.transactions?.length || 0, + tps, + gasprice: currentBlock.l1_gas_price.price_in_wei, + gaspricefri: currentBlock.l1_gas_price.price_in_fri, + timeDiff: timeDiff !== null ? timeDiff : null, + averageFeeUSD: averageFeeUSD.toFixed(4), + }; + + setBlockData(data); + } catch (e: any) { + console.error("Error fetching block data:", e); + setError(e.message || "Failed to fetch block data"); + } + }, [publicClient, getEstimatedTxTime, calculateAverageFee, blockNumber]); + + useEffect(() => { + if (isEnabled) { + fetchBlockData(); + } + }, [fetchBlockData, isEnabled]); + + const toggleFetching = () => { + setIsEnabled((prev) => !prev); + }; + + return { + blockData, + error, + refetch: fetchBlockData, + isEnabled, + toggleFetching, + }; +}; diff --git a/packages/nextjs/hooks/scaffold-stark/useDeployedContractInfo.ts b/packages/nextjs/hooks/scaffold-stark/useDeployedContractInfo.ts index 57c2d90cf..e2eded7a4 100644 --- a/packages/nextjs/hooks/scaffold-stark/useDeployedContractInfo.ts +++ b/packages/nextjs/hooks/scaffold-stark/useDeployedContractInfo.ts @@ -1,4 +1,4 @@ -import { useEffect, useState, useMemo } from "react"; +import { useEffect, useState } from "react"; import { useTargetNetwork } from "./useTargetNetwork"; import { useIsMounted } from "usehooks-ts"; import { @@ -7,7 +7,8 @@ import { Contract, contracts, } from "~~/utils/scaffold-stark/contract"; -import { BlockIdentifier, RpcProvider } from "starknet"; +import { BlockIdentifier } from "starknet"; +import { useProvider } from "@starknet-react/core"; export const useDeployedContractInfo = ( contractName: TContractName, @@ -20,14 +21,7 @@ export const useDeployedContractInfo = ( const [status, setStatus] = useState( ContractCodeStatus.LOADING, ); - const publicNodeUrl = targetNetwork.rpcUrls.public.http[0]; - - // Use useMemo to memoize the publicClient object - const publicClient = useMemo(() => { - return new RpcProvider({ - nodeUrl: publicNodeUrl, - }); - }, [publicNodeUrl]); + const { provider: publicClient } = useProvider(); useEffect(() => { const checkContractDeployment = async () => { @@ -36,9 +30,9 @@ export const useDeployedContractInfo = ( return; } - let contractClasHash: string | undefined = undefined; + let contractClassHash: string | undefined = undefined; try { - contractClasHash = await publicClient.getClassHashAt( + contractClassHash = await publicClient.getClassHashAt( deployedContract.address, "pending" as BlockIdentifier, ); @@ -53,7 +47,7 @@ export const useDeployedContractInfo = ( return; } // If contract code is `0x` => no contract deployed on that address - if (contractClasHash == undefined) { + if (contractClassHash == undefined) { setStatus(ContractCodeStatus.NOT_FOUND); return; } @@ -66,5 +60,7 @@ export const useDeployedContractInfo = ( return { data: status === ContractCodeStatus.DEPLOYED ? deployedContract : undefined, isLoading: status === ContractCodeStatus.LOADING, + raw: deployedContract, + status, }; }; diff --git a/packages/nextjs/hooks/scaffold-stark/useScaffoldContract.ts b/packages/nextjs/hooks/scaffold-stark/useScaffoldContract.ts index 8ba5640b7..d276df0c2 100644 --- a/packages/nextjs/hooks/scaffold-stark/useScaffoldContract.ts +++ b/packages/nextjs/hooks/scaffold-stark/useScaffoldContract.ts @@ -1,9 +1,9 @@ -import { useMemo } from "react"; +"use client"; import { useDeployedContractInfo } from "~~/hooks/scaffold-stark"; import { ContractName } from "~~/utils/scaffold-stark/contract"; -import { useTargetNetwork } from "./useTargetNetwork"; -import { Contract, RpcProvider } from "starknet"; -import { useAccount } from "~~/hooks/useAccount"; +import { Contract, Abi } from "starknet"; +import { useProvider, useAccount } from "@starknet-react/core"; +import { useMemo } from "react"; export const useScaffoldContract = ({ contractName, @@ -13,23 +13,33 @@ export const useScaffoldContract = ({ const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo(contractName); - const { targetNetwork } = useTargetNetwork(); + const { provider: publicClient } = useProvider(); const { account } = useAccount(); - const publicNodeUrl = targetNetwork.rpcUrls.public.http[0]; - - const publicClient = useMemo(() => { - return new RpcProvider({ - nodeUrl: publicNodeUrl, - }); - }, [publicNodeUrl]); - let contract = undefined; - if (deployedContractData) { - contract = new Contract( - [...deployedContractData.abi], + + const contract = useMemo(() => { + if (!deployedContractData) return undefined; + + const contractInstance = new Contract( + deployedContractData.abi as Abi, deployedContractData.address, publicClient, ); - } + + if (account) { + contractInstance.connect(account); + } + + const originalCall = contractInstance.call.bind(contractInstance); + contractInstance.call = async (method: string, ...args: any[]) => { + try { + return await originalCall(method, ...args, { parseResponse: false }); + } catch (error) { + return originalCall(method, ...args); + } + }; + + return contractInstance; + }, [deployedContractData, publicClient, account]); return { data: contract, diff --git a/packages/nextjs/hooks/scaffold-stark/useScaffoldMultiWriteContract.ts b/packages/nextjs/hooks/scaffold-stark/useScaffoldMultiWriteContract.ts index 8d6cd3aeb..9d804cb2b 100644 --- a/packages/nextjs/hooks/scaffold-stark/useScaffoldMultiWriteContract.ts +++ b/packages/nextjs/hooks/scaffold-stark/useScaffoldMultiWriteContract.ts @@ -9,10 +9,18 @@ import { UseScaffoldWriteConfig, } from "~~/utils/scaffold-stark/contract"; import { useSendTransaction, useNetwork, Abi } from "@starknet-react/core"; -import { Contract as StarknetJsContract, InvocationsDetails } from "starknet"; +import { + Contract as StarknetJsContract, + InvocationsDetails, + Call, +} from "starknet"; import { notification } from "~~/utils/scaffold-stark"; import { useTransactor } from "./useTransactor"; +function isRawCall(value: Call | any): value is Call { + return "entrypoint" in value; +} + export const useScaffoldMultiWriteContract = < TAbi extends Abi, TContractName extends ContractName, @@ -24,7 +32,9 @@ export const useScaffoldMultiWriteContract = < calls, options, }: { - calls: Array>; + calls: Array< + UseScaffoldWriteConfig | Call + >; options?: InvocationsDetails; }) => { const { targetNetwork } = useTargetNetwork(); @@ -52,6 +62,9 @@ export const useScaffoldMultiWriteContract = < const parsedCalls = (() => { if (calls) { return calls.map((call) => { + if (isRawCall(call)) { + return call; + } const functionName = call.functionName; const contractName = call.contractName; const unParsedArgs = call.args as any[]; diff --git a/packages/nextjs/hooks/scaffold-stark/useScaffoldStarkProfile.tsx b/packages/nextjs/hooks/scaffold-stark/useScaffoldStarkProfile.tsx new file mode 100644 index 000000000..77e4c0e71 --- /dev/null +++ b/packages/nextjs/hooks/scaffold-stark/useScaffoldStarkProfile.tsx @@ -0,0 +1,99 @@ +import * as chains from "@starknet-react/chains"; +import scaffoldConfig from "~~/scaffold.config"; +import { useEffect, useState } from "react"; +import { StarkProfile } from "starknet"; + +type network = "mainnet" | "sepolia" | "devnet"; + +const shouldUseProfile = () => { + const set = new Set(["mainnet", "sepolia"]); + return ( + set.has(scaffoldConfig.targetNetworks[0].network) && + (scaffoldConfig.targetNetworks[0].network as network) !== + chains.devnet.network + ); +}; + +const starknetIdApiBaseUrl = + (scaffoldConfig.targetNetworks[0].network as network) === + chains.mainnet.network + ? "https://api.starknet.id" + : "https://sepolia.api.starknet.id"; + +export const fetchProfileFromApi = async (address: string) => { + try { + const addrToDomainRes = await fetch( + `${starknetIdApiBaseUrl}/addr_to_domain?addr=${address}`, + ); + + if (!addrToDomainRes.ok) { + throw new Error(await addrToDomainRes.text()); + } + + const addrToDomainJson = await addrToDomainRes.json(); + + const domain = addrToDomainJson.domain; + + const profileRes = await fetch( + `${starknetIdApiBaseUrl}/domain_to_data?domain=${domain}`, + ); + + if (!profileRes.ok) throw new Error(await profileRes.text()); + + const profileData = await profileRes.json(); + + const id = BigInt(profileData.id).toString(); + + const uriRes = await fetch(`${starknetIdApiBaseUrl}/uri?id=${id}`); + + const uriData = await uriRes.json(); + + return { + name: profileData.domain.domain, + profilePicture: uriData.image, + // TODO: figure out where these go in case we have PFP, because its a bit complex to parse the data + // discord?: string; + // twitter?: string; + // github?: string; + // proofOfPersonhood?: boolean; + }; + } catch (e) { + console.error(e); + return { + name: "", + profilePicture: "", + }; + } +}; + +// this hook is a workaround, basically a re-implement of the starknet react hook with conditional rendering. +export const useScaffoldStarkProfile = ( + address: chains.Address | undefined, +) => { + const [isLoading, setIsLoading] = useState(false); + const [profile, setProfile] = useState(); + const isEnabled = shouldUseProfile(); + + useEffect(() => { + if (!isEnabled || !address) { + setProfile({ name: "", profilePicture: "" }); + return; + } + + setIsLoading(true); + + fetchProfileFromApi(address) + .then((data) => { + setProfile(data); + }) + .catch((e) => { + console.error(`[useScaffoldStarkProfile] ` + e.message); + setProfile(undefined); + }) + .finally(() => { + setIsLoading(false); + }); + }, [address, isEnabled]); + + return { data: profile, isLoading }; +}; diff --git a/packages/nextjs/hooks/useConditionalStarkProfile.tsx b/packages/nextjs/hooks/useConditionalStarkProfile.tsx deleted file mode 100644 index e13b39333..000000000 --- a/packages/nextjs/hooks/useConditionalStarkProfile.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { useStarkProfile } from "@starknet-react/core"; -import * as chains from "@starknet-react/chains"; -import scaffoldConfig from "~~/scaffold.config"; - -const useConditionalStarkProfile = (address: chains.Address | undefined) => { - const shouldUseProfile = - scaffoldConfig.targetNetworks[0].id !== chains.devnet.id; - // Conditional hooks are not recommended, but in this case, it's the best approach to avoid issues on devnet. - const profile = shouldUseProfile - ? // eslint-disable-next-line react-hooks/rules-of-hooks - useStarkProfile({ address }) - : { data: undefined }; - return profile; -}; - -export default useConditionalStarkProfile; diff --git a/packages/nextjs/next.config.mjs b/packages/nextjs/next.config.mjs index 6c1dd362a..80becc3a8 100644 --- a/packages/nextjs/next.config.mjs +++ b/packages/nextjs/next.config.mjs @@ -1,6 +1,25 @@ /** @type {import('next').NextConfig} */ +import webpack from "webpack"; + const nextConfig = { reactStrictMode: true, + images: { + // make sure no one injects anything funny in svg + dangerouslyAllowSVG: true, + remotePatterns: [ + // we might need to add more links. this is just from the starknet ID identicon + { + protocol: "https", + hostname: "identicon.starknet.id", + pathname: "/**", // Allows all paths under this domain + }, + { + protocol: "https", + hostname: "img.starkurabu.com", + pathname: "/**", + }, + ], + }, typescript: { ignoreBuildErrors: process.env.NEXT_PUBLIC_IGNORE_BUILD_ERROR === "true", }, @@ -10,6 +29,11 @@ const nextConfig = { webpack: (config) => { config.resolve.fallback = { fs: false, net: false, tls: false }; config.externals.push("pino-pretty", "lokijs", "encoding"); + config.plugins.push( + new webpack.NormalModuleReplacementPlugin(/^node:(.*)$/, (resource) => { + resource.request = resource.request.replace(/^node:/, ""); + }), + ); return config; }, }; diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 4281d063d..14e61af98 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -19,6 +19,7 @@ "@heroicons/react": "^2.1.3", "@radix-ui/react-icons": "1.3.0", "@radix-ui/themes": "2.0.3", + "@scaffold-stark/stark-burner": "0.1.8", "@starknet-io/types-js": "^0.7.7", "@starknet-react/chains": "^3.1.0", "@starknet-react/core": "^3.6.0", @@ -31,6 +32,8 @@ "next": "14.1.3", "next-themes": "^0.2.1", "nprogress": "^0.2.0", + "prettier": "^3.4.2", + "prettier-standalone": "^1.3.1-0", "qrcode.react": "^3.1.0", "react": "^18", "react-copy-to-clipboard": "^5.1.0", @@ -46,9 +49,9 @@ "@testing-library/react": "^16.0.1", "@types/node": "^20", "@types/nprogress": "^0", - "@types/react": "^18", + "@types/react": "latest", "@types/react-copy-to-clipboard": "^5.0.4", - "@types/react-dom": "^18", + "@types/react-dom": "latest", "@vitejs/plugin-react": "^4.3.1", "@vitest/coverage-istanbul": "^2.1.1", "@vitest/coverage-v8": "^2.1.1", @@ -60,6 +63,8 @@ "tailwindcss": "^3.3.0", "typescript": "^5", "vercel": "^33.7.1", - "vitest": "^2.1.1" + "vitest": "^2.1.1", + "webpack": "^5.97.1", + "webpack-cli": "^6.0.1" } } diff --git a/packages/nextjs/scaffold.config.ts b/packages/nextjs/scaffold.config.ts index 84b2b526e..4b80eee2c 100644 --- a/packages/nextjs/scaffold.config.ts +++ b/packages/nextjs/scaffold.config.ts @@ -1,7 +1,8 @@ -import * as chains from "@starknet-react/chains"; +import { Chain } from "@starknet-react/chains"; +import { supportedChains as chains } from "./supportedChains"; export type ScaffoldConfig = { - targetNetworks: readonly chains.Chain[]; + targetNetworks: readonly Chain[]; pollingInterval: number; onlyLocalBurnerWallet: boolean; rpcProviderUrl: string; diff --git a/packages/nextjs/services/web3/PriceService.ts b/packages/nextjs/services/web3/PriceService.ts index a60e9e4b8..6fc3ff74d 100644 --- a/packages/nextjs/services/web3/PriceService.ts +++ b/packages/nextjs/services/web3/PriceService.ts @@ -12,7 +12,9 @@ export const fetchPriceFromCoingecko = async ( return symbol === "ETH" ? data.ethereum.usd : data.starknet.usd; } catch (error) { console.error( - `Attempt ${attempt + 1} - Error fetching ${symbol} price from Coingecko: `, + `Attempt ${ + attempt + 1 + } - Error fetching ${symbol} price from Coingecko: `, error, ); attempt++; diff --git a/packages/nextjs/services/web3/connectors.tsx b/packages/nextjs/services/web3/connectors.tsx index dff24b647..7f5efab47 100644 --- a/packages/nextjs/services/web3/connectors.tsx +++ b/packages/nextjs/services/web3/connectors.tsx @@ -1,6 +1,6 @@ import { argent, braavos, InjectedConnector } from "@starknet-react/core"; import { getTargetNetworks } from "~~/utils/scaffold-stark"; -import { BurnerConnector } from "./stark-burner/BurnerConnector"; +import { BurnerConnector } from "@scaffold-stark/stark-burner"; import scaffoldConfig from "~~/scaffold.config"; import { LAST_CONNECTED_TIME_LOCALSTORAGE_KEY } from "~~/utils/Constants"; @@ -23,12 +23,13 @@ function withDisconnectWrapper(connector: InjectedConnector) { function getConnectors() { const { targetNetworks } = scaffoldConfig; - const connectors = [argent(), braavos()]; + const connectors: InjectedConnector[] = [argent(), braavos()]; if ( targetNetworks.some((network) => (network.network as string) === "devnet") ) { - connectors.push(new BurnerConnector()); + const burnerConnector = new BurnerConnector(); + connectors.push(burnerConnector as unknown as InjectedConnector); } return connectors.sort(() => Math.random() - 0.5).map(withDisconnectWrapper); diff --git a/packages/nextjs/services/web3/stark-burner/BurnerConnector.ts b/packages/nextjs/services/web3/stark-burner/BurnerConnector.ts deleted file mode 100644 index acad0a589..000000000 --- a/packages/nextjs/services/web3/stark-burner/BurnerConnector.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { - InjectedConnector, - UserRejectedRequestError, - starknetChainId, -} from "@starknet-react/core"; -import { - Account, - AccountInterface, - Call, - CallData, - RpcProvider, - byteArray, - uint256, -} from "starknet"; -import { - ConnectorData, - ConnectorIcons, -} from "@starknet-react/core/src/connectors/base"; -import { Chain, devnet } from "@starknet-react/chains"; -import scaffoldConfig from "~~/scaffold.config"; -import { BurnerAccount, burnerAccounts } from "~~/utils/devnetAccounts"; -import { - RequestFnCall, - RpcMessage, - RpcTypeToMessageMap, -} from "@starknet-io/types-js"; - -export const burnerWalletId = "burner-wallet"; -export const burnerWalletName = "Burner Wallet"; -const burnerWalletIcon = - "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzUzIiBoZWlnaHQ9IjM1MiIgdmlld0JveD0iMCAwIDM1MyAzNTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHg9IjAuNzE2MzA5IiB5PSIwLjMxNzEzOSIgd2lkdGg9IjM1MS4zOTQiIGhlaWdodD0iMzUxLjM5NCIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzNfMTUxKSIvPgo8Y2lyY2xlIGN4PSIzNC40OTUzIiBjeT0iMzQuNDk1MyIgcj0iMzQuNDk1MyIgdHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMjA3LjAxOCAyNTQuMTIpIiBmaWxsPSIjRkY2NjBBIi8+CjxwYXRoIGQ9Ik0xNTQuMzE4IDMxNy45NTVDMTcxLjI3MyAzMTAuODkgMTc2LjU4MiAyOTAuNzE1IDE3Ni4xNTcgMjgzLjQ4N0wyMDcuMDE4IDI4OC44NjRDMjA3LjAxOCAzMDMuMzE0IDIwMC4yMTIgMzA5LjQwMiAxOTcuODI0IDMxMi40MzNDMTkzLjQ3NCAzMTcuOTU1IDE3My4zNTEgMzMwLjAzIDE1NC4zMTggMzE3Ljk1NVoiIGZpbGw9InVybCgjcGFpbnQxX3JhZGlhbF8zXzE1MSkiLz4KPGcgZmlsdGVyPSJ1cmwoI2ZpbHRlcjBfZF8zXzE1MSkiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIyNy4zNzcgMzAyLjI3NkMyMjYuNDI2IDMwNS44OTcgMjMwLjMxNSAzMDkuNDA1IDIzMy4zOTYgMzA3LjI3OUMyNTQuNTM4IDI5Mi42ODQgMjcwLjQ3OSAyNjkuOTQ1IDI3NC44OSAyNDcuNDg5QzI4Mi4yNCAyMTAuMDcxIDI3Mi4yMzUgMTc1LjcyNyAyMzguMDI4IDE0NS45MjVDMjAwLjg3NCAxMTMuNTU2IDE5MS44NDQgODguNDU2MSAxOTAuMTYyIDUwLjg3MThDMTg5Ljc5NyA0Mi43MjE4IDE4MS42MDQgMzcuMjk0NyAxNzQuODI0IDQxLjgzMTdDMTUyLjY2OCA1Ni42NTc0IDEzMi41MTIgODQuNDk5IDEzOC45MTEgMTIwLjc1OEMxNDEuMDA0IDEzMi42MjEgMTQ2Ljc5NCAxNDEuMDE2IDE1MS45NyAxNDguNTIzQzE1OC40OTEgMTU3Ljk3OCAxNjQuMDM5IDE2Ni4wMjMgMTU5Ljk5NyAxNzcuODFDMTU1LjIwMyAxOTEuNzk0IDEzOS4xMzQgMTk5LjE2MiAxMjguNzQ3IDE5Mi40MjlDMTE0LjE3IDE4Mi45ODEgMTEzLjI1MyAxNjYuNjUxIDExNy45NjkgMTQ5LjQ1NkMxMTguOTAyIDE0Ni4wNTUgMTE1LjQ3MSAxNDMuMjA0IDExMi42OCAxNDUuMzU5QzkxLjM2MDQgMTYxLjgyMSA2OS4xNTMyIDE5OS4yNjcgNzcuNjY0NyAyNDcuNDg5Qzg1Ljk3OTIgMjc2LjIxMiA5Ny45Mjc3IDI5Mi41MzcgMTEwLjk3MSAzMDEuNTQxQzExMy43NjMgMzAzLjQ2OCAxMTcuMTU5IDMwMC42MzEgMTE2LjU5NyAyOTcuMjg2QzExNi4wODEgMjk0LjIxMiAxMTUuODEzIDI5MS4wNTQgMTE1LjgxMyAyODcuODMzQzExNS44MTMgMjU2LjUxMyAxNDEuMjAzIDIzMS4xMjMgMTcyLjUyMyAyMzEuMTIzQzIwMy44NDIgMjMxLjEyMyAyMjkuMjMyIDI1Ni41MTMgMjI5LjIzMiAyODcuODMzQzIyOS4yMzIgMjkyLjgyNCAyMjguNTg3IDI5Ny42NjUgMjI3LjM3NyAzMDIuMjc2WiIgZmlsbD0idXJsKCNwYWludDJfbGluZWFyXzNfMTUxKSIvPgo8L2c+CjxkZWZzPgo8ZmlsdGVyIGlkPSJmaWx0ZXIwX2RfM18xNTEiIHg9IjcyLjExMTIiIHk9IjM2LjQ5NCIgd2lkdGg9IjIwOC43NDIiIGhlaWdodD0iMjc1LjEyIiBmaWx0ZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIGNvbG9yLWludGVycG9sYXRpb24tZmlsdGVycz0ic1JHQiI+CjxmZUZsb29kIGZsb29kLW9wYWNpdHk9IjAiIHJlc3VsdD0iQmFja2dyb3VuZEltYWdlRml4Ii8+CjxmZUNvbG9yTWF0cml4IGluPSJTb3VyY2VBbHBoYSIgdHlwZT0ibWF0cml4IiB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDEyNyAwIiByZXN1bHQ9ImhhcmRBbHBoYSIvPgo8ZmVPZmZzZXQvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIxLjg0NTA2Ii8+CjxmZUNvbXBvc2l0ZSBpbjI9ImhhcmRBbHBoYSIgb3BlcmF0b3I9Im91dCIvPgo8ZmVDb2xvck1hdHJpeCB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAxIDAgMCAwIDAgMC40MiAwIDAgMCAwIDAgMCAwIDAgMC43IDAiLz4KPGZlQmxlbmQgbW9kZT0ibXVsdGlwbHkiIGluMj0iQmFja2dyb3VuZEltYWdlRml4IiByZXN1bHQ9ImVmZmVjdDFfZHJvcFNoYWRvd18zXzE1MSIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDFfZHJvcFNoYWRvd18zXzE1MSIgcmVzdWx0PSJzaGFwZSIvPgo8L2ZpbHRlcj4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzNfMTUxIiB4MT0iMTc2LjQxMyIgeTE9IjAuMzE3MTM5IiB4Mj0iMTc2LjQxMyIgeTI9IjM1MS43MTEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRjI3OSIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkQzMzYiLz4KPC9saW5lYXJHcmFkaWVudD4KPHJhZGlhbEdyYWRpZW50IGlkPSJwYWludDFfcmFkaWFsXzNfMTUxIiBjeD0iMCIgY3k9IjAiIHI9IjEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDIxOC4wNDggMjQ5LjM0Nykgcm90YXRlKDEyNC4wMTgpIHNjYWxlKDg5LjI5NTUgMjY0LjgwOSkiPgo8c3RvcCBvZmZzZXQ9IjAuNjQwODUiIHN0b3AtY29sb3I9IiNGRjY2MEEiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjRkZCRTE1Ii8+CjwvcmFkaWFsR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQyX2xpbmVhcl8zXzE1MSIgeDE9IjE3Ni40ODIiIHkxPSI0MC4xODQxIiB4Mj0iMTc2LjQ4MiIgeTI9IjMxNy4yNzgiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agb2Zmc2V0PSIwLjMzODU0MiIgc3RvcC1jb2xvcj0iI0ZGOEYzRiIvPgo8c3RvcCBvZmZzZXQ9IjAuNjU2MjUiIHN0b3AtY29sb3I9IiNGRjcwMjAiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjRkYzRDAwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg=="; - -// https://github.com/apibara/starknet-react/blob/main/packages/core/src/connectors/injected.ts -export class BurnerConnector extends InjectedConnector { - chain: Chain = devnet; - burnerAccount: BurnerAccount = burnerAccounts[0]; - - constructor() { - super({ - options: { - id: burnerWalletId, - name: burnerWalletName, - icon: { dark: burnerWalletIcon, light: burnerWalletIcon }, - }, - }); - this.chain = scaffoldConfig.targetNetworks[0]; - } - - get id(): string { - return super.id; - } - - get name(): string { - return super.name; - } - - async account(): Promise { - return Promise.resolve( - new Account( - new RpcProvider({ - nodeUrl: this.chain.rpcUrls.public.http[0], - chainId: starknetChainId(this.chain.id), - }), - this.burnerAccount.accountAddress, - this.burnerAccount.privateKey, - "1", - ), - ); - } - - available(): boolean { - return true; - } - - chainId(): Promise { - return Promise.resolve(this.chain.id); - } - - get icon(): ConnectorIcons { - return { - dark: burnerWalletIcon, - light: burnerWalletIcon, - }; - } - - async ready(): Promise { - return Promise.resolve((await this.account()).address !== ""); - } - - async request( - call: RequestFnCall, - ): Promise { - if (call.params && "calls" in call.params) { - let compiledCalls = call.params.calls; - try { - // TODO : starknet connector uses "emtrypoint" instead of "entry_point" - // TODO : starknet connector uses "contract_address" instead of "contractAddress" - compiledCalls.forEach((element) => { - //@ts-ignore - element.calldata = CallData.compile(element.calldata); - //@ts-ignore - element.contractAddress = element.contract_address; - //@ts-ignore - element.entrypoint = element.entry_point; - // element.calldata.__compiled__ = true; - }); - - return await ( - await this.account() - ) - //@ts-ignore - .execute(compiledCalls, { - version: "0x3", - }); - } catch (e) { - throw e; - } - } - - return await super.request(call); - } - - async connect(): Promise { - return Promise.resolve({ - account: (await this.account()).address, - chainId: this.chain.id, - }); - } - - disconnect(): Promise { - return Promise.resolve(); - } -} diff --git a/packages/nextjs/services/web3/stark-burner/BurnerConnectorErrors.ts b/packages/nextjs/services/web3/stark-burner/BurnerConnectorErrors.ts deleted file mode 100644 index cdb3f10c3..000000000 --- a/packages/nextjs/services/web3/stark-burner/BurnerConnectorErrors.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Error list used by {@link BurnerConnectorError} - */ -export const BurnerConnectorErrorList = { - accountNotFound: "Account not found", - couldNotConnect: "Could not connect to network", - unsupportedBurnerChain: "This network is not supported for burner connector", - chainIdNotResolved: "Could not resolve chainId", - chainNotSupported: "Chain is not supported, check burner wallet config", -} as const; - -/** - * A union of all the BurnerConnectorErrorList - */ -export type BurnerConnectorErrorTypes = - (typeof BurnerConnectorErrorList)[keyof typeof BurnerConnectorErrorList]; - -export class BurnerConnectorError extends Error { - constructor(errorType: BurnerConnectorErrorTypes, message?: string) { - const msg = `BurnerConnectorError ${errorType}: ${message ?? ""} `; - super(msg); - console.warn(msg); - } -} diff --git a/packages/nextjs/styles/globals.css b/packages/nextjs/styles/globals.css index 950500f23..f94604bee 100644 --- a/packages/nextjs/styles/globals.css +++ b/packages/nextjs/styles/globals.css @@ -27,9 +27,28 @@ p { @apply shadow-md; } +html { + @apply overflow-y-scroll overflow-x-hidden; +} + +body { + @apply overflow-y-auto overflow-x-hidden; +} + +.modal { + @apply overflow-hidden; +} + .modal-box { - @apply min-h-[20rem] max-w-[25rem]; + @apply min-h-[20rem] max-w-[25rem] overflow-hidden; + transform: translateZ(0); } + +.modal-backdrop, +.modal.backdrop-blur { + @apply fixed inset-0 overflow-hidden; +} + .btn.btn-ghost { @apply shadow-none; } diff --git a/packages/nextjs/supportedChains.ts b/packages/nextjs/supportedChains.ts new file mode 100644 index 000000000..d6fe773b6 --- /dev/null +++ b/packages/nextjs/supportedChains.ts @@ -0,0 +1,26 @@ +import * as chains from "@starknet-react/chains"; + +// devnet with mainnet network ID +const mainnetFork = { + id: BigInt("0x534e5f4d41494e"), + network: "devnet", + name: "Starknet Devnet", + nativeCurrency: { + address: + "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + testnet: true, + rpcUrls: { + default: { + http: [], + }, + public: { + http: ["http://localhost:5050/rpc"], + }, + }, +} as chains.Chain; + +export const supportedChains = { ...chains, mainnetFork }; diff --git a/packages/nextjs/utils/devnetAccounts.ts b/packages/nextjs/utils/devnetAccounts.ts deleted file mode 100644 index cf1dc18ee..000000000 --- a/packages/nextjs/utils/devnetAccounts.ts +++ /dev/null @@ -1,78 +0,0 @@ -export type BurnerAccount = { - accountAddress: string; - privateKey: string; - publicKey: string; -}; - -export const burnerAccounts: BurnerAccount[] = [ - { - accountAddress: - "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691", - privateKey: "0x71d7bb07b9a64f6f78ac4c816aff4da9", - publicKey: - "0x39d9e6ce352ad4530a0ef5d5a18fd3303c3606a7fa6ac5b620020ad681cc33b", - }, - { - accountAddress: - "0x78662e7352d062084b0010068b99288486c2d8b914f6e2a55ce945f8792c8b1", - privateKey: "0xe1406455b7d66b1690803be066cbe5e", - publicKey: - "0x7a1bb2744a7dd29bffd44341dbd78008adb4bc11733601e7eddff322ada9cb", - }, - { - accountAddress: - "0x49dfb8ce986e21d354ac93ea65e6a11f639c1934ea253e5ff14ca62eca0f38e", - privateKey: "0xa20a02f0ac53692d144b20cb371a60d7", - publicKey: - "0xb8fd4ddd415902d96f61b7ad201022d495997c2dff8eb9e0eb86253e30fabc", - }, - { - accountAddress: - "0x4f348398f859a55a0c80b1446c5fdc37edb3a8478a32f10764659fc241027d3", - privateKey: "0xa641611c17d4d92bd0790074e34beeb7", - publicKey: - "0x5e05d2510c6110bde03df9c1c126a1f592207d78cd9e481ac98540d5336d23c", - }, - { - accountAddress: - "0xd513de92c16aa42418cf7e5b60f8022dbee1b4dfd81bcf03ebee079cfb5cb5", - privateKey: "0x5b4ac23628a5749277bcabbf4726b025", - publicKey: - "0x4708e28e2424381659ea6b7dded2b3aff4b99debfcf6080160a9d098ac2214d", - }, - { - accountAddress: - "0x1e8c6c17efa3a047506c0b1610bd188aa3e3dd6c5d9227549b65428de24de78", - privateKey: "0x836203aceb0e9b0066138c321dda5ae6", - publicKey: - "0x776d33371a98abee91ce60ac04321361565c8623cb612ee9357092da2162f51", - }, - { - accountAddress: - "0x557ba9ef60b52dad611d79b60563901458f2476a5c1002a8b4869fcb6654c7e", - privateKey: "0x15b5e3013d752c909988204714f1ff35", - publicKey: - "0x4236bd1a08ee4bc3288081dfaf2b71d9a6e6e573d1b31a62719db73a88bb55", - }, - { - accountAddress: - "0x3736286f1050d4ba816b4d56d15d80ca74c1752c4e847243f1da726c36e06f", - privateKey: "0xa56597ba3378fa9e6440ea9ae0cf2865", - publicKey: - "0x20b6aad24b5741eb49ed1b00ea78e3657e4d74af47e329f6f9fe489517474db", - }, - { - accountAddress: - "0x4d8bb41636b42d3c69039f3537333581cc19356a0c93904fa3e569498c23ad0", - privateKey: "0xb467066159b295a7667b633d6bdaabac", - publicKey: - "0xc6c2f7833f681c8fe001533e99571f6ff8dec59268792a429a14b5b252f1ad", - }, - { - accountAddress: - "0x4b3f4ba8c00a02b66142a4b1dd41a4dfab4f92650922a3280977b0f03c75ee1", - privateKey: "0x57b2f8431c772e647712ae93cc616638", - publicKey: - "0x374f7fcb50bc2d6b8b7a267f919232e3ac68354ce3eafe88d3df323fc1deb23", - }, -]; diff --git a/packages/nextjs/utils/scaffold-stark/contract.ts b/packages/nextjs/utils/scaffold-stark/contract.ts index 49049d69d..4f4a6e8ae 100644 --- a/packages/nextjs/utils/scaffold-stark/contract.ts +++ b/packages/nextjs/utils/scaffold-stark/contract.ts @@ -88,15 +88,22 @@ export const deepMergeContracts = < new Set([...Object.keys(local), ...Object.keys(external)]), ); for (const key of allKeys) { - if (!external[key]) { - result[key] = local[key]; - continue; + const localValue = local[key]; + const externalValue = external[key]; + if ( + typeof localValue === "object" && + typeof externalValue === "object" && + localValue !== null && + externalValue !== null + ) { + // Recursively merge nested objects + result[key] = deepMergeContracts(localValue, externalValue); + } else { + // Use external value if available, otherwise fallback to local + result[key] = externalValue !== undefined ? externalValue : localValue; } - const amendedExternal = Object.fromEntries( - Object.entries(external[key] as Record>), - ); - result[key] = { ...local[key], ...amendedExternal }; } + return result as MergeDeepRecord< AddExternalFlag, AddExternalFlag, @@ -447,7 +454,11 @@ const decodeParamsWithType = (paramType: string, param: any): unknown => { const option = x as CairoOption; return option.isNone() ? "None" - : `Some(${parseParamWithType(paramType.split("<").pop()!, option.unwrap(), isRead)})`; + : `Some(${parseParamWithType( + paramType.split("<").pop()!, + option.unwrap(), + isRead, + )})`; }, param); } else if (isCairoResult(paramType)) { return tryParsingParamReturnObject((x) => { @@ -472,10 +483,7 @@ const decodeParamsWithType = (paramType: string, param: any): unknown => { ? "false" : "true"; } else if (isCairoBytes31(paramType)) { - return tryParsingParamReturnObject( - (x: bigint) => `0x${x.toString(16)}`, - param, - ); + return tryParsingParamReturnObject((x: bigint) => feltToHex(x), param); } else if (isCairoInt(paramType)) { return tryParsingParamReturnObject( (x) => (typeof x === "bigint" ? Number(x) : parseInt(x, 16)), diff --git a/packages/nextjs/utils/scaffold-stark/networks.ts b/packages/nextjs/utils/scaffold-stark/networks.ts index 5316f79b2..d69bb4dc1 100644 --- a/packages/nextjs/utils/scaffold-stark/networks.ts +++ b/packages/nextjs/utils/scaffold-stark/networks.ts @@ -32,8 +32,10 @@ export function getBlockExplorerTxLink(network: string, txnHash: string) { const chainNames = Object.keys(chains); const targetChainArr = chainNames.filter((chainName) => { - const wagmiChain = chains[chainName as keyof typeof chains]; - return wagmiChain.network === network; + const starknetReactChain = chains[ + chainName as keyof typeof chains + ] as Chain; + return starknetReactChain.network === network; }); if (targetChainArr.length === 0) { @@ -53,7 +55,7 @@ export function getBlockExplorerTxLink(network: string, txnHash: string) { /** * Gives the block explorer URL for a given address. - * Defaults to Etherscan if no (wagmi) block explorer is configured for the network. + * Defaults to Starkscan if no block explorer is configured for the network. */ export function getBlockExplorerAddressLink(network: Chain, address: string) { const blockExplorerBaseURL = network.explorers?.starkscan[0]; @@ -70,7 +72,7 @@ export function getBlockExplorerAddressLink(network: Chain, address: string) { /** * Gives the block explorer URL for a given classhash. - * Defaults to Etherscan if no (wagmi) block explorer is configured for the network. + * Defaults to Starkscan if no block explorer is configured for the network. */ export function getBlockExplorerClasshashLink(network: Chain, address: string) { const blockExplorerBaseURL = network.explorers?.starkscan[0]; diff --git a/packages/nextjs/utils/scaffold-stark/notification.tsx b/packages/nextjs/utils/scaffold-stark/notification.tsx index 96830267e..6df794499 100644 --- a/packages/nextjs/utils/scaffold-stark/notification.tsx +++ b/packages/nextjs/utils/scaffold-stark/notification.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { ToastPosition, toast } from "react-hot-toast"; +import { type Toast, ToastPosition, toast } from "react-hot-toast"; import { XMarkIcon } from "@heroicons/react/20/solid"; import { CheckCircleIcon, @@ -44,7 +44,7 @@ const Notification = ({ position = DEFAULT_POSITION, }: NotificationProps) => { return toast.custom( - (t) => ( + (t: Toast) => (
{ // ToDo Checkpoint 2: Implement your function buy_tokens here. fn buy_tokens( - ref self: ContractState, eth_amount_wei: u256 + ref self: ContractState, eth_amount_wei: u256, ) { // Note: In UI and Debug contract `buyer` should call `approve`` before to `transfer` the amount to the `Vendor` contract. } diff --git a/packages/snfoundry/contracts/src/YourToken.cairo b/packages/snfoundry/contracts/src/YourToken.cairo index 7c3cc4078..3f7270969 100644 --- a/packages/snfoundry/contracts/src/YourToken.cairo +++ b/packages/snfoundry/contracts/src/YourToken.cairo @@ -7,7 +7,7 @@ pub trait IYourToken { fn transfer(ref self: T, recipient: ContractAddress, amount: u256) -> bool; fn approve(ref self: T, spender: ContractAddress, amount: u256) -> bool; fn transfer_from( - ref self: T, sender: ContractAddress, recipient: ContractAddress, amount: u256 + ref self: T, sender: ContractAddress, recipient: ContractAddress, amount: u256, ) -> bool; fn allowance(self: @T, owner: ContractAddress, spender: ContractAddress) -> u256; } @@ -17,7 +17,7 @@ mod YourToken { use openzeppelin_token::erc20::interface::IERC20; use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use super::{ContractAddress, IYourToken}; + use super::{ContractAddress}; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -28,16 +28,17 @@ mod YourToken { #[storage] struct Storage { #[substorage(v0)] - erc20: ERC20Component::Storage + erc20: ERC20Component::Storage, } #[event] #[derive(Drop, starknet::Event)] enum Event { #[flat] - ERC20Event: ERC20Component::Event + ERC20Event: ERC20Component::Event, } + #[constructor] // Todo Checkpoint 1: Edit the constructor to mint the fixed supply of tokens to the recipient. fn constructor(ref self: ContractState, recipient: ContractAddress) { @@ -67,12 +68,12 @@ mod YourToken { ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, - amount: u256 + amount: u256, ) -> bool { self.erc20.transfer_from(sender, recipient, amount) } fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress + self: @ContractState, owner: ContractAddress, spender: ContractAddress, ) -> u256 { self.erc20.allowance(owner, spender) } diff --git a/packages/snfoundry/contracts/src/mock_contracts/MockETHToken.cairo b/packages/snfoundry/contracts/src/mock_contracts/MockETHToken.cairo index 07ab1feb5..000440945 100644 --- a/packages/snfoundry/contracts/src/mock_contracts/MockETHToken.cairo +++ b/packages/snfoundry/contracts/src/mock_contracts/MockETHToken.cairo @@ -12,14 +12,14 @@ pub mod MockETHToken { #[storage] struct Storage { #[substorage(v0)] - erc20: ERC20Component::Storage + erc20: ERC20Component::Storage, } #[event] #[derive(Drop, starknet::Event)] enum Event { #[flat] - ERC20Event: ERC20Component::Event + ERC20Event: ERC20Component::Event, } #[constructor] diff --git a/packages/snfoundry/contracts/src/test/TestContract.cairo b/packages/snfoundry/contracts/src/test/TestContract.cairo index 2c9540ddf..4c4c1bd2f 100644 --- a/packages/snfoundry/contracts/src/test/TestContract.cairo +++ b/packages/snfoundry/contracts/src/test/TestContract.cairo @@ -4,8 +4,8 @@ use contracts::mock_contracts::MockETHToken; use openzeppelin_token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use openzeppelin_utils::serde::SerializedAppend; use snforge_std::{ - declare, cheat_caller_address, start_cheat_block_timestamp_global, CheatSpan, - DeclareResultTrait, ContractClassTrait, + CheatSpan, ContractClassTrait, DeclareResultTrait, cheat_caller_address, declare, + start_cheat_block_timestamp_global, }; use starknet::{ContractAddress, contract_address_const, get_block_timestamp}; @@ -57,7 +57,7 @@ fn deploy_vendor_contract() -> ContractAddress { let eth_amount_wei: u256 = 1000000000000000000; // 1_ETH_IN_WEI let eth_token_dispatcher = IERC20CamelDispatcher { contract_address: eth_token_address }; assert( - eth_token_dispatcher.transfer(vendor_contract_address, eth_amount_wei), 'Transfer failed' + eth_token_dispatcher.transfer(vendor_contract_address, eth_amount_wei), 'Transfer failed', ); let vendor_eth_balance = eth_token_dispatcher.balanceOf(vendor_contract_address); println!("-- Vendor eth balance: {:?} ETH in wei", vendor_eth_balance); @@ -68,7 +68,7 @@ fn deploy_vendor_contract() -> ContractAddress { let your_token_dispatcher = IYourTokenDispatcher { contract_address: your_token_address }; let INITIAL_BALANCE: u256 = 1000000000000000000000; // 1000_GLD_IN_WEI assert( - your_token_dispatcher.transfer(vendor_contract_address, INITIAL_BALANCE), 'Transfer failed' + your_token_dispatcher.transfer(vendor_contract_address, INITIAL_BALANCE), 'Transfer failed', ); let vendor_token_balance = your_token_dispatcher.balance_of(vendor_contract_address); println!("-- Vendor GLD token balance: {:?} GLD in wei", vendor_token_balance); @@ -121,7 +121,7 @@ fn test_buy_tokens() { eth_token_dispatcher.approve(vendor_contract_address, eth_amount_wei); // check allowance let allowance = eth_token_dispatcher.allowance(tester_address, vendor_contract_address); - assert_eq!(allowance, eth_amount_wei, "Allowance should be equal to the bought amount"); + assert(allowance == eth_amount_wei, 'Allowance should be equal'); // Change the caller address of the your_token_address to the tester_address cheat_caller_address(vendor_contract_address, tester_address, CheatSpan::TargetCalls(1)); @@ -133,7 +133,7 @@ fn test_buy_tokens() { let expected_balance = starting_balance + expected_tokens; // 1000 + 0.1 = 1000.1_GLD_IN_WEI let new_balance = your_token_dispatcher.balance_of(tester_address); println!("---- New token balance: {:?} GLD in wei", new_balance); - assert_eq!(new_balance, expected_balance, "Balance should be increased by the bought amount"); + assert(new_balance == expected_balance, 'Balance should be increased'); } // Should let us sell tokens and we should get the appropriate amount eth back... @@ -157,7 +157,7 @@ fn test_sell_tokens() { your_token_dispatcher.approve(vendor_contract_address, gld_token_amount_wei); // check allowance let allowance = your_token_dispatcher.allowance(tester_address, vendor_contract_address); - assert_eq!(allowance, gld_token_amount_wei, "Allowance should be equal to the sold amount"); + assert(allowance == gld_token_amount_wei, 'Allowance equal to sold amount'); // Change the caller address of the your_token_address to the tester_address cheat_caller_address(vendor_contract_address, tester_address, CheatSpan::TargetCalls(1)); @@ -167,7 +167,7 @@ fn test_sell_tokens() { println!("---- New token balance: {:?} GLD in wei", new_balance); let expected_balance = starting_balance - gld_token_amount_wei; // 2000 - 0.1 = 1999.9_GLD_IN_WEI - assert_eq!(new_balance, expected_balance, "Balance should be decreased by the sold amount"); + assert(new_balance == expected_balance, 'Balance should be decreased'); } //Should let the owner (and nobody else) withdraw the eth from the contract... @@ -194,7 +194,7 @@ fn test_failing_withdraw_tokens() { eth_token_dispatcher.approve(vendor_contract_address, eth_amount_wei); // check allowance let allowance = eth_token_dispatcher.allowance(tester_address, vendor_contract_address); - assert_eq!(allowance, eth_amount_wei, "Allowance should be equal to the bought amount"); + assert(allowance == eth_amount_wei, 'Allowance should be equal'); // Change the caller address of the your_token_address to the tester_address cheat_caller_address(vendor_contract_address, tester_address, CheatSpan::TargetCalls(1)); @@ -206,7 +206,7 @@ fn test_failing_withdraw_tokens() { let expected_balance = starting_balance + expected_tokens; // 1000 + 0.1 = 1000.1_GLD_IN_WEI let new_balance = your_token_dispatcher.balance_of(tester_address); println!("---- New token balance: {:?} GLD in wei", new_balance); - assert_eq!(new_balance, expected_balance, "Balance should be increased by the bought amount"); + assert(new_balance == expected_balance, 'Balance should be increased'); let vendor_eth_balance = eth_token_dispatcher.balanceOf(vendor_contract_address); println!("---- Vendor contract eth balance: {:?} ETH in wei", vendor_eth_balance); @@ -221,9 +221,9 @@ fn test_failing_withdraw_tokens() { let balance_after_attemp_withdraw = eth_token_dispatcher.balanceOf(vendor_contract_address); println!( "---- Vendor contract eth balance after withdraw: {:?} ETH in wei", - balance_after_attemp_withdraw + balance_after_attemp_withdraw, ); - assert_eq!(not_owner_balance, balance_after_attemp_withdraw, "Balance should be the same"); + assert(not_owner_balance == balance_after_attemp_withdraw, 'Balance should be the same'); } #[test] @@ -251,7 +251,7 @@ fn test_success_withdraw_tokens() { let owner_eth_balance_before_withdraw = eth_token_dispatcher.balanceOf(owner_address); println!( "---- Owner token balance before withdraw: {:?} ETH in wei", - owner_eth_balance_before_withdraw + owner_eth_balance_before_withdraw, ); let vendor_eth_balance = eth_token_dispatcher.balanceOf(vendor_contract_address); @@ -263,12 +263,10 @@ fn test_success_withdraw_tokens() { vendor_dispatcher.withdraw(); let eth_balance_after_withdraw = eth_token_dispatcher.balanceOf(owner_address); println!( - "---- Owner token balance after withdraw: {:?} ETH in wei", eth_balance_after_withdraw + "---- Owner token balance after withdraw: {:?} ETH in wei", eth_balance_after_withdraw, ); - assert_eq!( - owner_eth_balance_before_withdraw + vendor_eth_balance, - eth_balance_after_withdraw, - "Balance should be the same" + assert( + owner_eth_balance_before_withdraw + vendor_eth_balance == eth_balance_after_withdraw, + 'Balance should be the same', ); } - diff --git a/packages/snfoundry/scripts-ts/deploy-contract.ts b/packages/snfoundry/scripts-ts/deploy-contract.ts index 5c6dc803f..71a0878bd 100644 --- a/packages/snfoundry/scripts-ts/deploy-contract.ts +++ b/packages/snfoundry/scripts-ts/deploy-contract.ts @@ -109,6 +109,27 @@ const deployContract_NotWait = async (payload: { } }; +const findContractFile = ( + contract: string, + fileType: "compiled_contract_class" | "contract_class" +): string => { + const targetDir = path.resolve(__dirname, "../contracts/target/dev"); + const files = fs.readdirSync(targetDir); + + // Look for files that end with the contract name and file type + const pattern = new RegExp(`.*${contract}\\.${fileType}\\.json$`); + const matchingFile = files.find((file) => pattern.test(file)); + + if (!matchingFile) { + throw new Error( + `Could not find ${fileType} file for contract "${contract}". ` + + `Try removing snfoundry/contracts/target, then run 'yarn compile' and check if your contract name is correct inside the contracts/target/dev directory.` + ); + } + + return path.join(targetDir, matchingFile); +}; + /** * Deploy a contract using the specified parameters. * @@ -156,28 +177,13 @@ const deployContract = async ( try { compiledContractCasm = JSON.parse( fs - .readFileSync( - path.resolve( - __dirname, - `../contracts/target/dev/contracts_${contract}.compiled_contract_class.json` - ) - ) + .readFileSync(findContractFile(contract, "compiled_contract_class")) .toString("ascii") ); } catch (error) { - if ( - typeof error.message === "string" && - error.message.includes("no such file") && - error.message.includes("compiled_contract_class") - ) { - const match = error.message.match( - /\/dev\/(.+?)\.compiled_contract_class/ - ); - const missingContract = match ? match[1].split("_").pop() : "Unknown"; + if (error.message.includes("Could not find")) { console.error( - red( - `The contract "${missingContract}" doesn't exist or is not compiled` - ) + red(`The contract "${contract}" doesn't exist or is not compiled`) ); } else { console.error(red("Error reading compiled contract class file: "), error); @@ -191,12 +197,7 @@ const deployContract = async ( try { compiledContractSierra = JSON.parse( fs - .readFileSync( - path.resolve( - __dirname, - `../contracts/target/dev/contracts_${contract}.contract_class.json` - ) - ) + .readFileSync(findContractFile(contract, "contract_class")) .toString("ascii") ); } catch (error) { diff --git a/packages/snfoundry/scripts-ts/helpers/fees.ts b/packages/snfoundry/scripts-ts/helpers/fees.ts index 684df7a7c..508675d54 100644 --- a/packages/snfoundry/scripts-ts/helpers/fees.ts +++ b/packages/snfoundry/scripts-ts/helpers/fees.ts @@ -1,14 +1,6 @@ -import { - CairoContract, - CompiledSierra, - Contract, - Provider, - uint256, - Abi, -} from "starknet"; +import { Contract, Provider, uint256, Abi } from "starknet"; import { red, yellow } from "./colorize-log"; import { Network } from "../types"; -import { isString } from "util"; export const erc20ABI = [ { diff --git a/yarn.lock b/yarn.lock index d5e8f71cc..7b0232b8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -258,6 +258,13 @@ __metadata: languageName: node linkType: hard +"@discoveryjs/json-ext@npm:^0.6.1": + version: 0.6.3 + resolution: "@discoveryjs/json-ext@npm:0.6.3" + checksum: 8305a5feb9bbaedbfdb91f938cb577f98c34cb432535dbc7af5e5df7f1cb3d1895f7a9ec0d956b5bd9e980e5b7f8cd36684c4c9ed219e6e556e0dfe367c4cb66 + languageName: node + linkType: hard + "@edge-runtime/format@npm:2.2.1": version: 2.2.1 resolution: "@edge-runtime/format@npm:2.2.1" @@ -623,6 +630,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.6 + resolution: "@jridgewell/source-map@npm:0.3.6" + dependencies: + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + checksum: c9dc7d899397df95e3c9ec287b93c0b56f8e4453cd20743e2b9c8e779b1949bc3cccf6c01bb302779e46560eb45f62ea38d19fedd25370d814734268450a9f30 + languageName: node + linkType: hard + "@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": version: 1.5.0 resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" @@ -2180,6 +2197,19 @@ __metadata: languageName: node linkType: hard +"@scaffold-stark/stark-burner@npm:0.1.8": + version: 0.1.8 + resolution: "@scaffold-stark/stark-burner@npm:0.1.8" + dependencies: + "@starknet-io/types-js": ^0.7.7 + peerDependencies: + "@starknet-react/chains": ^3.1.0 + "@starknet-react/core": ^3.6.0 + starknet: ^6.12.0 + checksum: 0bab97de85f244b4b670dd3ef4799a408c4fba18e2d7440925d08957725e2a379d240a906cab033d78c374ec0b98724f67305b12f62cd8738133d05114548f42 + languageName: node + linkType: hard + "@scure/base@npm:~1.1.3, @scure/base@npm:~1.1.7, @scure/base@npm:~1.1.8": version: 1.1.9 resolution: "@scure/base@npm:1.1.9" @@ -2232,6 +2262,7 @@ __metadata: "@heroicons/react": ^2.1.3 "@radix-ui/react-icons": 1.3.0 "@radix-ui/themes": 2.0.3 + "@scaffold-stark/stark-burner": 0.1.8 "@starknet-io/types-js": ^0.7.7 "@starknet-react/chains": ^3.1.0 "@starknet-react/core": ^3.6.0 @@ -2240,9 +2271,9 @@ __metadata: "@testing-library/react": ^16.0.1 "@types/node": ^20 "@types/nprogress": ^0 - "@types/react": ^18 + "@types/react": latest "@types/react-copy-to-clipboard": ^5.0.4 - "@types/react-dom": ^18 + "@types/react-dom": latest "@vitejs/plugin-react": ^4.3.1 "@vitest/coverage-istanbul": ^2.1.1 "@vitest/coverage-v8": ^2.1.1 @@ -2259,6 +2290,8 @@ __metadata: next-themes: ^0.2.1 nprogress: ^0.2.0 postcss: ^8 + prettier: ^3.4.2 + prettier-standalone: ^1.3.1-0 qrcode.react: ^3.1.0 react: ^18 react-copy-to-clipboard: ^5.1.0 @@ -2271,6 +2304,8 @@ __metadata: usehooks-ts: ^2.13.0 vercel: ^33.7.1 vitest: ^2.1.1 + webpack: ^5.97.1 + webpack-cli: ^6.0.1 zustand: ^4.1.2 languageName: unknown linkType: soft @@ -2494,14 +2529,34 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:1.0.6, @types/estree@npm:^1.0.0": +"@types/eslint-scope@npm:^3.7.7": + version: 3.7.7 + resolution: "@types/eslint-scope@npm:3.7.7" + dependencies: + "@types/eslint": "*" + "@types/estree": "*" + checksum: e2889a124aaab0b89af1bab5959847c5bec09809209255de0e63b9f54c629a94781daa04adb66bffcdd742f5e25a17614fb933965093c0eea64aacda4309380e + languageName: node + linkType: hard + +"@types/eslint@npm:*": + version: 9.6.1 + resolution: "@types/eslint@npm:9.6.1" + dependencies: + "@types/estree": "*" + "@types/json-schema": "*" + checksum: c286e79707ab604b577cf8ce51d9bbb9780e3d6a68b38a83febe13fa05b8012c92de17c28532fac2b03d3c460123f5055d603a579685325246ca1c86828223e0 + languageName: node + linkType: hard + +"@types/estree@npm:*, @types/estree@npm:1.0.6, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6": version: 1.0.6 resolution: "@types/estree@npm:1.0.6" checksum: 8825d6e729e16445d9a1dd2fb1db2edc5ed400799064cd4d028150701031af012ba30d6d03fe9df40f4d7a437d0de6d2b256020152b7b09bde9f2e420afdffd9 languageName: node linkType: hard -"@types/json-schema@npm:^7.0.6": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 @@ -2515,6 +2570,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:*": + version: 22.10.2 + resolution: "@types/node@npm:22.10.2" + dependencies: + undici-types: ~6.20.0 + checksum: b22401e6e7d1484e437d802c72f5560e18100b1257b9ad0574d6fe05bebe4dbcb620ea68627d1f1406775070d29ace8b6b51f57e7b1c7b8bafafe6da7f29c843 + languageName: node + linkType: hard + "@types/node@npm:14.18.33": version: 14.18.33 resolution: "@types/node@npm:14.18.33" @@ -2570,16 +2634,16 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^18": - version: 18.3.1 - resolution: "@types/react-dom@npm:18.3.1" - dependencies: - "@types/react": "*" - checksum: ad28ecce3915d30dc76adc2a1373fda1745ba429cea290e16c6628df9a05fd80b6403c8e87d78b45e6c60e51df7a67add389ab62b90070fbfdc9bda8307d9953 +"@types/react-dom@npm:latest": + version: 19.0.2 + resolution: "@types/react-dom@npm:19.0.2" + peerDependencies: + "@types/react": ^19.0.0 + checksum: d2ae81ec0b8eee7a4bf31918796fdaa34e8db68f69682163bc212d759de76783e6ffcc02c02722dcf508429067148841e6da81414cc730ca2a28c9c2b350c880 languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:^18": +"@types/react@npm:*": version: 18.3.12 resolution: "@types/react@npm:18.3.12" dependencies: @@ -2589,6 +2653,15 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:latest": + version: 19.0.2 + resolution: "@types/react@npm:19.0.2" + dependencies: + csstype: ^3.0.2 + checksum: 2f12c2a84b778283884d41560c723d815153d88c56cacf25c0166329e9099c35c82c602a21d8831a381e2ef5574434ebd7bf09a636fe073558919474b0b3c9ed + languageName: node + linkType: hard + "@types/yargs-parser@npm:*": version: 21.0.3 resolution: "@types/yargs-parser@npm:21.0.3" @@ -3150,6 +3223,204 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/ast@npm:1.14.1, @webassemblyjs/ast@npm:^1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/ast@npm:1.14.1" + dependencies: + "@webassemblyjs/helper-numbers": 1.13.2 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + checksum: f9154ad9ea14f6f2374ebe918c221fd69a4d4514126a1acc6fa4966e8d27ab28cb550a5e6880032cf620e19640578658a7e5a55bd2aad1e3db4e9d598b8f2099 + languageName: node + linkType: hard + +"@webassemblyjs/floating-point-hex-parser@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.13.2" + checksum: e866ec8433f4a70baa511df5e8f2ebcd6c24f4e2cc6274c7c5aabe2bcce3459ea4680e0f35d450e1f3602acf3913b6b8e4f15069c8cfd34ae8609fb9a7d01795 + languageName: node + linkType: hard + +"@webassemblyjs/helper-api-error@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/helper-api-error@npm:1.13.2" + checksum: 48b5df7fd3095bb252f59a139fe2cbd999a62ac9b488123e9a0da3906ad8a2f2da7b2eb21d328c01a90da987380928706395c2897d1f3ed9e2125b6d75a920d0 + languageName: node + linkType: hard + +"@webassemblyjs/helper-buffer@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/helper-buffer@npm:1.14.1" + checksum: b611e981dfd6a797c3d8fc3a772de29a6e55033737c2c09c31bb66c613bdbb2d25f915df1dee62a602c6acc057ca71128432fa8c3e22a893e1219dc454f14ede + languageName: node + linkType: hard + +"@webassemblyjs/helper-numbers@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/helper-numbers@npm:1.13.2" + dependencies: + "@webassemblyjs/floating-point-hex-parser": 1.13.2 + "@webassemblyjs/helper-api-error": 1.13.2 + "@xtuc/long": 4.2.2 + checksum: 49e2c9bf9b66997e480f6b44d80f895b3cde4de52ac135921d28e144565edca6903a519f627f4089b5509de1d7f9e5023f0e1a94ff78a36c9e2eb30e7c18ffd2 + languageName: node + linkType: hard + +"@webassemblyjs/helper-wasm-bytecode@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.13.2" + checksum: 8e059e1c1f0294f4fc3df8e4eaff3c5ef6e2e1358f34ebc118eaf5070ed59e56ed7fc92b28be734ebde17c8d662d5d27e06ade686c282445135da083ae11c128 + languageName: node + linkType: hard + +"@webassemblyjs/helper-wasm-section@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.14.1" + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/wasm-gen": 1.14.1 + checksum: 0a08d454a63192cd66abf91b6f060ac4b466cef341262246e9dcc828dd4c8536195dea9b46a1244b1eac65b59b8b502164a771a190052a92ff0a0a2ded0f8f53 + languageName: node + linkType: hard + +"@webassemblyjs/ieee754@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/ieee754@npm:1.13.2" + dependencies: + "@xtuc/ieee754": ^1.2.0 + checksum: d7e3520baa37a7309fa7db4d73d69fb869878853b1ebd4b168821bd03fcc4c0e1669c06231315b0039035d9a7a462e53de3ad982da4a426a4b0743b5888e8673 + languageName: node + linkType: hard + +"@webassemblyjs/leb128@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/leb128@npm:1.13.2" + dependencies: + "@xtuc/long": 4.2.2 + checksum: 64083507f7cff477a6d71a9e325d95665cea78ec8df99ca7c050e1cfbe300fbcf0842ca3dcf3b4fa55028350135588a4f879398d3dd2b6a8de9913ce7faf5333 + languageName: node + linkType: hard + +"@webassemblyjs/utf8@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/utf8@npm:1.13.2" + checksum: 95ec6052f30eefa8d50c9b2a3394d08b17d53a4aa52821451d41d774c126fa8f39b988fbf5bff56da86852a87c16d676e576775a4071e5e5ccf020cc85a4b281 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-edit@npm:^1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wasm-edit@npm:1.14.1" + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/helper-wasm-section": 1.14.1 + "@webassemblyjs/wasm-gen": 1.14.1 + "@webassemblyjs/wasm-opt": 1.14.1 + "@webassemblyjs/wasm-parser": 1.14.1 + "@webassemblyjs/wast-printer": 1.14.1 + checksum: 9341c3146bb1b7863f03d6050c2a66990f20384ca137388047bbe1feffacb599e94fca7b7c18287d17e2449ffb4005fdc7f41f674a6975af9ad8522756f8ffff + languageName: node + linkType: hard + +"@webassemblyjs/wasm-gen@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wasm-gen@npm:1.14.1" + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/ieee754": 1.13.2 + "@webassemblyjs/leb128": 1.13.2 + "@webassemblyjs/utf8": 1.13.2 + checksum: 401b12bec7431c4fc29d9414bbe40d3c6dc5be04d25a116657c42329f5481f0129f3b5834c293f26f0e42681ceac9157bf078ce9bdb6a7f78037c650373f98b2 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-opt@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wasm-opt@npm:1.14.1" + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/wasm-gen": 1.14.1 + "@webassemblyjs/wasm-parser": 1.14.1 + checksum: 60c697a9e9129d8d23573856df0791ba33cea4a3bc2339044cae73128c0983802e5e50a42157b990eeafe1237eb8e7653db6de5f02b54a0ae7b81b02dcdf2ae9 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-parser@npm:1.14.1, @webassemblyjs/wasm-parser@npm:^1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wasm-parser@npm:1.14.1" + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-api-error": 1.13.2 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/ieee754": 1.13.2 + "@webassemblyjs/leb128": 1.13.2 + "@webassemblyjs/utf8": 1.13.2 + checksum: 93f1fe2676da465b4e824419d9812a3d7218de4c3addd4e916c04bc86055fa134416c1b67e4b7cbde8d728c0dce2721d06cc0bfe7a7db7c093a0898009937405 + languageName: node + linkType: hard + +"@webassemblyjs/wast-printer@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wast-printer@npm:1.14.1" + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@xtuc/long": 4.2.2 + checksum: 517881a0554debe6945de719d100b2d8883a2d24ddf47552cdeda866341e2bb153cd824a864bc7e2a61190a4b66b18f9899907e0074e9e820d2912ac0789ea60 + languageName: node + linkType: hard + +"@webpack-cli/configtest@npm:^3.0.1": + version: 3.0.1 + resolution: "@webpack-cli/configtest@npm:3.0.1" + peerDependencies: + webpack: ^5.82.0 + webpack-cli: 6.x.x + checksum: a83301ff360de6c36fe98766f1f391db6149f0806450ce31484c49df3902584f73385453da23f3324a605d5afad4d2889654ada679afd49e35c59a2c4769ee97 + languageName: node + linkType: hard + +"@webpack-cli/info@npm:^3.0.1": + version: 3.0.1 + resolution: "@webpack-cli/info@npm:3.0.1" + peerDependencies: + webpack: ^5.82.0 + webpack-cli: 6.x.x + checksum: 0ddcfd8b370d924f71cc085b17b31a77b362d8046fedb38ac601042733568cda05b0c8c7b1e0e1e050dc926ee76f754cd9c4f351e2b361a0d157465f8b03b689 + languageName: node + linkType: hard + +"@webpack-cli/serve@npm:^3.0.1": + version: 3.0.1 + resolution: "@webpack-cli/serve@npm:3.0.1" + peerDependencies: + webpack: ^5.82.0 + webpack-cli: 6.x.x + peerDependenciesMeta: + webpack-dev-server: + optional: true + checksum: 5bbd66548faa8adc7b0759f5880411b611c9a25e9303e2f580ab2d658ec105926a21c981fa7797e9f7c24093d0a0ff96d6f2d8f76f265d7760441cf138cab889 + languageName: node + linkType: hard + +"@xtuc/ieee754@npm:^1.2.0": + version: 1.2.0 + resolution: "@xtuc/ieee754@npm:1.2.0" + checksum: ac56d4ca6e17790f1b1677f978c0c6808b1900a5b138885d3da21732f62e30e8f0d9120fcf8f6edfff5100ca902b46f8dd7c1e3f903728634523981e80e2885a + languageName: node + linkType: hard + +"@xtuc/long@npm:4.2.2": + version: 4.2.2 + resolution: "@xtuc/long@npm:4.2.2" + checksum: 8ed0d477ce3bc9c6fe2bf6a6a2cc316bb9c4127c5a7827bae947fa8ec34c7092395c5a283cc300c05b5fa01cbbfa1f938f410a7bf75db7c7846fea41949989ec + languageName: node + linkType: hard + "abbrev@npm:1": version: 1.1.1 resolution: "abbrev@npm:1.1.1" @@ -3220,7 +3491,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.11.0, acorn@npm:^8.4.1, acorn@npm:^8.6.0, acorn@npm:^8.9.0": +"acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.4.1, acorn@npm:^8.6.0, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.14.0 resolution: "acorn@npm:8.14.0" bin: @@ -3264,6 +3535,40 @@ __metadata: languageName: node linkType: hard +"ajv-formats@npm:^2.1.1": + version: 2.1.1 + resolution: "ajv-formats@npm:2.1.1" + dependencies: + ajv: ^8.0.0 + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + checksum: 4a287d937f1ebaad4683249a4c40c0fa3beed30d9ddc0adba04859026a622da0d317851316ea64b3680dc60f5c3c708105ddd5d5db8fe595d9d0207fd19f90b7 + languageName: node + linkType: hard + +"ajv-keywords@npm:^3.5.2": + version: 3.5.2 + resolution: "ajv-keywords@npm:3.5.2" + peerDependencies: + ajv: ^6.9.1 + checksum: 7dc5e5931677a680589050f79dcbe1fefbb8fea38a955af03724229139175b433c63c68f7ae5f86cf8f65d55eb7c25f75a046723e2e58296707617ca690feae9 + languageName: node + linkType: hard + +"ajv-keywords@npm:^5.1.0": + version: 5.1.0 + resolution: "ajv-keywords@npm:5.1.0" + dependencies: + fast-deep-equal: ^3.1.3 + peerDependencies: + ajv: ^8.8.2 + checksum: c35193940b853119242c6757787f09ecf89a2c19bcd36d03ed1a615e710d19d450cb448bfda407b939aba54b002368c8bff30529cc50a0536a8e10bcce300421 + languageName: node + linkType: hard + "ajv@npm:8.6.3": version: 8.6.3 resolution: "ajv@npm:8.6.3" @@ -3276,7 +3581,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.0.0, ajv@npm:^6.12.4": +"ajv@npm:^6.0.0, ajv@npm:^6.12.4, ajv@npm:^6.12.5": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -3288,6 +3593,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:^8.0.0, ajv@npm:^8.9.0": + version: 8.17.1 + resolution: "ajv@npm:8.17.1" + dependencies: + fast-deep-equal: ^3.1.3 + fast-uri: ^3.0.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + checksum: 1797bf242cfffbaf3b870d13565bd1716b73f214bb7ada9a497063aada210200da36e3ed40237285f3255acc4feeae91b1fb183625331bad27da95973f7253d9 + languageName: node + linkType: hard + "ansi-regex@npm:^5.0.1": version: 5.0.1 resolution: "ansi-regex@npm:5.0.1" @@ -3700,6 +4017,13 @@ __metadata: languageName: node linkType: hard +"buffer-from@npm:^1.0.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb + languageName: node + linkType: hard + "busboy@npm:1.6.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" @@ -3871,6 +4195,13 @@ __metadata: languageName: node linkType: hard +"chrome-trace-event@npm:^1.0.2": + version: 1.0.4 + resolution: "chrome-trace-event@npm:1.0.4" + checksum: fcbbd9dd0cd5b48444319007cc0c15870fd8612cc0df320908aa9d5e8a244084d48571eb28bf3c58c19327d2c5838f354c2d89fac3956d8e992273437401ac19 + languageName: node + linkType: hard + "cjs-module-lexer@npm:1.2.3": version: 1.2.3 resolution: "cjs-module-lexer@npm:1.2.3" @@ -3910,6 +4241,17 @@ __metadata: languageName: node linkType: hard +"clone-deep@npm:^4.0.1": + version: 4.0.1 + resolution: "clone-deep@npm:4.0.1" + dependencies: + is-plain-object: ^2.0.4 + kind-of: ^6.0.2 + shallow-clone: ^3.0.0 + checksum: 770f912fe4e6f21873c8e8fbb1e99134db3b93da32df271d00589ea4a29dbe83a9808a322c93f3bcaf8584b8b4fa6fc269fc8032efbaa6728e0c9886c74467d2 + languageName: node + linkType: hard + "code-block-writer@npm:^10.1.1": version: 10.1.1 resolution: "code-block-writer@npm:10.1.1" @@ -3942,6 +4284,13 @@ __metadata: languageName: node linkType: hard +"colorette@npm:^2.0.14": + version: 2.0.20 + resolution: "colorette@npm:2.0.20" + checksum: 0c016fea2b91b733eb9f4bcdb580018f52c0bc0979443dad930e5037a968237ac53d9beb98e218d2e9235834f8eebce7f8e080422d6194e957454255bde71d3d + languageName: node + linkType: hard + "combined-stream@npm:^1.0.8": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" @@ -3951,6 +4300,20 @@ __metadata: languageName: node linkType: hard +"commander@npm:^12.1.0": + version: 12.1.0 + resolution: "commander@npm:12.1.0" + checksum: 68e9818b00fc1ed9cdab9eb16905551c2b768a317ae69a5e3c43924c2b20ac9bb65b27e1cab36aeda7b6496376d4da908996ba2c0b5d79463e0fb1e77935d514 + languageName: node + linkType: hard + +"commander@npm:^2.20.0": + version: 2.20.3 + resolution: "commander@npm:2.20.3" + checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e + languageName: node + linkType: hard + "commander@npm:^4.0.0": version: 4.1.1 resolution: "commander@npm:4.1.1" @@ -4009,7 +4372,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -4385,6 +4748,16 @@ __metadata: languageName: node linkType: hard +"enhanced-resolve@npm:^5.17.1": + version: 5.18.0 + resolution: "enhanced-resolve@npm:5.18.0" + dependencies: + graceful-fs: ^4.2.4 + tapable: ^2.2.0 + checksum: 77c6b11f0d19f21f52214e5a2c0dfb7070decb4045572f44be4cacf92b4be5e2c1d9a4c044a226d1003ca9daf9b71d498d256e7520ff5060f23d0284f814d392 + languageName: node + linkType: hard + "entities@npm:^4.5.0": version: 4.5.0 resolution: "entities@npm:4.5.0" @@ -4408,6 +4781,15 @@ __metadata: languageName: node linkType: hard +"envinfo@npm:^7.14.0": + version: 7.14.0 + resolution: "envinfo@npm:7.14.0" + bin: + envinfo: dist/cli.js + checksum: 137c1dd9a4d5781c4a6cdc6b695454ba3c4ba1829f73927198aa4122f11b35b59d7b2cb7e1ceea1364925a30278897548511d22f860c14253a33797d0bebd551 + languageName: node + linkType: hard + "err-code@npm:^2.0.2": version: 2.0.3 resolution: "err-code@npm:2.0.3" @@ -4515,6 +4897,13 @@ __metadata: languageName: node linkType: hard +"es-module-lexer@npm:^1.2.1": + version: 1.6.0 + resolution: "es-module-lexer@npm:1.6.0" + checksum: 4413a9aed9bf581de62b98174f3eea3f23ce2994fb6832df64bdd6504f6977da1a3b5ebd3c10f75e3c2f214dcf1a1d8b54be5e62c71b7110e6ccedbf975d2b7d + languageName: node + linkType: hard + "es-module-lexer@npm:^1.5.4": version: 1.5.4 resolution: "es-module-lexer@npm:1.5.4" @@ -5029,6 +5418,16 @@ __metadata: languageName: node linkType: hard +"eslint-scope@npm:5.1.1": + version: 5.1.1 + resolution: "eslint-scope@npm:5.1.1" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^4.1.1 + checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb + languageName: node + linkType: hard + "eslint-scope@npm:^7.2.2": version: 7.2.2 resolution: "eslint-scope@npm:7.2.2" @@ -5133,6 +5532,13 @@ __metadata: languageName: node linkType: hard +"estraverse@npm:^4.1.1": + version: 4.3.0 + resolution: "estraverse@npm:4.3.0" + checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 + languageName: node + linkType: hard + "estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": version: 5.3.0 resolution: "estraverse@npm:5.3.0" @@ -5199,6 +5605,13 @@ __metadata: languageName: node linkType: hard +"events@npm:^3.2.0": + version: 3.3.0 + resolution: "events@npm:3.3.0" + checksum: f6f487ad2198aa41d878fa31452f1a3c00958f46e9019286ff4787c84aac329332ab45c9cdc8c445928fc6d7ded294b9e005a7fce9426488518017831b272780 + languageName: node + linkType: hard + "execa@npm:3.2.0": version: 3.2.0 resolution: "execa@npm:3.2.0" @@ -5265,6 +5678,20 @@ __metadata: languageName: node linkType: hard +"fast-uri@npm:^3.0.1": + version: 3.0.3 + resolution: "fast-uri@npm:3.0.3" + checksum: c52e6c86465f5c240e84a4485fb001088cc743d261a4b54b0050ce4758b1648bdbe53da1328ef9620149dca1435e3de64184f226d7c0a3656cb5837b3491e149 + languageName: node + linkType: hard + +"fastest-levenshtein@npm:^1.0.12": + version: 1.0.16 + resolution: "fastest-levenshtein@npm:1.0.16" + checksum: a78d44285c9e2ae2c25f3ef0f8a73f332c1247b7ea7fb4a191e6bb51aa6ee1ef0dfb3ed113616dcdc7023e18e35a8db41f61c8d88988e877cf510df8edafbc71 + languageName: node + linkType: hard + "fastparse@npm:^1.1.2": version: 1.1.2 resolution: "fastparse@npm:1.1.2" @@ -5325,6 +5752,16 @@ __metadata: languageName: node linkType: hard +"find-up@npm:^4.0.0": + version: 4.1.0 + resolution: "find-up@npm:4.1.0" + dependencies: + locate-path: ^5.0.0 + path-exists: ^4.0.0 + checksum: 4c172680e8f8c1f78839486e14a43ef82e9decd0e74145f40707cc42e7420506d5ec92d9a11c22bd2c48fb0c384ea05dd30e10dd152fefeec6f2f75282a8b844 + languageName: node + linkType: hard + "find-up@npm:^5.0.0": version: 5.0.0 resolution: "find-up@npm:5.0.0" @@ -5346,6 +5783,15 @@ __metadata: languageName: node linkType: hard +"flat@npm:^5.0.2": + version: 5.0.2 + resolution: "flat@npm:5.0.2" + bin: + flat: cli.js + checksum: 12a1536ac746db74881316a181499a78ef953632ddd28050b7a3a43c62ef5462e3357c8c29d76072bb635f147f7a9a1f0c02efef6b4be28f8db62ceb3d5c7f5d + languageName: node + linkType: hard + "flatted@npm:^3.2.9": version: 3.3.2 resolution: "flatted@npm:3.3.2" @@ -5635,6 +6081,13 @@ __metadata: languageName: node linkType: hard +"glob-to-regexp@npm:^0.4.1": + version: 0.4.1 + resolution: "glob-to-regexp@npm:0.4.1" + checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167 + languageName: node + linkType: hard + "glob@npm:10.3.10": version: 10.3.10 resolution: "glob@npm:10.3.10" @@ -5745,7 +6198,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -5948,6 +6401,18 @@ __metadata: languageName: node linkType: hard +"import-local@npm:^3.0.2": + version: 3.2.0 + resolution: "import-local@npm:3.2.0" + dependencies: + pkg-dir: ^4.2.0 + resolve-cwd: ^3.0.0 + bin: + import-local-fixture: fixtures/cli.js + checksum: 0b0b0b412b2521739fbb85eeed834a3c34de9bc67e670b3d0b86248fc460d990a7b116ad056c084b87a693ef73d1f17268d6a5be626bb43c998a8b1c8a230004 + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -6004,6 +6469,13 @@ __metadata: languageName: node linkType: hard +"interpret@npm:^3.1.1": + version: 3.1.1 + resolution: "interpret@npm:3.1.1" + checksum: 35cebcf48c7351130437596d9ab8c8fe131ce4038da4561e6d665f25640e0034702a031cf7e3a5cea60ac7ac548bf17465e0571ede126f3d3a6933152171ac82 + languageName: node + linkType: hard + "invariant@npm:^2.2.4": version: 2.2.4 resolution: "invariant@npm:2.2.4" @@ -6095,6 +6567,15 @@ __metadata: languageName: node linkType: hard +"is-core-module@npm:^2.16.0": + version: 2.16.1 + resolution: "is-core-module@npm:2.16.1" + dependencies: + hasown: ^2.0.2 + checksum: 6ec5b3c42d9cbf1ac23f164b16b8a140c3cec338bf8f884c076ca89950c7cc04c33e78f02b8cae7ff4751f3247e3174b2330f1fe4de194c7210deb8b1ea316a7 + languageName: node + linkType: hard + "is-data-view@npm:^1.0.1": version: 1.0.1 resolution: "is-data-view@npm:1.0.1" @@ -6198,6 +6679,15 @@ __metadata: languageName: node linkType: hard +"is-plain-object@npm:^2.0.4": + version: 2.0.4 + resolution: "is-plain-object@npm:2.0.4" + dependencies: + isobject: ^3.0.1 + checksum: 2a401140cfd86cabe25214956ae2cfee6fbd8186809555cd0e84574f88de7b17abacb2e477a6a658fa54c6083ecbda1e6ae404c7720244cd198903848fca70ca + languageName: node + linkType: hard + "is-potential-custom-element-name@npm:^1.0.1": version: 1.0.1 resolution: "is-potential-custom-element-name@npm:1.0.1" @@ -6319,6 +6809,13 @@ __metadata: languageName: node linkType: hard +"isobject@npm:^3.0.1": + version: 3.0.1 + resolution: "isobject@npm:3.0.1" + checksum: db85c4c970ce30693676487cca0e61da2ca34e8d4967c2e1309143ff910c207133a969f9e4ddb2dc6aba670aabce4e0e307146c310350b298e74a31f7d464703 + languageName: node + linkType: hard + "isomorphic-fetch@npm:^3.0.0": version: 3.0.0 resolution: "isomorphic-fetch@npm:3.0.0" @@ -6429,6 +6926,17 @@ __metadata: languageName: node linkType: hard +"jest-worker@npm:^27.4.5": + version: 27.5.1 + resolution: "jest-worker@npm:27.5.1" + dependencies: + "@types/node": "*" + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 98cd68b696781caed61c983a3ee30bf880b5bd021c01d98f47b143d4362b85d0737f8523761e2713d45e18b4f9a2b98af1eaee77afade4111bb65c77d6f7c980 + languageName: node + linkType: hard + "jiti@npm:^1.21.6": version: 1.21.6 resolution: "jiti@npm:1.21.6" @@ -6513,6 +7021,13 @@ __metadata: languageName: node linkType: hard +"json-parse-even-better-errors@npm:^2.3.1": + version: 2.3.1 + resolution: "json-parse-even-better-errors@npm:2.3.1" + checksum: 798ed4cf3354a2d9ccd78e86d2169515a0097a5c133337807cdf7f1fc32e1391d207ccfc276518cc1d7d8d4db93288b8a50ba4293d212ad1336e52a8ec0a941f + languageName: node + linkType: hard + "json-schema-to-ts@npm:1.6.4": version: 1.6.4 resolution: "json-schema-to-ts@npm:1.6.4" @@ -6610,6 +7125,13 @@ __metadata: languageName: node linkType: hard +"kind-of@npm:^6.0.2": + version: 6.0.3 + resolution: "kind-of@npm:6.0.3" + checksum: 3ab01e7b1d440b22fe4c31f23d8d38b4d9b91d9f291df683476576493d5dfd2e03848a8b05813dd0c3f0e835bc63f433007ddeceb71f05cb25c45ae1b19c6d3b + languageName: node + linkType: hard + "language-subtag-registry@npm:^0.3.20": version: 0.3.23 resolution: "language-subtag-registry@npm:0.3.23" @@ -6657,6 +7179,22 @@ __metadata: languageName: node linkType: hard +"loader-runner@npm:^4.2.0": + version: 4.3.0 + resolution: "loader-runner@npm:4.3.0" + checksum: a90e00dee9a16be118ea43fec3192d0b491fe03a32ed48a4132eb61d498f5536a03a1315531c19d284392a8726a4ecad71d82044c28d7f22ef62e029bf761569 + languageName: node + linkType: hard + +"locate-path@npm:^5.0.0": + version: 5.0.0 + resolution: "locate-path@npm:5.0.0" + dependencies: + p-locate: ^4.1.0 + checksum: 83e51725e67517287d73e1ded92b28602e3ae5580b301fe54bfb76c0c723e3f285b19252e375712316774cf52006cb236aed5704692c32db0d5d089b69696e30 + languageName: node + linkType: hard + "locate-path@npm:^6.0.0": version: 6.0.0 resolution: "locate-path@npm:6.0.0" @@ -6848,7 +7386,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -7076,6 +7614,13 @@ __metadata: languageName: node linkType: hard +"neo-async@npm:^2.6.2": + version: 2.6.2 + resolution: "neo-async@npm:2.6.2" + checksum: deac9f8d00eda7b2e5cd1b2549e26e10a0faa70adaa6fdadca701cc55f49ee9018e427f424bac0c790b7c7e2d3068db97f3093f1093975f2acb8f8818b936ed9 + languageName: node + linkType: hard + "next-themes@npm:^0.2.1": version: 0.2.1 resolution: "next-themes@npm:0.2.1" @@ -7453,6 +7998,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^2.2.0": + version: 2.3.0 + resolution: "p-limit@npm:2.3.0" + dependencies: + p-try: ^2.0.0 + checksum: 84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 + languageName: node + linkType: hard + "p-limit@npm:^3.0.2": version: 3.1.0 resolution: "p-limit@npm:3.1.0" @@ -7462,6 +8016,15 @@ __metadata: languageName: node linkType: hard +"p-locate@npm:^4.1.0": + version: 4.1.0 + resolution: "p-locate@npm:4.1.0" + dependencies: + p-limit: ^2.2.0 + checksum: 513bd14a455f5da4ebfcb819ef706c54adb09097703de6aeaa5d26fe5ea16df92b48d1ac45e01e3944ce1e6aa2a66f7f8894742b8c9d6e276e16cd2049a2b870 + languageName: node + linkType: hard + "p-locate@npm:^5.0.0": version: 5.0.0 resolution: "p-locate@npm:5.0.0" @@ -7480,6 +8043,13 @@ __metadata: languageName: node linkType: hard +"p-try@npm:^2.0.0": + version: 2.2.0 + resolution: "p-try@npm:2.2.0" + checksum: f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae + languageName: node + linkType: hard + "package-json-from-dist@npm:^1.0.0": version: 1.0.1 resolution: "package-json-from-dist@npm:1.0.1" @@ -7669,6 +8239,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^4.2.0": + version: 4.2.0 + resolution: "pkg-dir@npm:4.2.0" + dependencies: + find-up: ^4.0.0 + checksum: 9863e3f35132bf99ae1636d31ff1e1e3501251d480336edb1c211133c8d58906bed80f154a1d723652df1fda91e01c7442c2eeaf9dc83157c7ae89087e43c8d6 + languageName: node + linkType: hard + "possible-typed-array-names@npm:^1.0.0": version: 1.0.0 resolution: "possible-typed-array-names@npm:1.0.0" @@ -7775,6 +8354,13 @@ __metadata: languageName: node linkType: hard +"prettier-standalone@npm:^1.3.1-0": + version: 1.3.1-0 + resolution: "prettier-standalone@npm:1.3.1-0" + checksum: 5ae1f71878a4145ee1ce071573282016f0625c2bdabeddc8d41212975d7d7d29e33cc2daa6898e3ee0e7af055b48cdb13a53c5a5aae1d7b991ffb8e43e09391a + languageName: node + linkType: hard + "prettier@npm:^2.8.8": version: 2.8.8 resolution: "prettier@npm:2.8.8" @@ -7793,6 +8379,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^3.4.2": + version: 3.4.2 + resolution: "prettier@npm:3.4.2" + bin: + prettier: bin/prettier.cjs + checksum: 061c84513db62d3944c8dc8df36584dad82883ce4e49efcdbedd8703dce5b173c33fd9d2a4e1725d642a3b713c932b55418342eaa347479bc4a9cca114a04cd0 + languageName: node + linkType: hard + "pretty-format@npm:^27.0.2": version: 27.5.1 resolution: "pretty-format@npm:27.5.1" @@ -7897,6 +8492,15 @@ __metadata: languageName: node linkType: hard +"randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: ^5.1.0 + checksum: d779499376bd4cbb435ef3ab9a957006c8682f343f14089ed5f27764e4645114196e75b7f6abf1cbd84fd247c0cb0651698444df8c9bf30e62120fbbc52269d6 + languageName: node + linkType: hard + "raw-body@npm:2.4.1": version: 2.4.1 resolution: "raw-body@npm:2.4.1" @@ -8074,6 +8678,15 @@ __metadata: languageName: node linkType: hard +"rechoir@npm:^0.8.0": + version: 0.8.0 + resolution: "rechoir@npm:0.8.0" + dependencies: + resolve: ^1.20.0 + checksum: ad3caed8afdefbc33fbc30e6d22b86c35b3d51c2005546f4e79bcc03c074df804b3640ad18945e6bef9ed12caedc035655ec1082f64a5e94c849ff939dc0a788 + languageName: node + linkType: hard + "redeyed@npm:~2.1.0": version: 2.1.1 resolution: "redeyed@npm:2.1.1" @@ -8138,6 +8751,15 @@ __metadata: languageName: node linkType: hard +"resolve-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-cwd@npm:3.0.0" + dependencies: + resolve-from: ^5.0.0 + checksum: 546e0816012d65778e580ad62b29e975a642989108d9a3c5beabfb2304192fa3c9f9146fbdfe213563c6ff51975ae41bac1d3c6e047dd9572c94863a057b4d81 + languageName: node + linkType: hard + "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -8172,6 +8794,19 @@ __metadata: languageName: node linkType: hard +"resolve@npm:^1.20.0": + version: 1.22.10 + resolution: "resolve@npm:1.22.10" + dependencies: + is-core-module: ^2.16.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: ab7a32ff4046fcd7c6fdd525b24a7527847d03c3650c733b909b01b757f92eb23510afa9cc3e9bf3f26a3e073b48c88c706dfd4c1d2fb4a16a96b73b6328ddcf + languageName: node + linkType: hard + "resolve@npm:^2.0.0-next.5": version: 2.0.0-next.5 resolution: "resolve@npm:2.0.0-next.5" @@ -8198,6 +8833,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@^1.20.0#~builtin": + version: 1.22.10 + resolution: "resolve@patch:resolve@npm%3A1.22.10#~builtin::version=1.22.10&hash=07638b" + dependencies: + is-core-module: ^2.16.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 8aac1e4e4628bd00bf4b94b23de137dd3fe44097a8d528fd66db74484be929936e20c696e1a3edf4488f37e14180b73df6f600992baea3e089e8674291f16c9d + languageName: node + linkType: hard + "resolve@patch:resolve@^2.0.0-next.5#~builtin": version: 2.0.0-next.5 resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#~builtin::version=2.0.0-next.5&hash=07638b" @@ -8333,7 +8981,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 @@ -8376,6 +9024,29 @@ __metadata: languageName: node linkType: hard +"schema-utils@npm:^3.2.0": + version: 3.3.0 + resolution: "schema-utils@npm:3.3.0" + dependencies: + "@types/json-schema": ^7.0.8 + ajv: ^6.12.5 + ajv-keywords: ^3.5.2 + checksum: ea56971926fac2487f0757da939a871388891bc87c6a82220d125d587b388f1704788f3706e7f63a7b70e49fc2db974c41343528caea60444afd5ce0fe4b85c0 + languageName: node + linkType: hard + +"schema-utils@npm:^4.3.0": + version: 4.3.0 + resolution: "schema-utils@npm:4.3.0" + dependencies: + "@types/json-schema": ^7.0.9 + ajv: ^8.9.0 + ajv-formats: ^2.1.1 + ajv-keywords: ^5.1.0 + checksum: 3dbd9056727c871818eaf3cabeeb5c9e173ae2b17bbf2a9c7a2e49c220fa1a580e44df651c876aea3b4926cecf080730a39e28202cb63f2b68d99872b49cd37a + languageName: node + linkType: hard + "semver@npm:6.3.1, semver@npm:^6.0.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -8405,6 +9076,15 @@ __metadata: languageName: node linkType: hard +"serialize-javascript@npm:^6.0.2": + version: 6.0.2 + resolution: "serialize-javascript@npm:6.0.2" + dependencies: + randombytes: ^2.1.0 + checksum: c4839c6206c1d143c0f80763997a361310305751171dd95e4b57efee69b8f6edd8960a0b7fbfc45042aadff98b206d55428aee0dc276efe54f100899c7fa8ab7 + languageName: node + linkType: hard + "set-blocking@npm:^2.0.0": version: 2.0.0 resolution: "set-blocking@npm:2.0.0" @@ -8452,6 +9132,15 @@ __metadata: languageName: node linkType: hard +"shallow-clone@npm:^3.0.0": + version: 3.0.1 + resolution: "shallow-clone@npm:3.0.1" + dependencies: + kind-of: ^6.0.2 + checksum: 39b3dd9630a774aba288a680e7d2901f5c0eae7b8387fc5c8ea559918b29b3da144b7bdb990d7ccd9e11be05508ac9e459ce51d01fd65e583282f6ffafcba2e7 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -8575,6 +9264,23 @@ __metadata: languageName: node linkType: hard +"source-map-support@npm:~0.5.20": + version: 0.5.21 + resolution: "source-map-support@npm:0.5.21" + dependencies: + buffer-from: ^1.0.0 + source-map: ^0.6.0 + checksum: 43e98d700d79af1d36f859bdb7318e601dfc918c7ba2e98456118ebc4c4872b327773e5a1df09b0524e9e5063bb18f0934538eace60cca2710d1fa687645d137 + languageName: node + linkType: hard + +"source-map@npm:^0.6.0": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 + languageName: node + linkType: hard + "sprintf-js@npm:^1.1.3": version: 1.1.3 resolution: "sprintf-js@npm:1.1.3" @@ -8866,6 +9572,15 @@ __metadata: languageName: node linkType: hard +"supports-color@npm:^8.0.0": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: ^4.0.0 + checksum: c052193a7e43c6cdc741eb7f378df605636e01ad434badf7324f17fb60c69a880d8d8fcdcb562cf94c2350e57b937d7425ab5b8326c67c2adc48f7c87c1db406 + languageName: node + linkType: hard + "supports-preserve-symlinks-flag@npm:^1.0.0": version: 1.0.0 resolution: "supports-preserve-symlinks-flag@npm:1.0.0" @@ -8913,7 +9628,7 @@ __metadata: languageName: node linkType: hard -"tapable@npm:^2.2.0": +"tapable@npm:^2.1.1, tapable@npm:^2.2.0": version: 2.2.1 resolution: "tapable@npm:2.2.1" checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51 @@ -8949,6 +9664,42 @@ __metadata: languageName: node linkType: hard +"terser-webpack-plugin@npm:^5.3.10": + version: 5.3.11 + resolution: "terser-webpack-plugin@npm:5.3.11" + dependencies: + "@jridgewell/trace-mapping": ^0.3.25 + jest-worker: ^27.4.5 + schema-utils: ^4.3.0 + serialize-javascript: ^6.0.2 + terser: ^5.31.1 + peerDependencies: + webpack: ^5.1.0 + peerDependenciesMeta: + "@swc/core": + optional: true + esbuild: + optional: true + uglify-js: + optional: true + checksum: c84c005d4041ad2e2eed0c9059b52a50ffd27f1e2afca7d34864a2b4b2bb1295405bc7578eeb25bae732e358339954d8cb6fbf6d83df52e8aa9333e8bf409ebe + languageName: node + linkType: hard + +"terser@npm:^5.31.1": + version: 5.37.0 + resolution: "terser@npm:5.37.0" + dependencies: + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 + commander: ^2.20.0 + source-map-support: ~0.5.20 + bin: + terser: bin/terser + checksum: 70c06a8ce1288ff4370a7e481beb6fc8b22fc4995371479f49df1552aa9cf8e794ace66e1da6e87057eda1745644311213f5043bda9a06cf55421eff68b3ac06 + languageName: node + linkType: hard + "test-exclude@npm:^7.0.1": version: 7.0.1 resolution: "test-exclude@npm:7.0.1" @@ -9422,6 +10173,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.20.0": + version: 6.20.0 + resolution: "undici-types@npm:6.20.0" + checksum: b7bc50f012dc6afbcce56c9fd62d7e86b20a62ff21f12b7b5cbf1973b9578d90f22a9c7fe50e638e96905d33893bf2f9f16d98929c4673c2480de05c6c96ea8b + languageName: node + linkType: hard + "undici@npm:5.26.5": version: 5.26.5 resolution: "undici@npm:5.26.5" @@ -9753,6 +10511,16 @@ __metadata: languageName: node linkType: hard +"watchpack@npm:^2.4.1": + version: 2.4.2 + resolution: "watchpack@npm:2.4.2" + dependencies: + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.1.2 + checksum: 92d9d52ce3d16fd83ed6994d1dd66a4d146998882f4c362d37adfea9ab77748a5b4d1e0c65fa104797928b2d40f635efa8f9b925a6265428a69f1e1852ca3441 + languageName: node + linkType: hard + "web-vitals@npm:0.2.4": version: 0.2.4 resolution: "web-vitals@npm:0.2.4" @@ -9784,6 +10552,90 @@ __metadata: languageName: node linkType: hard +"webpack-cli@npm:^6.0.1": + version: 6.0.1 + resolution: "webpack-cli@npm:6.0.1" + dependencies: + "@discoveryjs/json-ext": ^0.6.1 + "@webpack-cli/configtest": ^3.0.1 + "@webpack-cli/info": ^3.0.1 + "@webpack-cli/serve": ^3.0.1 + colorette: ^2.0.14 + commander: ^12.1.0 + cross-spawn: ^7.0.3 + envinfo: ^7.14.0 + fastest-levenshtein: ^1.0.12 + import-local: ^3.0.2 + interpret: ^3.1.1 + rechoir: ^0.8.0 + webpack-merge: ^6.0.1 + peerDependencies: + webpack: ^5.82.0 + peerDependenciesMeta: + webpack-bundle-analyzer: + optional: true + webpack-dev-server: + optional: true + bin: + webpack-cli: ./bin/cli.js + checksum: 1418d0e48c58b4a223472d1a34aee74b497cd8b8fc7f0508da86983e6bbc0b2f20e85459d89fb7169309a6f0409e3a27c1b688e645fa705806195884855434fc + languageName: node + linkType: hard + +"webpack-merge@npm:^6.0.1": + version: 6.0.1 + resolution: "webpack-merge@npm:6.0.1" + dependencies: + clone-deep: ^4.0.1 + flat: ^5.0.2 + wildcard: ^2.0.1 + checksum: e8a604c686b944605a1c57cc7b75e886ab902dc5ffdd15259a092c5c2dd5f58868fe39f995ea4bad4f189e38843b061c4ae1eb22822d7169813f4adab571dc3d + languageName: node + linkType: hard + +"webpack-sources@npm:^3.2.3": + version: 3.2.3 + resolution: "webpack-sources@npm:3.2.3" + checksum: 989e401b9fe3536529e2a99dac8c1bdc50e3a0a2c8669cbafad31271eadd994bc9405f88a3039cd2e29db5e6d9d0926ceb7a1a4e7409ece021fe79c37d9c4607 + languageName: node + linkType: hard + +"webpack@npm:^5.97.1": + version: 5.97.1 + resolution: "webpack@npm:5.97.1" + dependencies: + "@types/eslint-scope": ^3.7.7 + "@types/estree": ^1.0.6 + "@webassemblyjs/ast": ^1.14.1 + "@webassemblyjs/wasm-edit": ^1.14.1 + "@webassemblyjs/wasm-parser": ^1.14.1 + acorn: ^8.14.0 + browserslist: ^4.24.0 + chrome-trace-event: ^1.0.2 + enhanced-resolve: ^5.17.1 + es-module-lexer: ^1.2.1 + eslint-scope: 5.1.1 + events: ^3.2.0 + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.2.11 + json-parse-even-better-errors: ^2.3.1 + loader-runner: ^4.2.0 + mime-types: ^2.1.27 + neo-async: ^2.6.2 + schema-utils: ^3.2.0 + tapable: ^2.1.1 + terser-webpack-plugin: ^5.3.10 + watchpack: ^2.4.1 + webpack-sources: ^3.2.3 + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: 649065e2258b495ae41a4088be804b4be2ec07d280aa514ebef43da79caf96fa973d26a08826c3902b5676a098d9b37c589f16be7b4da17b68b08b6c76441196 + languageName: node + linkType: hard + "whatwg-encoding@npm:^3.1.1": version: 3.1.1 resolution: "whatwg-encoding@npm:3.1.1" @@ -9928,6 +10780,13 @@ __metadata: languageName: node linkType: hard +"wildcard@npm:^2.0.1": + version: 2.0.1 + resolution: "wildcard@npm:2.0.1" + checksum: e0c60a12a219e4b12065d1199802d81c27b841ed6ad6d9d28240980c73ceec6f856771d575af367cbec2982d9ae7838759168b551776577f155044f5a5ba843c + languageName: node + linkType: hard + "word-wrap@npm:^1.2.5": version: 1.2.5 resolution: "word-wrap@npm:1.2.5"