diff --git a/.env.example b/.env.example index 1340f397..098a5a85 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,41 @@ NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=50db9e195634356bb8ab0375a9f07607 +NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP= +NEXT_PUBLIC_ALCHEMY_ETHEREUM_KEY= NEXT_PUBLIC_ALCHEMY_SEPOLIA_HTTP= NEXT_PUBLIC_ALCHEMY_SEPOLIA_KEY= +NEXT_PUBLIC_ALCHEMY_POLYGON_HTTP= +NEXT_PUBLIC_ALCHEMY_POLYGON_KEY= NEXT_PUBLIC_ALCHEMY_MUMBAI_HTTP= NEXT_PUBLIC_ALCHEMY_MUMBAI_KEY= -NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP= +NEXT_PUBLIC_ALCHEMY_OPTIMISM_HTTP= +NEXT_PUBLIC_ALCHEMY_OPTIMISM_KEY= +NEXT_PUBLIC_ALCHEMY_OPGOERLI_HTTP= +NEXT_PUBLIC_ALCHEMY_OPGOERLI_KEY= +NEXT_PUBLIC_ALCHEMY_OPSEPOLIA_HTTP= +NEXT_PUBLIC_ALCHEMY_OPSEPOLIA_KEY= +NEXT_PUBLIC_ALCHEMY_AVALANCHE_HTTP= +NEXT_PUBLIC_ALCHEMY_AVALANCHE_KEY= +NEXT_PUBLIC_ALCHEMY_FUJI_HTTP= +NEXT_PUBLIC_ALCHEMY_FUJI_KEY= +NEXT_PUBLIC_ALCHEMY_BASE_HTTP= +NEXT_PUBLIC_ALCHEMY_BASE_KEY= +NEXT_PUBLIC_ALCHEMY_BASEGOERLI_HTTP= +NEXT_PUBLIC_ALCHEMY_BASEGOERLI_KEY= +NEXT_PUBLIC_ALCHEMY_BNBTESTNET_HTTP= +NEXT_PUBLIC_ALCHEMY_BNBTESTNET_KEY= +NEXT_PUBLIC_ALCHEMY_ARBITRUMONE_HTTP= +NEXT_PUBLIC_ALCHEMY_ARBITRUMONE_KEY= +NEXT_PUBLIC_ALCHEMY_ARBITRUMSEPOLIA_HTTP= +NEXT_PUBLIC_ALCHEMY_ARBITRUMSEPOLIA_KEY= + +# Subgraph endpoint production query + +# ENDPOINT_URL=https://gateway.testnet.thegraph.com/api/[api-key]/subgraphs/id/EynHJVht9r6xhaZEPCyLYLd4EqBq8msf4jTrw1Vwg8ZV + + +# Subgraph endpoint production query + +NEXT_PUBLIC_ENDPOINT_URL=https://api.studio.thegraph.com/query/57887/swaplace-subgraph-sepolia/version/latest + +NEXT_PUBLIC_SUBGRAPH_AUTH_KEY=3b2048f02febad918a35bbafe78b2115 +NEXT_PUBLIC_PONDER_ENDPOINT="" \ No newline at end of file diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index 40c7174d..b2bb4788 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -11,12 +11,12 @@ name: ESLint on: push: - branches: [ "main" ] + branches: ["main"] pull_request: # The branches below must be a subset of the branches above - branches: [ "main" ] + branches: ["main"] schedule: - - cron: '16 6 * * 3' + - cron: "16 6 * * 3" jobs: eslint: diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 00000000..98e57f6f --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,5 @@ +trailingComma: "all" +singleQuote: false +printWidth: 80 +tabWidth: 2 +semi: true diff --git a/CODEOWNERS b/CODEOWNERS index b0269319..b0c0ffc7 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,3 +1,3 @@ # Default owners for everything in the repo -* @FrancoAguzzi @heronlancellot @eduramme +- @FrancoAguzzi @heronlancellot @eduramme @0xneves diff --git a/components/01-atoms/ApprovedTokenCards.tsx b/components/01-atoms/ApprovedTokenCards.tsx new file mode 100644 index 00000000..43d2f078 --- /dev/null +++ b/components/01-atoms/ApprovedTokenCards.tsx @@ -0,0 +1,46 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { ApproveTokenCard } from "@/components/03-organisms"; +import { SwapContext } from "@/components/01-atoms"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { Token } from "@/lib/shared/types"; +import { useContext, useEffect, useState } from "react"; + +export const ApprovedTokenCards = () => { + const { authenticatedUserAddress } = useAuthenticatedUser(); + const [tokensApprovedForSwap, setTokensApprovedForSwap] = useState( + [], + ); + + const { authenticatedUserTokensList, setApprovedTokensCount } = + useContext(SwapContext); + + useEffect(() => { + setApprovedTokensCount(0); + }, [authenticatedUserTokensList]); + + if (!authenticatedUserAddress?.address) { + return null; + } + + const addNewTokenToApprovedList = (token: Token) => { + if (!tokensApprovedForSwap.includes(token)) { + const approvedTokensCount = tokensApprovedForSwap.length + 1; + setTokensApprovedForSwap([...tokensApprovedForSwap, token]); + setApprovedTokensCount(approvedTokensCount); + } + }; + + return ( +
+
+ {authenticatedUserTokensList.map((token, index) => ( + + ))} +
+
+ ); +}; diff --git a/components/01-atoms/ConfirmSwapModal.tsx b/components/01-atoms/ConfirmSwapModal.tsx deleted file mode 100644 index 5a488d14..00000000 --- a/components/01-atoms/ConfirmSwapModal.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import { - NftCard, - NftCardActionType, - SwapContext, - SwapIcon, - TransactionResultModal, -} from "."; -import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { SWAPLACE_SMART_CONTRACT_ADDRESS } from "@/lib/client/constants"; -import { Dialog, Transition } from "@headlessui/react"; -import { Fragment, useContext, useEffect, useState } from "react"; -import { useNetwork, useWalletClient } from "wagmi"; -import toast from "react-hot-toast"; - -interface ConfirmSwapModalProps { - open: boolean; - onClose: () => void; -} - -enum CreateOfferStatus { - "CREATE_OFFER" = "CREATE_OFFER", - "WAITING_WALLET_APPROVAL" = "WAITING_WALLET_APPROVAL", -} - -export enum TransactionResult { - "LOADING" = "LOADING", - "SUCCESS" = "SUCCESS", - "FAILURE" = "FAILURE", -} - -export const ConfirmSwapModal = ({ open, onClose }: ConfirmSwapModalProps) => { - const { authenticatedUserAddress } = useAuthenticatedUser(); - const { nftInputUser, nftAuthUser, validatedAddressToSwap } = - useContext(SwapContext); - - const [createOfferStatus, setCreateOfferStatus] = useState( - CreateOfferStatus.CREATE_OFFER - ); - const [transactionResult, displayTransactionResultModal] = - useState(null); - - const { chain } = useNetwork(); - const { data: walletClient } = useWalletClient(); - - useEffect(() => { - if (!open) { - setCreateOfferStatus(CreateOfferStatus.CREATE_OFFER); - } - }, [open]); - - if (!authenticatedUserAddress?.address || !nftInputUser || !nftAuthUser) { - onClose(); - return null; - } - - const createOffer = async () => { - const swaplaceContractForCurrentChain = - chain && SWAPLACE_SMART_CONTRACT_ADDRESS[chain?.id]; - - if (swaplaceContractForCurrentChain && walletClient) { - // const farFarInTheFuture = getTimestamp(chain.id); - - setCreateOfferStatus(CreateOfferStatus.WAITING_WALLET_APPROVAL); - walletClient - .signMessage({ - message: "Swaplace dApps wants to create a Swap Offer!", - }) - .then(() => { - setCreateOfferStatus(CreateOfferStatus.CREATE_OFFER); - displayTransactionResultModal(TransactionResult.LOADING); - setTimeout(() => { - displayTransactionResultModal(TransactionResult.SUCCESS); - }, 10000); - }) - .catch((error) => { - toast.error("Message signature failed"); - setCreateOfferStatus(CreateOfferStatus.CREATE_OFFER); - displayTransactionResultModal(TransactionResult.FAILURE); - console.error(error); - }); - - // makeSwap( - // swaplaceContractForCurrentChain, - // authenticatedUserAddress.address, - // validatedAddressToSwap, - // destinyChain, - // farFarInTheFuture, - // nftAuthUser, - // nftInputUser, - // chain.id - // ) - // .then((data) => { - // console.log("data", data); - // }) - // .catch((error) => { - // console.log("error", error); - // }); - } else { - throw new Error( - "Could not find a Swaplace contract for the current chain" - ); - } - }; - - return ( - <> - -
- - - - - - Confirm Swap Offer creation - - - Please confirm the data below is correct: - -
-
-
You are offering
-
- -
-
- -
-
You are asking for
-
- -
-
-
- - Tip: you can click on the NFT card
to copy its metadata to - your clipboard! -
- - - Are you sure you want to create this Swap Offer? - - -
-
-
- - - - ); -}; diff --git a/components/01-atoms/ConnectWallet.tsx b/components/01-atoms/ConnectWallet.tsx index 4be484ff..77944f21 100644 --- a/components/01-atoms/ConnectWallet.tsx +++ b/components/01-atoms/ConnectWallet.tsx @@ -1,11 +1,13 @@ +import { WalletIcon } from "@/components/01-atoms"; import { ConnectButton } from "@rainbow-me/rainbowkit"; import { useRouter } from "next/router"; interface IConnectWallet { customStyle?: string; + walletIcon?: boolean; } -export const ConnectWallet = ({ customStyle }: IConnectWallet) => { +export const ConnectWallet = ({ customStyle, walletIcon }: IConnectWallet) => { const router = useRouter(); return ( @@ -44,10 +46,10 @@ export const ConnectWallet = ({ customStyle }: IConnectWallet) => { return ( ); } @@ -65,7 +67,7 @@ export const ConnectWallet = ({ customStyle }: IConnectWallet) => {
+ ); +}; diff --git a/components/01-atoms/ENSAvatar.tsx b/components/01-atoms/ENSAvatar.tsx new file mode 100644 index 00000000..bc54eeac --- /dev/null +++ b/components/01-atoms/ENSAvatar.tsx @@ -0,0 +1,76 @@ +import { LoadingIndicator } from "@/components/01-atoms"; +import { + ENSAvatarQueryStatus, + useEnsData, +} from "@/lib/client/hooks/useENSData"; +import { EthereumAddress } from "@/lib/shared/types"; +import BoringAvatar from "boring-avatars"; +import cc from "classcat"; + +export enum ENSAvatarSize { + SMALL = "small", + MEDIUM = "medium", +} + +const ENSAvatarClassName = { + [ENSAvatarSize.SMALL]: "ens-avatar-small", + [ENSAvatarSize.MEDIUM]: "ens-avatar-medium", +}; + +interface ENSAvatarProps { + avatarENSAddress: EthereumAddress; + size?: ENSAvatarSize; +} + +export const ENSAvatar = ({ + avatarENSAddress, + size = ENSAvatarSize.MEDIUM, +}: ENSAvatarProps) => { + const { avatarQueryStatus, avatarSrc } = useEnsData({ + ensAddress: avatarENSAddress, + }); + + return ( +
+ {avatarQueryStatus === ENSAvatarQueryStatus.LOADING ? ( +
+ +
+ ) : avatarQueryStatus === ENSAvatarQueryStatus.ERROR ? ( +
+ +
+ ) : /* + Below condition will always be true since we only have 3 possible values + for avatarQueryStatus, being the third one ENSAvatarQueryStatus.SUCCESS: + + When the query is successful, avatarSrc will be defined + */ + avatarSrc ? ( + {`ENS + ) : null} +
+ ); +}; diff --git a/components/01-atoms/LoadingIndicator.tsx b/components/01-atoms/LoadingIndicator.tsx index 1107a5db..8c1da6b7 100644 --- a/components/01-atoms/LoadingIndicator.tsx +++ b/components/01-atoms/LoadingIndicator.tsx @@ -1,7 +1,5 @@ -import React from "react"; +import React, { HTMLProps } from "react"; -const LoadingIndicator = () => ( -
+export const LoadingIndicator = (props: HTMLProps) => ( +
); - -export default LoadingIndicator; diff --git a/components/01-atoms/NetworkDropdown.tsx b/components/01-atoms/NetworkDropdown.tsx new file mode 100644 index 00000000..3ae599b1 --- /dev/null +++ b/components/01-atoms/NetworkDropdown.tsx @@ -0,0 +1,188 @@ +import { + ArrowIcon, + ArrowIconVariant, + NetworkIcon, + NetworkVariants, +} from "@/components/01-atoms"; +import { SupportedNetworks } from "@/lib/client/constants"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { useSupportedNetworks } from "@/lib/client/hooks/useSupportedNetworks"; +import { capitalizeFirstLetterPrhases } from "@/lib/client/utils"; +import React, { useEffect, useState } from "react"; +import { useSwitchNetwork, sepolia, useNetwork } from "wagmi"; +import cc from "classcat"; + +interface NetworkDropdownProps { + forAuthedUser: boolean; +} +export const NetworkDropdown = ({ forAuthedUser }: NetworkDropdownProps) => { + const [isOpen, setIsOpen] = useState(false); + const [networkText, setNetworkText] = useState("default"); + const { switchNetwork, isSuccess } = useSwitchNetwork(); + const { isNetworkSupported } = useSupportedNetworks(); + const { authenticatedUserAddress } = useAuthenticatedUser(); + const { chain } = useNetwork(); + + useEffect(() => { + if (!isNetworkSupported) { + setNetworkText("default"); + } else { + setNetworkText(SupportedNetworks.SEPOLIA); + } + }, [authenticatedUserAddress, isNetworkSupported, chain]); + + const handleToggleDropdown = () => { + setIsOpen(!isOpen); + }; + + const handleDropdownItemClick = (networkName: NetworkVariants) => { + if (networkName === SupportedNetworks.SEPOLIA) { + switchNetwork && switchNetwork(sepolia.id); + isSuccess && setNetworkText(networkName); + } + setIsOpen(false); + }; + + interface NetworkProps { + icon: React.JSX.Element; + name: string; + } + + /** + * This constant represents a collection of network icons and their corresponding names. + * It facilitates the automatic rendering of network icons and names in a select component. + * + * For now only SEPOLIA available + * Each entry consists of a network icon component and its associated name. + */ + const NetworkInfo: Partial> = { + [SupportedNetworks.SEPOLIA]: { + icon: ( + + ), + name: SupportedNetworks.SEPOLIA, + }, + // [SupportedNetworks.OPTIMISM]: { + // icon: ( + // + // ), + // name: SupportedNetworks.OPTIMISM, + // }, + // [SupportedNetworks.MUMBAI]: { + // icon: ( + // + // ), + // name: SupportedNetworks.MUMBAI, + // }, + // [SupportedNetworks.FUJI]: { + // icon: ( + // + // ), + // name: SupportedNetworks.FUJI, + // }, + // [SupportedNetworks.BNB]: { + // icon: ( + // + // ), + // name: SupportedNetworks.BNB, + // }, + // [SupportedNetworks.BASEGOERLI]: { + // icon: ( + // + // ), + // name: SupportedNetworks.BASEGOERLI, + // }, + // [SupportedNetworks.ARBITRUMSEPOLIA]: { + // icon: ( + // + // ), + // name: SupportedNetworks.ARBITRUMSEPOLIA, + // }, + }; + + return ( +
+
+
+
+
+
+ +
+
+ {networkText === "default" + ? forAuthedUser + ? "Your network" + : "Their network" + : capitalizeFirstLetterPrhases(networkText)} +
+
+
+ +
+
+
+ {isOpen && ( +
+
+ {Object.values(NetworkInfo).map((network, index) => ( +
+ handleDropdownItemClick(network.name as NetworkVariants) + } + className="gap-2 flex px-4 py-2 p-small-variant-black-2 dark:p-small-dark-variant-grey items-center" + > + + {capitalizeFirstLetterPrhases(network.name)} +
+ ))} +
+
+ )} +
+
+ ); +}; diff --git a/components/01-atoms/OfferExpiryConfirmSwap.tsx b/components/01-atoms/OfferExpiryConfirmSwap.tsx new file mode 100644 index 00000000..5e3bdc91 --- /dev/null +++ b/components/01-atoms/OfferExpiryConfirmSwap.tsx @@ -0,0 +1,24 @@ +interface OfferExpiryConfirmSwapProps { + expireTime: string; +} + +export const OfferExpiryConfirmSwap = ({ + expireTime +}: OfferExpiryConfirmSwapProps) => { + return ( + <> +
+

+ Offer expires in +

+

+ {expireTime} +

+
+ + ); +}; diff --git a/components/01-atoms/OfferTag.tsx b/components/01-atoms/OfferTag.tsx new file mode 100644 index 00000000..7e1f2783 --- /dev/null +++ b/components/01-atoms/OfferTag.tsx @@ -0,0 +1,32 @@ +export const OfferTag = () => { + enum TAG { + PEDING = "PENDING", + ACCEPTED = "ACCEPTED", + CANCELED = "CANCELED", + EXPIRED = "EXPIRED", + } + interface TagConfig { + body: React.ReactNode; + } + + const Tags: Record = { + [TAG.ACCEPTED]: { + body:
{TAG.ACCEPTED}
, + }, + [TAG.CANCELED]: { + body:
{TAG.CANCELED}
, + }, + [TAG.EXPIRED]: { + body:
{TAG.EXPIRED}
, + }, + [TAG.PEDING]: { + body:
{TAG.PEDING}
, + }, + }; + + return ( +
+ {Tags[TAG.PEDING].body} +
+ ); +}; diff --git a/components/01-atoms/ProgressBar.tsx b/components/01-atoms/ProgressBar.tsx new file mode 100644 index 00000000..40ad186e --- /dev/null +++ b/components/01-atoms/ProgressBar.tsx @@ -0,0 +1,32 @@ +import cc from "classcat"; + +interface ProgressBarProps { + currentStep: number; + numberOfItems: number; +} + +export const ProgressBar = ({ + currentStep, + numberOfItems, +}: ProgressBarProps) => { + return ( +
+ {Array(numberOfItems) + .fill(0) + .map((_, index) => { + return ( +
index, + "bg-[#353836]": currentStep <= index, + }, + ])} + /> + ); + })} +
+ ); +}; diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index 6b2b3171..8fad0a67 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -1,139 +1,103 @@ +/* eslint-disable import/no-named-as-default */ /* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable import/no-named-as-default-member */ -/* eslint-disable import/no-named-as-default */ -import { - MagnifyingGlassIcon, - SelectAuthedUserChain, - SelectDestinyChain, - SwapContext, -} from "."; +import { MagnifyingGlassIcon, SwapContext } from "@/components/01-atoms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { useContext, useEffect, useState } from "react"; +import { useContext, useEffect } from "react"; import { ENS } from "web3-eth-ens"; import cc from "classcat"; import Web3 from "web3"; +import toast from "react-hot-toast"; export const SearchBar = () => { const { setInputAddress, inputAddress, validateAddressToSwap, - userJustValidatedInput, + setUserJustValidatedInput, } = useContext(SwapContext); const { authenticatedUserAddress } = useAuthenticatedUser(); - const [validateAfterENSaddressLoads, setValidateAfterENSaddressLoads] = - useState(false); - const validateInput = () => { - if (authenticatedUserAddress) { - if (loadingENSaddress) { - setValidateAfterENSaddressLoads(true); - } else { - validateAddressToSwap(authenticatedUserAddress, ensNameAddress); - } - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars + + const validateUser = (ensNameAddress: string | null) => { + validateAddressToSwap(authenticatedUserAddress, ensNameAddress); }; - const [ensNameAddress, setEnsNameAddress] = useState(""); - const [loadingENSaddress, setLoadingENSaddress] = useState(false); - useEffect(() => { - if (inputAddress) { + const getUserAddress = async () => { + if (inputAddress && authenticatedUserAddress) { if (!process.env.NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP) { throw new Error( - "Cannot get ENS address without Alchemy Ethereum Mainnet API key" + "Cannot get ENS address without Alchemy Ethereum Mainnet API key", ); } const provider = new Web3.providers.HttpProvider( - process.env.NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP + process.env.NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP, ); const ens = new ENS(undefined, provider); - ens - .getOwner( - inputAddress.toLowerCase().includes(".") - ? inputAddress.toLowerCase().includes(".eth") - ? inputAddress.split(".")[1].length >= 3 - ? inputAddress - : `${inputAddress.split(".")[0]}.eth` - : inputAddress.split(".")[1].length >= 3 - ? inputAddress - : `${inputAddress.split(".")[0]}.eth` - : `${inputAddress}.eth` - ) - .then((address: unknown) => { - if (typeof address == "string") { - setEnsNameAddress(address); - setLoadingENSaddress(false); - } else { - setEnsNameAddress(""); - setLoadingENSaddress(false); - } - }) - .catch(() => { - setEnsNameAddress(""); - setLoadingENSaddress(false); - }); + const formattedAddress = inputAddress.toLowerCase().includes(".") + ? inputAddress.toLowerCase().includes(".eth") + ? inputAddress.split(".")[1].length >= 3 + ? inputAddress + : `${inputAddress.split(".")[0]}.eth` + : inputAddress.split(".")[1].length >= 3 + ? inputAddress + : `${inputAddress.split(".")[0]}.eth` + : `${inputAddress}.eth`; + + try { + const address: unknown = await ens.getOwner(formattedAddress); + + if (typeof address !== "string") return; + validateUser(address); + } catch (e) { + console.error(e); + } finally { + setUserJustValidatedInput(true); + } + } else if (inputAddress && !authenticatedUserAddress) { + toast.error("Cannot get ENS address without connect your wallet"); } - }, [inputAddress]); + }; useEffect(() => { - if (!loadingENSaddress && validateAfterENSaddressLoads) { - validateInput(); - setValidateAfterENSaddressLoads(false); - } - }, [loadingENSaddress]); + const requestDelay = setTimeout(() => { + setUserJustValidatedInput(false); + getUserAddress(); + }, 1500); + return () => clearTimeout(requestDelay); + }, [inputAddress]); return ( -
+
-

Who are you swapping with today?

+

+ Who are you swapping with today? +

-
+
+
+ +
setInputAddress(e.target.value)} + placeholder="Search username, address or ENS" + onChange={({ target }) => setInputAddress(target.value)} /> -
-
- -
-
-
- -
-
-

Your network:

- -
-
-

Searched address network:

-
- -
-
); diff --git a/components/01-atoms/SearchItemsShelf.tsx b/components/01-atoms/SearchItemsShelf.tsx new file mode 100644 index 00000000..20a11104 --- /dev/null +++ b/components/01-atoms/SearchItemsShelf.tsx @@ -0,0 +1,31 @@ +import { MagnifyingGlassIcon } from "@/components/01-atoms"; +import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; +import { useTheme } from "next-themes"; +import cc from "classcat"; + +export const SearchItemsShelf = () => { + const { theme } = useTheme(); + const { isMobile } = useScreenSize(); + + return ( +
+ +
+ +
+
+ ); +}; diff --git a/components/01-atoms/SelectAuthedUserChain.tsx b/components/01-atoms/SelectAuthedUserChain.tsx index 8a8a9250..fc36125b 100644 --- a/components/01-atoms/SelectAuthedUserChain.tsx +++ b/components/01-atoms/SelectAuthedUserChain.tsx @@ -49,7 +49,7 @@ export const SelectAuthedUserChain = () => {
+ ); +} diff --git a/components/01-atoms/SwapModalLayout.tsx b/components/01-atoms/SwapModalLayout.tsx new file mode 100644 index 00000000..31e42577 --- /dev/null +++ b/components/01-atoms/SwapModalLayout.tsx @@ -0,0 +1,97 @@ +import { CloseCTA } from "@/components/01-atoms"; +import { Transition, Dialog } from "@headlessui/react"; +import React, { Fragment } from "react"; + +interface ConfirmSwapModalToggle { + open: boolean; + onClose: () => void; +} + +interface ConfirmSwapModalText { + title: string; + description?: string; +} + +interface ISwapModalLayout { + toggleCloseButton: ConfirmSwapModalToggle; + text: ConfirmSwapModalText; + body: React.ReactNode; + footer?: React.ReactNode; +} + +export const SwapModalLayout = ({ + toggleCloseButton, + text, + body, + footer, +}: ISwapModalLayout) => { + return ( + <> + +
+ + + + +
+ +

+ {text.title} +

+
+ +
+
+
+ +
+ {text.description && ( +
+ {text.description} +
+ )} + + {body} +
+ + {footer && ( +
+ {footer} +
+ )} +
+
+
+ + ); +}; diff --git a/components/01-atoms/SwappingIcons.tsx b/components/01-atoms/SwappingIcons.tsx new file mode 100644 index 00000000..7d89a681 --- /dev/null +++ b/components/01-atoms/SwappingIcons.tsx @@ -0,0 +1,154 @@ +import { + ChatIcon, + NotificationsIcon, + OffersIcon, + SwappingIcon, + Tooltip, +} from "@/components/01-atoms"; +import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; +import { useTheme } from "next-themes"; +import { NextRouter, useRouter } from "next/router"; +import { SVGProps, useState } from "react"; +import cc from "classcat"; + +export interface IconSwap { + id: number; + name: string; + href: string; + icon: (props: SVGProps) => JSX.Element; + disabled?: boolean; +} + +export enum SwappingIconsID { + "SWAPLACE_STATION", + "OFFERS", + "CHAT", + "NOTIFICATIONS", +} + +const findInitialActiveTab = ( + swappingTabs: Array, + router: NextRouter, +) => { + const matchingTab = swappingTabs.find((tab) => router.pathname === tab.href); + return matchingTab ? matchingTab.id : SwappingIconsID.SWAPLACE_STATION; +}; + +export const SwappingIcons = () => { + const { theme } = useTheme(); + const { isWideScreen } = useScreenSize(); + + const swappingTabs: Array = [ + { + id: SwappingIconsID.SWAPLACE_STATION, + name: "Swaplace Station", + href: "/", + icon: SwappingIcon, + }, + { + id: SwappingIconsID.OFFERS, + name: "Offers", + href: "/offers", + icon: OffersIcon, + }, + { + id: SwappingIconsID.CHAT, + name: "Chat", + href: "/", + icon: ChatIcon, + disabled: true, + }, + { + id: SwappingIconsID.NOTIFICATIONS, + name: "Notifications", + href: "/", + icon: NotificationsIcon, + disabled: true, + }, + ]; + + const router = useRouter(); + + const [activeTab, setActiveTab] = useState( + findInitialActiveTab(swappingTabs, router), + ); + + const handleClick = async (e: IconSwap) => { + setActiveTab(e.id); + router.push(e.href); + }; + + return ( + <> + {swappingTabs.map((swappingTab) => { + const IconComponent = swappingTab.icon; + const isSelected = activeTab == swappingTab.id; + const isDisabled = swappingTab.disabled; + + return ( +
+ {isWideScreen ? ( + +
{ + !isDisabled && handleClick(swappingTab); + }} + > +
+ +
+
+
+ ) : ( + +
{ + handleClick(swappingTab); + }} + > +
+ +
+
+
+ )} +
+ ); + })} + + ); +}; diff --git a/components/01-atoms/ThreeDotsCardOffersOptions.tsx b/components/01-atoms/ThreeDotsCardOffersOptions.tsx new file mode 100644 index 00000000..3e62d9bf --- /dev/null +++ b/components/01-atoms/ThreeDotsCardOffersOptions.tsx @@ -0,0 +1,56 @@ +import { ShareIcon, ThreeDotsIcon, XMarkIcon } from "@/components/01-atoms"; +import { useState } from "react"; +import cc from "classcat"; + +export const ThreeDotsCardOffersOptions = () => { + const [isOpen, setIsOpen] = useState(false); + + const toggleDropdown = () => { + setIsOpen(!isOpen); + }; + + return ( +
+
+
+ +
+ + {isOpen && ( +
+
+ + +
+
+ )} +
+
+ ); +}; diff --git a/components/01-atoms/TokenCardProperties.tsx b/components/01-atoms/TokenCardProperties.tsx new file mode 100644 index 00000000..f0ab9ce8 --- /dev/null +++ b/components/01-atoms/TokenCardProperties.tsx @@ -0,0 +1,28 @@ +interface PropertiesInfo { + amount: number; + value: number; +} + +interface TokenCardPropertiesProps { + properties: PropertiesInfo; +} + +export const TokenCardProperties = ({ + properties, +}: TokenCardPropertiesProps) => { + return ( +
+
+
{properties.amount} item(s)
+
+

+ {properties.value} ETH +

+

+   (${properties.value}) +

+
+
+
+ ); +}; diff --git a/components/01-atoms/TokenCardsPlaceholder.tsx b/components/01-atoms/TokenCardsPlaceholder.tsx new file mode 100644 index 00000000..c1862e03 --- /dev/null +++ b/components/01-atoms/TokenCardsPlaceholder.tsx @@ -0,0 +1,58 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { + TokenCardStyleType, + TokenSizeClassNames, +} from "@/components/02-molecules"; +import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; + +interface TokenCardsPlaceholderProps { + totalCardsLength: number; + wideScreenTotalSquares?: number; + desktopTotalSquares?: number; + tabletTotalSquares?: number; + mobileTotalSquares?: number; + styleType?: TokenCardStyleType; +} + +export const TokenCardsPlaceholder = ({ + totalCardsLength, + wideScreenTotalSquares = 24, + desktopTotalSquares = 24, + tabletTotalSquares = 24, + mobileTotalSquares = 15, + styleType = TokenCardStyleType.MEDIUM, +}: TokenCardsPlaceholderProps) => { + const { isDesktop, isTablet, isWideScreen, isMobile } = useScreenSize(); + + let totalSquares = 0; + let totalSquaresX = 0; // Token quantity in X axis + + // We are getting X count as the LCM to fill the rows with empty cards correctly. + isMobile + ? ((totalSquares = mobileTotalSquares), + mobileTotalSquares == 5 ? (totalSquaresX = 5) : (totalSquaresX = 3)) + : isWideScreen + ? ((totalSquares = wideScreenTotalSquares), + wideScreenTotalSquares == 10 ? (totalSquaresX = 5) : (totalSquaresX = 6)) + : isDesktop + ? ((totalSquares = desktopTotalSquares), + desktopTotalSquares == 8 ? (totalSquaresX = 4) : (totalSquaresX = 6)) + : isTablet && + ((totalSquares = tabletTotalSquares), + tabletTotalSquares == 10 ? (totalSquaresX = 5) : (totalSquaresX = 6)); + + const spareTokensX = totalCardsLength % totalSquaresX; + const emptySquaresCountX = spareTokensX ? totalSquaresX - spareTokensX : 0; + + const spareTokens = totalSquares - totalCardsLength; + const emptySquaresCount = + emptySquaresCountX < spareTokens + ? Math.max(spareTokens, 0) + : emptySquaresCountX; + + return Array.from({ length: emptySquaresCount }, (_, index) => ( + <> +
+ + )); +}; diff --git a/components/01-atoms/TokenOfferDetails.tsx b/components/01-atoms/TokenOfferDetails.tsx new file mode 100644 index 00000000..ba03ab4a --- /dev/null +++ b/components/01-atoms/TokenOfferDetails.tsx @@ -0,0 +1,37 @@ +import { + DoneIcon, + OfferTag, + ThreeDotsCardOffersOptions, +} from "@/components/01-atoms"; +import React from "react"; + +export const TokenOfferDetails = () => ( +
+
+
    + +
  • +
    + Expires on 16 Oct, 2023 +
  • +
  • +
    + Created by you +
  • +
+
+
+
+ +
+ + +
+
+); diff --git a/components/01-atoms/TokensOfferSkeleton.tsx b/components/01-atoms/TokensOfferSkeleton.tsx new file mode 100644 index 00000000..77bddce9 --- /dev/null +++ b/components/01-atoms/TokensOfferSkeleton.tsx @@ -0,0 +1,54 @@ +import React from "react"; + +export const TokensOfferSkeleton = () => { + const TokenCardSkeleton = () => { + return ( +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ); + }; + + const TokenOfferDetailsSkeleton = () => { + return ( +
+
+
+
+
+
+
+
+
+
+
+ ); + }; + + return ( +
+
+
+ +
+
+ +
+
+ +
+ ); +}; diff --git a/components/01-atoms/Tab.tsx b/components/01-atoms/TokensShelfTab.tsx similarity index 58% rename from components/01-atoms/Tab.tsx rename to components/01-atoms/TokensShelfTab.tsx index 499431c8..7c9538ef 100644 --- a/components/01-atoms/Tab.tsx +++ b/components/01-atoms/TokensShelfTab.tsx @@ -5,7 +5,7 @@ interface ITab { setActiveSwappingShelfID: (_: SwappingShelfID) => void; } -interface Tab { +interface TokensShelfTab { id: number; name: string; } @@ -15,29 +15,31 @@ export enum SwappingShelfID { "YOUR_ITEMS", } -export const swappingTabs: Array = [ +export const swappingTabs: Array = [ { id: SwappingShelfID.THEIR_ITEMS, - name: "Their Items", + name: "Their items", }, { id: SwappingShelfID.YOUR_ITEMS, - name: "Your Items", + name: "Your items", }, ]; -export const Tab = ({ setActiveSwappingShelfID }: ITab) => { +export const TokensShelfTab = ({ setActiveSwappingShelfID }: ITab) => { const [isActiveTab, setIsActiveTab] = useState(SwappingShelfID.THEIR_ITEMS); return ( -
+
{swappingTabs.map((tab) => { return (
{ @@ -45,7 +47,9 @@ export const Tab = ({ setActiveSwappingShelfID }: ITab) => { setIsActiveTab(tab.id); }} > -
{tab.name}
+
+ {tab.name} +
); })} diff --git a/components/01-atoms/Tooltip.tsx b/components/01-atoms/Tooltip.tsx new file mode 100644 index 00000000..5f547750 --- /dev/null +++ b/components/01-atoms/Tooltip.tsx @@ -0,0 +1,88 @@ +import PropTypes from "prop-types"; +import cc from "classcat"; + +enum ToolTipPosition { + TOP = "top", + BOTTOM = "bottom", + LEFT = "left", + RIGHT = "right", +} + +type Position = ToolTipPosition | "top" | "bottom" | "left" | "right"; + +interface TooltipProps { + position: Position; + content: string | boolean | null; // In case of content === null the Tooltip will not appear + children?: React.ReactNode; +} + +/** + * Tooltip component for displaying tooltips in different positions. + * Top | Bottom | Left | Right + * + */ +export const Tooltip = ({ position, content, children }: TooltipProps) => + content !== null ? ( +
+
{children}
+
+ + +
+
+ ) : ( +
{children}
+ ); + +Tooltip.propTypes = { + position: PropTypes.oneOf([ + ToolTipPosition.TOP, + ToolTipPosition.BOTTOM, + ToolTipPosition.LEFT, + ToolTipPosition.RIGHT, + ]).isRequired, + content: PropTypes.node.isRequired, + children: PropTypes.node.isRequired, +}; diff --git a/components/01-atoms/TransactionResultModal.tsx b/components/01-atoms/TransactionResultModal.tsx deleted file mode 100644 index 65401fe9..00000000 --- a/components/01-atoms/TransactionResultModal.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { TransactionResult } from "."; -import LoadingIndicator from "./LoadingIndicator"; -import { DangerIcon } from "./icons/DangerIcon"; -import { Dialog, Transition } from "@headlessui/react"; -import { CheckmarkIcon } from "react-hot-toast"; -import { Fragment, useState } from "react"; - -interface TransactionResultModalProps { - onClose: () => void; - transactionResult: TransactionResult | null; -} - -export const TransactionResultModal = ({ - transactionResult, - onClose, -}: TransactionResultModalProps) => { - const [open, setOpen] = useState(true); - - if (!transactionResult) { - return null; - } - - const closeModal = () => { - setOpen(false); - onClose(); - }; - - return ( - <> - -
- - - - - {transactionResult === TransactionResult.LOADING ? ( -
- -

- Loading -

-
- ) : transactionResult === TransactionResult.FAILURE ? ( -
- -

- Could not create offer -

-
- ) : transactionResult === TransactionResult.SUCCESS ? ( -
- -

- Offer created successfully -

-
- ) : null} -
-
-
- - ); -}; diff --git a/components/01-atoms/icons/ArrowIcon.tsx b/components/01-atoms/icons/ArrowIcon.tsx new file mode 100644 index 00000000..2f021c4a --- /dev/null +++ b/components/01-atoms/icons/ArrowIcon.tsx @@ -0,0 +1,95 @@ +import { SVGProps } from "react"; + +export enum ArrowIconVariant { + UP = "up", + DOWN = "down", + LEFT = "left", + RIGHT = "right", +} + +interface ArrowIconProps { + props?: SVGProps; + variant?: ArrowIconVariant; +} + +export const ArrowIcon = ({ + props, + variant = ArrowIconVariant.DOWN, +}: ArrowIconProps) => { + const ArrowIcons: Partial> = { + [ArrowIconVariant.DOWN]: ( + + + + + + ), + [ArrowIconVariant.UP]: ( + + + + + + ), + [ArrowIconVariant.LEFT]: ( + + + + + + ), + [ArrowIconVariant.RIGHT]: ( + + + + + + ), + }; + + return ArrowIcons[variant]; +}; diff --git a/components/01-atoms/icons/ChatIcon.tsx b/components/01-atoms/icons/ChatIcon.tsx new file mode 100644 index 00000000..29a89118 --- /dev/null +++ b/components/01-atoms/icons/ChatIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const ChatIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/CloseCTA.tsx b/components/01-atoms/icons/CloseCTA.tsx new file mode 100644 index 00000000..8b677f34 --- /dev/null +++ b/components/01-atoms/icons/CloseCTA.tsx @@ -0,0 +1,32 @@ +import { SVGProps } from "react"; + +interface CloseCTAProps { + onClick: () => void; + props?: SVGProps; +} + +export const CloseCTA = ({ onClick, props }: CloseCTAProps) => { + return ( + + ); +}; diff --git a/components/01-atoms/icons/CopyIcon.tsx b/components/01-atoms/icons/CopyIcon.tsx new file mode 100644 index 00000000..bcd3f787 --- /dev/null +++ b/components/01-atoms/icons/CopyIcon.tsx @@ -0,0 +1,19 @@ +import React, { SVGProps } from "react"; + +export const CopyIcon = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/components/01-atoms/icons/DoneIcon.tsx b/components/01-atoms/icons/DoneIcon.tsx new file mode 100644 index 00000000..25e8ac93 --- /dev/null +++ b/components/01-atoms/icons/DoneIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const DoneIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/ErrorIcon.tsx b/components/01-atoms/icons/ErrorIcon.tsx new file mode 100644 index 00000000..ec9dd9a2 --- /dev/null +++ b/components/01-atoms/icons/ErrorIcon.tsx @@ -0,0 +1,52 @@ +import { SVGProps } from "react"; +import cc from "classcat"; +import { useTheme } from "next-themes"; + +export const ErrorIcon = (props: SVGProps) => { + const { theme } = useTheme(); + return ( +
+ + + + + + + + + + + +
+ ); +}; diff --git a/components/01-atoms/icons/ExternalLinkIcon.tsx b/components/01-atoms/icons/ExternalLinkIcon.tsx new file mode 100644 index 00000000..537433f7 --- /dev/null +++ b/components/01-atoms/icons/ExternalLinkIcon.tsx @@ -0,0 +1,19 @@ +import React, { SVGProps } from "react"; + +export const ExternalLinkIcon = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/components/01-atoms/icons/MagnifyingGlassIcon.tsx b/components/01-atoms/icons/MagnifyingGlassIcon.tsx index 04f9c36b..92e5df59 100644 --- a/components/01-atoms/icons/MagnifyingGlassIcon.tsx +++ b/components/01-atoms/icons/MagnifyingGlassIcon.tsx @@ -6,13 +6,13 @@ export const MagnifyingGlassIcon = (props: SVGProps) => { {...props} viewBox="0 0 20 21" xmlns="http://www.w3.org/2000/svg" - fill={props.fill ? props.fill : "none"} + fill={"currentColor"} > diff --git a/components/01-atoms/icons/MoonIcon.tsx b/components/01-atoms/icons/MoonIcon.tsx new file mode 100644 index 00000000..eb96d48d --- /dev/null +++ b/components/01-atoms/icons/MoonIcon.tsx @@ -0,0 +1,9 @@ +import { SVGProps } from "react"; + +export const MoonIcon = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/components/01-atoms/icons/NetworkIcon.tsx b/components/01-atoms/icons/NetworkIcon.tsx new file mode 100644 index 00000000..310b939a --- /dev/null +++ b/components/01-atoms/icons/NetworkIcon.tsx @@ -0,0 +1,72 @@ +import { SupportedNetworks } from "@/lib/client/constants"; +import arbitrumSepoliaIcon from "@/public/chains/arbitrumSepoliaIcon.png"; +import sepoliaIcon from "@/public/chains/sepoliaIcon.png"; +import baseGoerliIcon from "@/public/chains/baseGoerliIcon.png"; +import FujiIcon from "@/public/chains/FujiIcon.png"; +import bnbChainIcon from "@/public/chains/bnbChainIcon.png"; +import optimismIcon from "@/public/chains/optimismIcon.png"; +import polygonMumbai from "@/public/chains/polygonMumbai.png"; +import Image from "next/image"; +import { SVGProps } from "react"; +import { useTheme } from "next-themes"; + +export type NetworkVariants = SupportedNetworks | "default"; + +interface NetworkIconProps { + props?: SVGProps; + variant: NetworkVariants; +} + +/** + * This component will render the network Icons + * The variants are the Supported Networks by the dApp + * + **/ +export const NetworkIcon = ({ + props, + variant = "default", +}: NetworkIconProps) => { + const { theme } = useTheme(); + + const NetworkIcons: Partial> = { + [SupportedNetworks.ARBITRUMSEPOLIA]: ( + {"Arbitrum + ), + [SupportedNetworks.BASEGOERLI]: ( + {"Base + ), + [SupportedNetworks.SEPOLIA]: ( + {"Sepolia + ), + [SupportedNetworks.FUJI]: {"Fuji, + [SupportedNetworks.BNB]: {"BNB, + [SupportedNetworks.OPTIMISM]: ( + {"Optimism + ), + [SupportedNetworks.MUMBAI]: ( + {"Mumbai + ), + default: ( +
+ + + + + +
+ ), + }; + + return NetworkIcons[variant]; +}; diff --git a/components/01-atoms/icons/NoSwapsIcon.tsx b/components/01-atoms/icons/NoSwapsIcon.tsx new file mode 100644 index 00000000..9ff5e0f4 --- /dev/null +++ b/components/01-atoms/icons/NoSwapsIcon.tsx @@ -0,0 +1,88 @@ +import { SVGProps } from "react"; + +export const NoSwapsIcon = (props: SVGProps) => { + return ( + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/components/01-atoms/icons/NotificationsIcon.tsx b/components/01-atoms/icons/NotificationsIcon.tsx new file mode 100644 index 00000000..6929d741 --- /dev/null +++ b/components/01-atoms/icons/NotificationsIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const NotificationsIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/OffersIcon.tsx b/components/01-atoms/icons/OffersIcon.tsx new file mode 100644 index 00000000..0993383f --- /dev/null +++ b/components/01-atoms/icons/OffersIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const OffersIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/PaperPlane.tsx b/components/01-atoms/icons/PaperPlane.tsx index 721cc2fb..232fb002 100644 --- a/components/01-atoms/icons/PaperPlane.tsx +++ b/components/01-atoms/icons/PaperPlane.tsx @@ -7,13 +7,13 @@ export const PaperPlane = (props: SVGProps) => ( height="16" viewBox="0 0 17 16" xmlns="http://www.w3.org/2000/svg" - fill={props.fill ? props.fill : "none"} + fill={"currentColor"} > diff --git a/components/01-atoms/icons/PersonIcon.tsx b/components/01-atoms/icons/PersonIcon.tsx new file mode 100644 index 00000000..7c891168 --- /dev/null +++ b/components/01-atoms/icons/PersonIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const PersonIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/PlusIcon.tsx b/components/01-atoms/icons/PlusIcon.tsx new file mode 100644 index 00000000..52549762 --- /dev/null +++ b/components/01-atoms/icons/PlusIcon.tsx @@ -0,0 +1,19 @@ +export const PlusIcon = () => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/PowerIcon.tsx b/components/01-atoms/icons/PowerIcon.tsx new file mode 100644 index 00000000..50375145 --- /dev/null +++ b/components/01-atoms/icons/PowerIcon.tsx @@ -0,0 +1,26 @@ +import { SVGProps } from "react"; + +export const PowerIcon = (props: SVGProps) => { + return ( + + + + + + + + + + + ); +}; diff --git a/components/01-atoms/icons/SelectUserIcon.tsx b/components/01-atoms/icons/SelectUserIcon.tsx new file mode 100644 index 00000000..73677def --- /dev/null +++ b/components/01-atoms/icons/SelectUserIcon.tsx @@ -0,0 +1,23 @@ +import { SVGProps } from "react"; + +export const SelectUserIcon = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/components/01-atoms/icons/ShareIcon.tsx b/components/01-atoms/icons/ShareIcon.tsx new file mode 100644 index 00000000..2a3dcc73 --- /dev/null +++ b/components/01-atoms/icons/ShareIcon.tsx @@ -0,0 +1,22 @@ +import React, { SVGProps } from "react"; + +export const ShareIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/SunIcon.tsx b/components/01-atoms/icons/SunIcon.tsx new file mode 100644 index 00000000..ecbe98d2 --- /dev/null +++ b/components/01-atoms/icons/SunIcon.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from "react"; + +export const SunIcon = (props: SVGProps) => { + return ( + + + + + + + + + + + + ); +}; diff --git a/components/01-atoms/icons/SwapIcon.tsx b/components/01-atoms/icons/SwapIcon.tsx index 48b27697..a62f2c2a 100644 --- a/components/01-atoms/icons/SwapIcon.tsx +++ b/components/01-atoms/icons/SwapIcon.tsx @@ -1,61 +1,130 @@ import { SVGProps } from "react"; -export const SwapIcon = (props: SVGProps) => { - return ( - - - - - - - - - - - - - ; + variant?: SwapIconVariant; +} + +export const SwapIcon = ({ + props, + variant = SwapIconVariant.HORIZONTAL, +}: SwapIconProps) => { + const SwapIcons: Partial> = { + [SwapIconVariant.HORIZONTAL]: ( + + + - + + + + + + + + + + + + + + ), + [SwapIconVariant.VERTICAL]: ( + + + - - - - - - - ); + + + + + + + + + + + + + + + ), + }; + + return SwapIcons[variant]; }; diff --git a/components/01-atoms/icons/SwaplaceIcon.tsx b/components/01-atoms/icons/SwaplaceIcon.tsx index d4a68ad7..66556d29 100644 --- a/components/01-atoms/icons/SwaplaceIcon.tsx +++ b/components/01-atoms/icons/SwaplaceIcon.tsx @@ -4,7 +4,7 @@ export const SwaplaceIcon = (props: SVGProps) => { return ( @@ -12,12 +12,12 @@ export const SwaplaceIcon = (props: SVGProps) => { diff --git a/components/01-atoms/icons/SwappingIcon.tsx b/components/01-atoms/icons/SwappingIcon.tsx new file mode 100644 index 00000000..6bee19e0 --- /dev/null +++ b/components/01-atoms/icons/SwappingIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const SwappingIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/ThreeDotsIcon.tsx b/components/01-atoms/icons/ThreeDotsIcon.tsx new file mode 100644 index 00000000..8e4f42de --- /dev/null +++ b/components/01-atoms/icons/ThreeDotsIcon.tsx @@ -0,0 +1,20 @@ +import { SVGProps } from "react"; + +export const ThreeDotsIcon = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/components/01-atoms/icons/WalletIcon.tsx b/components/01-atoms/icons/WalletIcon.tsx new file mode 100644 index 00000000..b3d6ebd6 --- /dev/null +++ b/components/01-atoms/icons/WalletIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const WalletIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/XMarkIcon.tsx b/components/01-atoms/icons/XMarkIcon.tsx new file mode 100644 index 00000000..559f8f22 --- /dev/null +++ b/components/01-atoms/icons/XMarkIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const XMarkIcon = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/components/01-atoms/index.ts b/components/01-atoms/index.ts index 988081da..232f435a 100644 --- a/components/01-atoms/index.ts +++ b/components/01-atoms/index.ts @@ -1,15 +1,58 @@ +/** Atoms */ +export * from "./ApprovedTokenCards"; export * from "./ConnectWallet"; -export * from "../02-molecules/NftCard"; +export * from "./DisconnectWallet"; +export * from "./ENSAvatar"; +export * from "./LoadingIndicator"; +export * from "./NetworkDropdown"; +export * from "./OfferExpiryConfirmSwap"; +export * from "./OfferTag"; +export * from "./ProgressBar"; export * from "./SearchBar"; -export * from "./SelectAuthedUserChain"; -export * from "./Tab"; +export * from "./SearchItemsShelf"; +export * from "./SelectAuthedUserChain"; // Remove ? +export * from "./SelectDestinyChain"; // Remove ? +export * from "./StatusOffers"; export * from "./SwapContext"; -export * from "./icons/SwaplaceIcon"; +export * from "./SwapExpireTime"; +export * from "./SwapModalButton"; +export * from "./SwapModalLayout"; +export * from "./SwappingIcons"; +export * from "./ThreeDotsCardOffersOptions"; +export * from "./TokenCardProperties"; +export * from "./TokenCardsPlaceholder"; +export * from "./TokenOfferDetails"; +export * from "./TokensOfferSkeleton"; +export * from "./TokensShelfTab"; +export * from "./Tooltip"; + +/** Icons */ +export * from "./icons/ArrowIcon"; +export * from "./icons/ChatIcon"; +export * from "./icons/CloseCTA"; +export * from "./icons/CopyIcon"; +export * from "./icons/DangerIcon"; +export * from "./icons/DoneIcon"; +export * from "./icons/ErrorIcon"; +export * from "./icons/EthereumIcon"; +export * from "./icons/ExternalLinkIcon"; export * from "./icons/MagnifyingGlassIcon"; -export * from "./icons/SwapIcon"; +export * from "./icons/MoonIcon"; +export * from "./icons/NetworkIcon"; +export * from "./icons/NoSwapsIcon"; +export * from "./icons/NotificationsIcon"; +export * from "./icons/OffersIcon"; export * from "./icons/PaperPlane"; -export * from "./SelectDestinyChain"; -export * from "./icons/EthereumIcon"; +export * from "./icons/PersonIcon"; +export * from "./icons/PlusIcon"; export * from "./icons/PolygonIcon"; -export * from "./ConfirmSwapModal"; -export * from "./TransactionResultModal"; +export * from "./icons/PowerIcon"; +export * from "./icons/SelectUserIcon"; +export * from "./icons/ShareIcon"; +export * from "./icons/SunIcon"; +export * from "./icons/SwapIcon"; +export * from "./icons/SwaplaceIcon"; +export * from "./icons/SwappingIcon"; +export * from "./icons/ThreeDotsIcon"; +export * from "./icons/WalletIcon"; +export * from "./icons/XMarkIcon"; diff --git a/components/02-molecules/AccountBalanceWalletSidebar.tsx b/components/02-molecules/AccountBalanceWalletSidebar.tsx new file mode 100644 index 00000000..d03ac7da --- /dev/null +++ b/components/02-molecules/AccountBalanceWalletSidebar.tsx @@ -0,0 +1,40 @@ +import { useWalletBalance } from "@/lib/client/hooks/useWalletBalance"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import React from "react"; +import cc from "classcat"; +import { useTheme } from "next-themes"; +import { useNetwork } from "wagmi"; + +export const AccountBalanceWalletSidebar = () => { + const { authenticatedUserAddress } = useAuthenticatedUser(); + + const { chain } = useNetwork(); + + const { systemTheme, theme } = useTheme(); + const currentTheme = theme === "system" ? systemTheme : theme; + const isDark = currentTheme === "dark"; + + const { balance } = useWalletBalance({ + walletAddress: authenticatedUserAddress, + }); + + const match = balance?.match(/^(\d+\.\d{1,3})|\d+/); + const displayBalance = match ? match[0] : balance; + + return ( +
+

+ Current balance +

+
+

{displayBalance || "0"}

+

{chain?.nativeCurrency.symbol}

+
+
+ ); +}; diff --git a/components/02-molecules/AddTokenCardManually.tsx b/components/02-molecules/AddTokenCardManually.tsx new file mode 100644 index 00000000..38e7dd15 --- /dev/null +++ b/components/02-molecules/AddTokenCardManually.tsx @@ -0,0 +1,45 @@ +import { + AddTokenOrSwapManuallyModal, + AddTokenOrSwapManuallyModalVariant, +} from "@/components/02-molecules"; +import { PlusIcon, Tooltip } from "@/components/01-atoms"; +import { useState } from "react"; + +export const AddTokenCardManually = () => { + const [open, setOpen] = useState(false); + + return ( + <> +
+ +
+ +
+
+ + setOpen(false)} + open={open} + /> + + ); +}; diff --git a/components/02-molecules/AddTokenOrSwapManuallyModal.tsx b/components/02-molecules/AddTokenOrSwapManuallyModal.tsx new file mode 100644 index 00000000..b71cce5a --- /dev/null +++ b/components/02-molecules/AddTokenOrSwapManuallyModal.tsx @@ -0,0 +1,141 @@ +import { SwapModalLayout } from "@/components/01-atoms"; +import { TokenType } from "@/lib/shared/types"; +import React, { useState } from "react"; +import cc from "classcat"; + +export enum AddTokenOrSwapManuallyModalVariant { + SWAP = "swap", + TOKEN = "token", +} + +interface AddManuallyConfig { + header: string; + body: React.ReactNode; +} + +interface AddManuallyProps { + variant?: AddTokenOrSwapManuallyModalVariant; + open: boolean; + onClose: () => void; +} + +const SwapBody = () => { + return ( +
+
+
Swap ID
+
+ +
+
+
+ +
+
+ ); +}; + +const TokenBody = () => { + const [token, setToken] = useState(TokenType.ERC20); + return ( +
+
+
What kind of token you want to add?
+
+ + +
+
+
+ {token === TokenType.ERC20 ? ( +
+
+ Contract address +
+
+ +
+
+ ) : ( +
+
+
+ Contract address +
+
+ +
+
+
+
+ Token ID +
+
+ +
+
+
+ )} +
+
+ +
+
+ ); +}; + +const AddTokenOrSwapManuallyModalConfig: Record< + AddTokenOrSwapManuallyModalVariant, + AddManuallyConfig +> = { + [AddTokenOrSwapManuallyModalVariant.SWAP]: { + header: "Add swap manually", + body: , + }, + [AddTokenOrSwapManuallyModalVariant.TOKEN]: { + header: "Add token", + body: , + }, +}; + +export const AddTokenOrSwapManuallyModal = ({ + variant = AddTokenOrSwapManuallyModalVariant.TOKEN, + open, + onClose, +}: AddManuallyProps) => { + return ( + + ); +}; diff --git a/components/02-molecules/CardHome.tsx b/components/02-molecules/CardHome.tsx deleted file mode 100644 index f36f591b..00000000 --- a/components/02-molecules/CardHome.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { ConnectWallet, SwaplaceIcon } from "@/components/01-atoms"; -import React from "react"; - -export const CardHome = () => { - return ( -
-
-
- -

Swaplace

-
- -
-
- Your greatest deals are here -
-
- Connect your wallet to start swapping your NFTs and tokens -
-
-
- - -
- ); -}; diff --git a/components/02-molecules/CardOffers.tsx b/components/02-molecules/CardOffers.tsx new file mode 100644 index 00000000..b8595cf9 --- /dev/null +++ b/components/02-molecules/CardOffers.tsx @@ -0,0 +1,99 @@ +import { + TokenOfferVariant, + TokensShelfVariant, +} from "@/components/03-organisms"; +import { + TokenCardActionType, + TokenCardStyleType, + TokensList, + UserOfferInfo, + UserOfferVariant, +} from "@/components/02-molecules"; +import { SwapContext, TokenCardProperties } from "@/components/01-atoms"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { EthereumAddress, Token } from "@/lib/shared/types"; +import { useContext } from "react"; + +interface CardOffersProps { + address: EthereumAddress | null; + variant?: TokenOfferVariant; +} + +interface CardOfferSConfig { + body: React.ReactNode; +} + +export const CardOffers = ({ + address, + variant = TokenOfferVariant.HORIZONTAL, +}: CardOffersProps) => { + const { authenticatedUserAddress } = useAuthenticatedUser(); + const { authenticatedUserTokensList, searchedUserTokensList } = + useContext(SwapContext); + + const tokenShelfVariant = authenticatedUserAddress?.equals(address) + ? TokensShelfVariant.Your + : TokensShelfVariant.Their; + const tokensOfferFor: Record = { + [TokensShelfVariant.Your]: searchedUserTokensList, + [TokensShelfVariant.Their]: authenticatedUserTokensList, + }; + + const HorizontalVariant = (address: EthereumAddress | null) => { + if (!address) return null; + + return ( +
+
+ + +
+ +
+
+
+ ); + }; + + const VerticalVariant = (address: EthereumAddress | null) => { + if (!address) return null; + + return ( +
+ + +
+ ); + }; + + const CardOfferVariantsConfig: Record = { + [TokenOfferVariant.HORIZONTAL]: { + body: HorizontalVariant(address), + }, + [TokenOfferVariant.VERTICAL]: { + body: VerticalVariant(address), + }, + }; + + return <>{CardOfferVariantsConfig[variant].body}; +}; diff --git a/components/02-molecules/ConfirmSwapModal.tsx b/components/02-molecules/ConfirmSwapModal.tsx new file mode 100644 index 00000000..ee7c5d8b --- /dev/null +++ b/components/02-molecules/ConfirmSwapModal.tsx @@ -0,0 +1,274 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { + SwapModalLayout, + SwapContext, + ApprovedTokenCards, + SwapModalButton, + ButtonVariant, + OfferExpiryConfirmSwap, +} from "@/components/01-atoms"; +import { ProgressStatus } from "@/components/02-molecules"; +import { SwapUserConfiguration, createSwap } from "@/lib/service/createSwap"; +import { + ButtonClickPossibilities, + packingData, + toastBlockchainTxError, +} from "@/lib/client/blockchain-utils"; +import { TokenOffers } from "@/components/03-organisms"; +import { fromTokensToAssets, getSwapConfig } from "@/lib/client/swap-utils"; +import { SWAPLACE_SMART_CONTRACT_ADDRESS } from "@/lib/client/constants"; +import { publicClient } from "@/lib/wallet/wallet-config"; +import { SwapModalSteps } from "@/lib/client/ui-utils"; +import { SwaplaceAbi } from "@/lib/client/abi"; +import { EthereumAddress } from "@/lib/shared/types"; +import { type WalletClient, useNetwork, useWalletClient } from "wagmi"; +import { useContext, useEffect } from "react"; +import { useTheme } from "next-themes"; +import toast from "react-hot-toast"; +import { getContract } from "viem"; + +interface ConfirmSwapApprovalModalProps { + open: boolean; + onClose: () => void; +} + +export const ConfirmSwapModal = ({ + open, + onClose, +}: ConfirmSwapApprovalModalProps) => { + const { authenticatedUserAddress } = useAuthenticatedUser(); + const { + timeDate, + authenticatedUserTokensList, + searchedUserTokensList, + approvedTokensCount, + validatedAddressToSwap, + currentSwapModalStep, + updateSwapStep, + clearSwapData, + } = useContext(SwapContext); + + const { chain } = useNetwork(); + const { data: walletClient } = useWalletClient(); + const { theme } = useTheme(); + + useEffect(() => { + if (currentSwapModalStep === SwapModalSteps.CREATING_SWAP) { + handleSwap(); + } + }, [currentSwapModalStep]); + + useEffect(() => { + if (!open) { + updateSwapStep(ButtonClickPossibilities.PREVIOUS_STEP); + } + }, [open]); + + useEffect(() => { + updateSwapStep(ButtonClickPossibilities.PREVIOUS_STEP); + }, [authenticatedUserTokensList]); + + if ( + (!authenticatedUserAddress?.address || + !searchedUserTokensList || + !authenticatedUserTokensList) && + open + ) { + onClose(); + return null; + } + + let chainId: number; + let userWalletClient: WalletClient; + + const handleSwap = async () => { + if (typeof chain?.id != "undefined" && walletClient != undefined) { + chainId = chain?.id; + userWalletClient = walletClient; + } else { + throw new Error("Chain ID is undefined"); + } + + if (!validatedAddressToSwap) + throw new Error("No Swap offer receiver is defined"); + + // Franco TODO: Review this need + const SwaplaceContract = getContract({ + address: SWAPLACE_SMART_CONTRACT_ADDRESS[chainId] as `0x${string}`, + publicClient: publicClient({ chainId: chain.id }), + abi: SwaplaceAbi, + }); + const packedData = await packingData( + SwaplaceContract, + validatedAddressToSwap, + timeDate, + ); + + const authenticatedUserAssets = await fromTokensToAssets( + authenticatedUserTokensList, + ); + const searchedUserAssets = await fromTokensToAssets(searchedUserTokensList); + + const swapConfig = await getSwapConfig( + new EthereumAddress(userWalletClient.account.address), + packedData, + timeDate, + authenticatedUserAssets, + searchedUserAssets, + chainId, + ); + + const configurations: SwapUserConfiguration = { + walletClient: userWalletClient, + chain: chainId, + }; + + try { + if (approvedTokensCount) { + const transactionReceipt = await createSwap(swapConfig, configurations); + + if (transactionReceipt != undefined) { + toast.success("Successfully created swap offer!"); + updateSwapStep(ButtonClickPossibilities.NEXT_STEP); + } else { + toastBlockchainTxError("Create swap failed"); + updateSwapStep(ButtonClickPossibilities.PREVIOUS_STEP); + } + } else { + toast.error("You must approve the Tokens to Swap."); + updateSwapStep(ButtonClickPossibilities.PREVIOUS_STEP); + } + } catch (error) { + toastBlockchainTxError(String(error)); + updateSwapStep(ButtonClickPossibilities.PREVIOUS_STEP); + console.error(error); + } + }; + + const validateTokensAreApproved = () => { + if (approvedTokensCount) { + if (currentSwapModalStep === SwapModalSteps.APPROVE_TOKENS) { + updateSwapStep(ButtonClickPossibilities.NEXT_STEP); + } + } else { + toast.error("You must approve the Tokens to Swap."); + } + }; + + const ConfirmSwapModalStep: Partial> = { + [SwapModalSteps.APPROVE_TOKENS]: ( + } + footer={ +
+ + +
+ } + /> + ), + [SwapModalSteps.CREATE_SWAP]: ( + + + +
+ } + footer={ +
+ { + updateSwapStep(ButtonClickPossibilities.PREVIOUS_STEP); + }} + /> + + { + updateSwapStep(ButtonClickPossibilities.NEXT_STEP); + }} + /> +
+ } + /> + ), + [SwapModalSteps.CREATING_SWAP]: ( + + + +
+ } + footer={ +
+ +
+ } + /> + ), + [SwapModalSteps.CREATED_SWAP]: ( + + + +
+ } + footer={ +
+ { + clearSwapData(); + onClose(); + }} + /> +
+ } + /> + ), + }; + + return ConfirmSwapModalStep[currentSwapModalStep]; +}; diff --git a/components/02-molecules/CopyAdressButton.tsx b/components/02-molecules/CopyAdressButton.tsx new file mode 100644 index 00000000..462f9ce0 --- /dev/null +++ b/components/02-molecules/CopyAdressButton.tsx @@ -0,0 +1,43 @@ +import { CopyIcon, DoneIcon, Tooltip } from "@/components/01-atoms"; +import React, { useEffect, useState } from "react"; + +export const CopyAdressButton = ({ + authenticatedUserAddress, + displayAddress, +}: { + authenticatedUserAddress: string; + displayAddress: string; +}) => { + const [isCopied, setIsCopied] = useState(false); + + useEffect(() => { + if (isCopied) { + setTimeout(() => { + setIsCopied(false); + }, 3000); + } + }, [isCopied]); + + return ( + + + + ); +}; diff --git a/components/02-molecules/EnsNameAndAddressWallet.tsx b/components/02-molecules/EnsNameAndAddressWallet.tsx new file mode 100644 index 00000000..54e29dba --- /dev/null +++ b/components/02-molecules/EnsNameAndAddressWallet.tsx @@ -0,0 +1,64 @@ +import { CopyAdressButton } from "@/components/02-molecules"; +import { ENSAvatar, ExternalLinkIcon } from "@/components/01-atoms"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { useEnsData } from "@/lib/client/hooks/useENSData"; +import React from "react"; +import { useNetwork } from "wagmi"; + +export const EnsNameAndAddressWallet = () => { + const { authenticatedUserAddress } = useAuthenticatedUser(); + + const { primaryName } = useEnsData({ + ensAddress: authenticatedUserAddress, + }); + + const { chain } = useNetwork(); + + if (!authenticatedUserAddress) return null; + + const blockExplorer = `${ + chain?.blockExplorers?.default.url + }/address/${authenticatedUserAddress?.toString()}`; + + const displayAddress = authenticatedUserAddress?.getEllipsedAddress(); + + return ( +
+ {authenticatedUserAddress && ( + <> + +
+
+ {primaryName && ( + <> +

{`${primaryName}`}

+

+ | +

+ + )} + +
+ +
+ + )} +
+ ); +}; diff --git a/components/02-molecules/FilterOffers.tsx b/components/02-molecules/FilterOffers.tsx new file mode 100644 index 00000000..787ec89e --- /dev/null +++ b/components/02-molecules/FilterOffers.tsx @@ -0,0 +1,16 @@ +import { StatusOffers } from "@/components/01-atoms"; + +export const FilterOffers = () => { + return ( +
+
+
+

Your offers

+
+
+ +
+
+
+ ); +}; diff --git a/components/02-molecules/NftCard.tsx b/components/02-molecules/NftCard.tsx deleted file mode 100644 index cf2b4f33..00000000 --- a/components/02-molecules/NftCard.tsx +++ /dev/null @@ -1,146 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { SwapContext } from "../01-atoms"; -import { NFT } from "@/lib/client/constants"; -import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { EthereumAddress } from "@/lib/shared/types"; -import React, { useContext, useEffect, useState } from "react"; -import cc from "classcat"; -import toast from "react-hot-toast"; - -interface INftCard { - nftData: NFT; - ownerAddress: string | null; - onClickAction?: NftCardActionType; - withSelectionValidation?: boolean; -} - -/** - * - * This component receives the data of an nft and create a card NFT - * @param nftData - * @param ownerAddress - * - * @returns NftCard - */ - -export enum NftCardActionType { - "SELECT_NFT_FOR_SWAP", - "SHOW_NFT_DETAILS", -} - -export const NftCard = ({ - nftData, - ownerAddress, - withSelectionValidation = true, - onClickAction = NftCardActionType.SELECT_NFT_FOR_SWAP, -}: INftCard) => { - const { authenticatedUserAddress } = useAuthenticatedUser(); - const { setNftAuthUser, setNftInputUser, nftAuthUser, nftInputUser } = - useContext(SwapContext); - const [couldntLoadNftImage, setCouldntLoadNftImage] = useState(false); - const [currentNftIsSelected, setCurrentNftIsSelected] = useState(false); - - useEffect(() => { - setCouldntLoadNftImage(false); - }, [nftData]); - - useEffect(() => { - const currentNftIsFromAuthedUser = ownerAddress - ? authenticatedUserAddress?.equals(new EthereumAddress(ownerAddress)) - : null; - - if (currentNftIsFromAuthedUser) { - if (nftAuthUser.length) { - setCurrentNftIsSelected(nftAuthUser[0].id === nftData.id); - } else { - setCurrentNftIsSelected(false); - } - } else { - if (nftInputUser.length) { - setCurrentNftIsSelected(nftInputUser[0].id === nftData.id); - } else { - setCurrentNftIsSelected(false); - } - } - }, [authenticatedUserAddress, ownerAddress, nftAuthUser, nftInputUser]); - - if (!nftData || !nftData.id || !nftData.contract || !ownerAddress) - return null; - - const setNftAsActiveOne = () => { - if (onClickAction === NftCardActionType.SELECT_NFT_FOR_SWAP) { - const ownerEthAddress = new EthereumAddress(ownerAddress); - - if (authenticatedUserAddress?.equals(ownerEthAddress)) { - if (nftAuthUser.length) { - if (nftAuthUser[0].id === nftData.id) setNftAuthUser([]); - else setNftAuthUser([nftData]); - } else { - setNftAuthUser([nftData]); - } - } else { - if (nftInputUser.length) { - if (nftInputUser[0].id === nftData.id) setNftInputUser([]); - else setNftInputUser([nftData]); - } else { - setNftInputUser([nftData]); - } - } - } else if (onClickAction === NftCardActionType.SHOW_NFT_DETAILS) { - navigator.clipboard.writeText(JSON.stringify(nftData)); - toast.success("NFT data copied to your clipboard"); - } - }; - - const handleImageLoadError = () => { - setCouldntLoadNftImage(true); - }; - - const ButtonLayout = (children: React.ReactNode) => { - return ( - - ); - }; - - return nftData.metadata?.image && !couldntLoadNftImage ? ( - <> - {ButtonLayout( - {nftData.metadata?.name} - )} - - ) : nftData.metadata?.name ? ( - <> - {ButtonLayout( -
- {nftData.metadata?.name} -
- )} - - ) : nftData.contract.name && nftData.id.tokenId ? ( - <> - {ButtonLayout( -
- {nftData.metadata?.name} -
- )} - - ) : null; -}; diff --git a/components/02-molecules/NftsList.tsx b/components/02-molecules/NftsList.tsx deleted file mode 100644 index 54cd3267..00000000 --- a/components/02-molecules/NftsList.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/* eslint-disable react/jsx-key */ -import { NftCard } from "../01-atoms"; -import { NFT } from "@/lib/client/constants"; - -interface INftsList { - nftsList: NFT[]; - ownerAddress: string | null; -} - -/** - * - * This component receives the data of multiple nfts and create its cards - * @param nftsList - * @param ownerAddress - * - * @returns NftsList - */ - -export const NftsList = ({ nftsList, ownerAddress }: INftsList) => { - return ( -
- {nftsList.map((nft: NFT) => { - return ; - })} -
- ); -}; diff --git a/components/02-molecules/OfferSummary.tsx b/components/02-molecules/OfferSummary.tsx index 936d65b3..15ce2e92 100644 --- a/components/02-molecules/OfferSummary.tsx +++ b/components/02-molecules/OfferSummary.tsx @@ -1,87 +1,146 @@ -import { NftCard, SwapContext } from "../01-atoms"; -import { EthereumAddress } from "@/lib/shared/types"; +import { + ENSAvatar, + ENSAvatarSize, + PersonIcon, + SwapContext, +} from "@/components/01-atoms"; +import { TokenCardStyleType, TokensList } from "@/components/02-molecules"; +import { TokensShelfVariant } from "@/components/03-organisms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { ChainInfo } from "@/lib/client/constants"; -import { useEnsName, useNetwork } from "wagmi"; +import { useEnsData } from "@/lib/client/hooks/useENSData"; import { useContext } from "react"; interface IOfferSummary { - forAuthedUser: boolean; + variant: TokensShelfVariant; } -export const OfferSummary = ({ forAuthedUser }: IOfferSummary) => { - const { validatedAddressToSwap, nftAuthUser, nftInputUser, destinyChain } = - useContext(SwapContext); - const { chain } = useNetwork(); - const { data } = useEnsName({ - address: validatedAddressToSwap as `0x${string}`, - }); +export const OfferSummary = ({ variant }: IOfferSummary) => { + const { + validatedAddressToSwap, + authenticatedUserTokensList, + searchedUserTokensList, + } = useContext(SwapContext); const { authenticatedUserAddress } = useAuthenticatedUser(); + const tokensList = + variant === TokensShelfVariant.Your + ? authenticatedUserTokensList + : searchedUserTokensList; + + const { primaryName: searchedENSName } = useEnsData({ + ensAddress: validatedAddressToSwap, + }); + const { primaryName: authenticatedUserENSName } = useEnsData({ + ensAddress: authenticatedUserAddress, + }); return ( -
-
-
-
-
-

- {forAuthedUser - ? "You give" - : !forAuthedUser && !validatedAddressToSwap - ? "Use the search bar!" - : `${ - data - ? data - : new EthereumAddress( - validatedAddressToSwap - ).getEllipsedAddress() - } gives`} -

+
+
+
+
+
+ {variant === TokensShelfVariant.Your && validatedAddressToSwap ? ( + + ) : variant === TokensShelfVariant.Their && + authenticatedUserAddress ? ( + + ) : ( +
+ +
+ )} +
+
+

+ {variant === TokensShelfVariant.Your && validatedAddressToSwap + ? `${ + searchedENSName + ? searchedENSName + " gets" + : validatedAddressToSwap + ? validatedAddressToSwap.getEllipsedAddress() + " gets" + : "Use the search bar" + }` + : variant === TokensShelfVariant.Your && + !validatedAddressToSwap + ? "They get" + : variant === TokensShelfVariant.Their && + authenticatedUserAddress + ? `${ + authenticatedUserENSName + ? authenticatedUserENSName + " gets" + : authenticatedUserAddress + ? authenticatedUserAddress.getEllipsedAddress() + + " gets" + : "Connect your wallet" + }` + : "You get"} +

+
+ {(variant === TokensShelfVariant.Their && !validatedAddressToSwap) || + (variant === TokensShelfVariant.Your && + !authenticatedUserAddress) ? null : ( +
+ {tokensList.length} item + {tokensList.length !== 1 ? "s" : ""} +
+ )}
- {!forAuthedUser && !validatedAddressToSwap ? null : ( -
- {forAuthedUser ? nftAuthUser.length : nftInputUser.length} item - {forAuthedUser - ? nftAuthUser.length !== 1 - ? "s" - : "" - : nftInputUser.length !== 1 - ? "s" - : ""} -
- )} -
- -
-
- {(forAuthedUser && !authenticatedUserAddress?.address) || - (!forAuthedUser && !validatedAddressToSwap) ? null : ( - + {variant === TokensShelfVariant.Your && authenticatedUserAddress ? ( + + ) : variant === TokensShelfVariant.Their && validatedAddressToSwap ? ( + - )} -
-
- -
-

from

-

- {forAuthedUser ? ( - <>{chain?.name} ) : ( - <>{ChainInfo[destinyChain].name} + )} -

+
); diff --git a/components/02-molecules/ProgressStatus.tsx b/components/02-molecules/ProgressStatus.tsx new file mode 100644 index 00000000..7bfe8ae9 --- /dev/null +++ b/components/02-molecules/ProgressStatus.tsx @@ -0,0 +1,21 @@ +import { SwapContext, ProgressBar } from "@/components/01-atoms"; +import { useContext } from "react"; + +export const ProgressStatus = () => { + const { approvedTokensCount, authenticatedUserTokensList } = + useContext(SwapContext); + + return ( +
+

+ {approvedTokensCount + " / " + authenticatedUserTokensList.length} +

+
+ +
+
+ ); +}; diff --git a/components/02-molecules/SelectChainNetwork.tsx b/components/02-molecules/SelectChainNetwork.tsx new file mode 100644 index 00000000..86b01883 --- /dev/null +++ b/components/02-molecules/SelectChainNetwork.tsx @@ -0,0 +1,36 @@ +import { + NetworkDropdown, + SwapIcon, + SwapIconVariant, +} from "@/components/01-atoms"; +import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; + +export const SelectChainNetwork = () => { + const { isMobile } = useScreenSize(); + return ( +
+
+

+ Which network do you want to swap? +

+
+
+ +
+ {isMobile ? ( + + ) : ( + + )} +
+ +
+
+ ); +}; diff --git a/components/02-molecules/SwapOffersLayout.tsx b/components/02-molecules/SwapOffersLayout.tsx new file mode 100644 index 00000000..1cd7b79f --- /dev/null +++ b/components/02-molecules/SwapOffersLayout.tsx @@ -0,0 +1,103 @@ +import { + AddTokenOrSwapManuallyModal, + AddTokenOrSwapManuallyModalVariant, +} from "@/components/02-molecules"; +import { ErrorIcon, NoSwapsIcon } from "@/components/01-atoms"; +import { useTheme } from "next-themes"; +import React, { useState } from "react"; +import cc from "classcat"; +import { useRouter } from "next/router"; + +interface EmptyLayoutOffersProps { + icon: React.ReactNode; + title: React.ReactNode; + description: React.ReactNode; + button: React.ReactNode; +} + +const EmptyLayoutOffers = ({ + icon, + title, + description, + button, +}: EmptyLayoutOffersProps) => { + return ( +
+
{icon}
+
+

+ {title} +

+

+ {description} +

+
+
{button}
+
+ ); +}; + +export enum SwapOffersDisplayVariant { + ERROR = "error", + NO_SWAPS_CREATED = "swapless", +} + +type Variant = SwapOffersDisplayVariant | "error" | "swapless"; + +interface SwapOffersLayoutProps { + variant: Variant; +} + +export const SwapOffersLayout = ({ variant }: SwapOffersLayoutProps) => { + const { theme } = useTheme(); + const [toggleManually, setToggleManually] = useState(false); + const router = useRouter(); + + return ( + <> + {variant === SwapOffersDisplayVariant.ERROR ? ( + } + title={<> Sorry, we couldn't load your swaps} + description={<> Please try again later or add your swaps manually} + button={ + <> + + { + setToggleManually(false); + }} + variant={AddTokenOrSwapManuallyModalVariant.SWAP} + /> + + } + /> + ) : ( + } + title={<> No swaps here. Let's fill it up!} + description={ +
+ You haven't made or received any proposals. Time to jump in + and start trading. +
+ } + button={ + + } + /> + )} + + ); +}; diff --git a/components/02-molecules/SwapStation.tsx b/components/02-molecules/SwapStation.tsx deleted file mode 100644 index 5f8361e6..00000000 --- a/components/02-molecules/SwapStation.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { OfferSummary } from "@/components/02-molecules"; -import { - ConfirmSwapModal, - PaperPlane, - SwapContext, -} from "@/components/01-atoms"; -import { useContext, useEffect, useState } from "react"; -import cc from "classcat"; -import toast from "react-hot-toast"; - -export const SwapStation = () => { - const [isValidSwap, setIsValidSwap] = useState(false); - - const { nftAuthUser, nftInputUser, validatedAddressToSwap } = - useContext(SwapContext); - - useEffect(() => { - setIsValidSwap( - !!nftAuthUser.length && !!nftInputUser.length && !!validatedAddressToSwap - ); - }, [nftAuthUser, nftInputUser, validatedAddressToSwap]); - - const [openConfirmationModal, setOpenConfirmationModal] = - useState(false); - - const validateSwapSending = () => { - if (!isValidSwap) { - if (!validatedAddressToSwap) { - toast.error("You must select a destiny wallet to swap NFTs with"); - return; - } - - if (!nftAuthUser.length) { - toast.error("You must select at least one NFT from yours to swap"); - return; - } - - if (!nftInputUser.length) { - toast.error( - "You must select at least one NFT from the destiny wallet to swap" - ); - return; - } - } else { - setOpenConfirmationModal(true); - } - }; - - return ( -
-
-

Swap offer

- - -
-
-
- -
-
- - setOpenConfirmationModal(false)} - /> -
- ); -}; diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index d4ba9d79..f343363e 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -1,30 +1,121 @@ -import { ConnectWallet, SwaplaceIcon } from "@/components/01-atoms"; import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { + ConnectWallet, + ENSAvatar, + MoonIcon, + SunIcon, + SwaplaceIcon, + SwappingIcons, + Tooltip, +} from "@/components/01-atoms"; +import { useSidebar } from "@/lib/client/contexts/SidebarContext.tsx"; +import { WalletSidebarTemplate } from "@/components/03-organisms"; import React, { useEffect, useState } from "react"; -import cc from "classcat"; +import { useTheme } from "next-themes"; +import Link from "next/link"; export const TheHeader = () => { - const { isDesktop } = useScreenSize(); const { authenticatedUserAddress } = useAuthenticatedUser(); - const [showFullNav, setShowFullNav] = useState( - !isDesktop && !!authenticatedUserAddress?.address - ); + const { toggleSidebar, isSidebarOpen } = useSidebar(); + const { isWideScreen } = useScreenSize(); + const { systemTheme, theme, setTheme } = useTheme(); + const [mounted, setMounted] = useState(false); + + const setThemeMode = (mode: "light" | "dark") => { + const body = document.body; + + // Add the class to disable transitions + body.classList.add("no-transition"); + + setTheme(mode); + + // Use a timeout to re-enable transitions + setTimeout(() => { + body.classList.remove("no-transition"); + }, 0); + }; useEffect(() => { - setShowFullNav(!isDesktop); - }, [isDesktop]); + setMounted(true); + }, []); + if (!mounted) return null; + const currentTheme = theme === "system" ? systemTheme : theme; + const isDark = currentTheme === "dark"; return ( -
setShowFullNav(true)} - onMouseLeave={() => isDesktop && setShowFullNav(false)} - className="bg-[#F2F2F2] z-40 w-screen h-auto xl:w-auto xl:h-screen py-6 flex xl:flex-col justify-between items-center px-8 font-medium shadow-lg absolute left-0 top-0 xl:items-start" - > - -
- -
-
+ <> +
+
+ + + +
+
+ +
+
+
+ {isDark ? ( + 1440 ? "right" : "bottom"} + content={"Light Mode"} + > + + + ) : ( + 1440 ? "right" : "bottom"} + content={"Dark Mode"} + > + + + )} +
+
+ <> + {!!authenticatedUserAddress ? ( + 1440 ? "right" : "bottom"} + content={"Your wallet"} + > + + + ) : ( + 1440 ? "right" : "bottom"} + content={"Connect a Wallet"} + > + + + )} + +
+
+
+ + ); }; diff --git a/components/02-molecules/TheSidebarHeader.tsx b/components/02-molecules/TheSidebarHeader.tsx new file mode 100644 index 00000000..d2a37c05 --- /dev/null +++ b/components/02-molecules/TheSidebarHeader.tsx @@ -0,0 +1,41 @@ +import { CloseCTA, DisconnectWallet } from "@/components/01-atoms"; +import { useSidebar } from "@/lib/client/contexts/SidebarContext.tsx"; +import React from "react"; +import cc from "classcat"; +import { useTheme } from "next-themes"; + +export const TheSidebarHeader = () => { + const { systemTheme, theme } = useTheme(); + const currentTheme = theme === "system" ? systemTheme : theme; + const isDark = currentTheme === "dark"; + const { toggleSidebar } = useSidebar(); + + return ( +
+
+ toggleSidebar()} + className={cc([isDark ? "text-[#F6F6F1]" : "text-[#A3A9A5]"])} + /> +
+
+

+ Your wallet +

+ +
+
+ ); +}; diff --git a/components/02-molecules/TokenAmountSelectionModal.tsx b/components/02-molecules/TokenAmountSelectionModal.tsx new file mode 100644 index 00000000..11d20616 --- /dev/null +++ b/components/02-molecules/TokenAmountSelectionModal.tsx @@ -0,0 +1,139 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { SwapContext, SwapModalLayout } from "@/components/01-atoms"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { toastBlockchainTxError } from "@/lib/client/blockchain-utils"; +import { getTokenName } from "@/lib/client/ui-utils"; +import { + ERC20, + ERC20WithTokenAmountSelection, + EthereumAddress, + Token, +} from "@/lib/shared/types"; +import { useContext, useEffect, useState } from "react"; +import { useNetwork } from "wagmi"; +import toast from "react-hot-toast"; + +interface TokenAmountSelectionModalProps { + onCloseModal: () => void; + owner: EthereumAddress | null; + token: Token | null; +} + +export const TokenAmountSelectionModal = ({ + owner, + token, + onCloseModal, +}: TokenAmountSelectionModalProps) => { + const [tokenAmount, setTokenAmount] = useState(0); + const [userBalance, setUserBalance] = useState(0); + const { chain } = useNetwork(); + + const { authenticatedUserAddress } = useAuthenticatedUser(); + const { + authenticatedUserTokensList, + searchedUserTokensList, + setAuthenticatedUserTokensList, + setSearchedUserTokensList, + } = useContext(SwapContext); + + useEffect(() => { + if (chain?.id && token && owner) { + const balance = (token as ERC20).rawBalance; + + setUserBalance(balance); + } + }, [token, owner]); + + const closeAmountSelectionModal = () => { + if (!owner || !token) { + toastBlockchainTxError( + "No token or token's owner selected to set amount for.", + ); + throw new Error("No token or token's owner selected to set amount for."); + } + + const tokenOwnerIsAuthedUser = authenticatedUserAddress?.equals(owner); + + let originalTokensList: Token[]; + if (tokenOwnerIsAuthedUser) { + originalTokensList = [...authenticatedUserTokensList]; + } else { + originalTokensList = [...searchedUserTokensList]; + } + + if (!tokenAmount) { + toast.error("No Token amount was set.", { + id: "no-token-amount", + }); + + originalTokensList = originalTokensList.filter((tk) => tk !== token); + } else if (tokenAmount > userBalance) { + toast.error("The Token amount informed exceeds user's token balance.", { + id: "out-of-bounds-token-amount", + }); + + originalTokensList = originalTokensList.filter((tk) => tk !== token); + } else { + originalTokensList.map((token) => { + if (tokenAmount && token.contract === token.contract) { + (token as ERC20WithTokenAmountSelection).tokenAmount = tokenAmount; + } else if (!tokenAmount) { + originalTokensList = originalTokensList.filter( + (token) => token.contract !== token.contract, + ); + } + }); + } + + if (tokenOwnerIsAuthedUser) { + setAuthenticatedUserTokensList(originalTokensList); + } else { + setSearchedUserTokensList(originalTokensList); + } + + setUserBalance(0); + setTokenAmount(0); + + onCloseModal(); + }; + + if (!token) return null; + + return ( + +
+
+ setTokenAmount(Number(e.target.value))} + className="w-full rounded-lg rounded-r-none p-3 text-left bg-[#e0e0e0] dark:bg-[#282B29] border-[#353836] border-r-0 focus:outline-none" + id={token.tokenType + "-amount-selector"} + /> +
+ +
+ + + } + /> + ); +}; diff --git a/components/02-molecules/TokenCard.tsx b/components/02-molecules/TokenCard.tsx new file mode 100644 index 00000000..14fa6a2d --- /dev/null +++ b/components/02-molecules/TokenCard.tsx @@ -0,0 +1,265 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { SwapContext, SwaplaceIcon } from "@/components/01-atoms"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { + ERC20, + ERC721, + EthereumAddress, + Token, + TokenType, +} from "@/lib/shared/types"; +import { getTokenName } from "@/lib/client/ui-utils"; +import React, { useContext, useEffect, useState } from "react"; +import cc from "classcat"; +import toast from "react-hot-toast"; + +interface TokenCardProps { + tokenData: Token; + ownerAddress: EthereumAddress | null; + openTokenAmountSelectionModal?: ( + owner: EthereumAddress, + token: Token, + ) => void; + onClickAction?: TokenCardActionType; + + /* + When true, instead of displaying an ERC20 Token balance + the TokenCard will display the ERC20 Token amount + selected by the user for the swap transaction + */ + displayERC20TokensAmount?: boolean; + withSelectionValidation?: boolean; + styleType?: StyleVariant; +} + +export enum TokenCardActionType { + "SELECT_TOKEN_FOR_SWAP", + "APPROVE_TOKEN_SWAP", + "SHOW_NFT_DETAILS", + "NO_ACTION", +} + +export enum TokenCardStyleType { + SMALL = "small", + NORMAL = "normal", + MEDIUM = "medium", + LARGE = "large", +} + +type StyleVariant = + | TokenCardStyleType + | "small" + | "normal" + | "medium" + | "large"; + +export const TokenSizeClassNames = { + [TokenCardStyleType.SMALL]: "card-token-small", + [TokenCardStyleType.NORMAL]: "card-token-normal", + [TokenCardStyleType.MEDIUM]: "card-token-medium", + [TokenCardStyleType.LARGE]: "card-token-large", +}; + +/** + * TokenCard Component + * + * This component is responsible for rendering and interacting with a token card. + * It supports features such as displaying token information, handling user interaction, + * and triggering actions based on different scenarios. + * + * @param tokenData - Data representing the token, including its type, ID, and image. + * @param ownerAddress - The address of the token owner. + * @param openTokenAmountSelectionModal - Function to open a modal for selecting token amount. + * @param withSelectionValidation - Flag indicating whether to validate token selection. + * @param displayERC20TokensAmount - Flag indicating whether to display ERC20 token amounts. + * @param styleType - Style type for the token card (e.g., normal). + * @param onClickAction - Action type to be performed on token card click. + */ + +export const TokenCard = ({ + tokenData, + ownerAddress, + openTokenAmountSelectionModal, + withSelectionValidation = true, + displayERC20TokensAmount = false, + styleType = TokenCardStyleType.NORMAL, + onClickAction = TokenCardActionType.SELECT_TOKEN_FOR_SWAP, +}: TokenCardProps) => { + const { authenticatedUserAddress } = useAuthenticatedUser(); + const { + setAuthenticatedUserTokensList, + setSearchedUserTokensList, + authenticatedUserTokensList, + searchedUserTokensList, + } = useContext(SwapContext); + const [currentNftIsSelected, setCurrentNftIsSelected] = useState(false); + const [couldntLoadNftImage, setCouldntLoadNftImage] = useState(false); + + const [tokenDisplayableData, setDisplayableData] = useState({ + id: "", + image: "", + }); + + useEffect(() => { + const displayableData = { ...tokenDisplayableData }; + + switch (tokenData.tokenType) { + case TokenType.ERC20: + if ((tokenData as ERC20).symbol) { + displayableData.image = (tokenData as ERC20).symbol as string; + } else { + displayableData.image = ""; + } + + if ((tokenData as ERC20).id) { + displayableData.id = (tokenData as ERC20).id as string; + } + case TokenType.ERC721: + if ((tokenData as ERC721).metadata?.image) { + displayableData.image = (tokenData as ERC721).metadata + ?.image as string; + } else { + displayableData.image = ""; + } + if ((tokenData as ERC721).id) { + displayableData.id = (tokenData as ERC721).id as string; + } + } + + setDisplayableData(displayableData); + }, [tokenData]); + + useEffect(() => { + const currentNftIsFromAuthedUser = ownerAddress + ? authenticatedUserAddress?.equals(ownerAddress) + : false; + + if (currentNftIsFromAuthedUser) { + setCurrentNftIsSelected( + authenticatedUserTokensList.some( + (selectedNft) => selectedNft.id === tokenData.id, + ), + ); + } else { + setCurrentNftIsSelected( + searchedUserTokensList.some( + (selectedNft) => selectedNft.id === tokenData.id, + ), + ); + } + }, [ + authenticatedUserAddress, + authenticatedUserTokensList, + searchedUserTokensList, + ownerAddress, + tokenData, + ]); + + const onCardClick = () => { + if ( + onClickAction === TokenCardActionType.SELECT_TOKEN_FOR_SWAP && + ownerAddress + ) { + const ownerEthAddress = ownerAddress; + + if (authenticatedUserAddress?.equals(ownerEthAddress)) { + const isSelected = authenticatedUserTokensList.some( + (selectedNft) => selectedNft.id === tokenData.id, + ); + + if (isSelected) { + setAuthenticatedUserTokensList((prevNftAuthUser) => + prevNftAuthUser.filter((selectedNft) => { + return selectedNft.id !== tokenData.id; + }), + ); + } else { + setAuthenticatedUserTokensList((prevNftAuthUser) => [ + ...prevNftAuthUser, + tokenData, + ]); + + if (tokenData.tokenType === TokenType.ERC20) { + openTokenAmountSelectionModal?.(ownerEthAddress, tokenData); + } + } + } else { + const isSelected = searchedUserTokensList.some( + (selectedNft) => selectedNft.id === tokenData.id, + ); + + if (isSelected) { + setSearchedUserTokensList((prevNftInputUser) => { + return prevNftInputUser.filter((selectedNft) => { + return selectedNft.id !== tokenData.id; + }); + }); + } else { + setSearchedUserTokensList((prevNftInputUser) => [ + ...prevNftInputUser, + tokenData, + ]); + + if (tokenData.tokenType === TokenType.ERC20) { + openTokenAmountSelectionModal?.(ownerEthAddress, tokenData); + } + } + } + } else if (onClickAction === TokenCardActionType.SHOW_NFT_DETAILS) { + navigator.clipboard.writeText(JSON.stringify(tokenData)); + toast.success("NFT data copied to your clipboard"); + } + }; + + const handleImageLoadError = () => { + setCouldntLoadNftImage(true); + }; + + const ButtonLayout = (children: React.ReactNode) => { + return ( + + ); + }; + + return tokenDisplayableData.image && !couldntLoadNftImage ? ( + <> + {ButtonLayout( + {getTokenName(tokenData)}, + )} + + ) : ( + <> + {ButtonLayout( +
+ {getTokenName(tokenData, { + withAmountPrefix: tokenData.tokenType === TokenType.ERC20, + displayTokenAmount: displayERC20TokensAmount, + })} +
, + )} + + ); +}; diff --git a/components/02-molecules/TokensList.tsx b/components/02-molecules/TokensList.tsx new file mode 100644 index 00000000..ab90135a --- /dev/null +++ b/components/02-molecules/TokensList.tsx @@ -0,0 +1,133 @@ +import { TokensShelfVariant } from "@/components/03-organisms"; +import { + AddTokenCardManually, + TokenAmountSelectionModal, + TokenCard, + TokenCardActionType, + TokenCardStyleType, +} from "@/components/02-molecules"; +import { TokenCardsPlaceholder } from "@/components/01-atoms"; +import { ERC20, EthereumAddress, Token } from "@/lib/shared/types"; +import { EMPTY_ERC_20_BALANCE } from "@/lib/client/blockchain-utils"; +import { useState } from "react"; + +export interface TokensListProps { + tokensList: Token[]; + ownerAddress: EthereumAddress | null; + withSelectionValidation?: boolean; + withPlaceholders?: boolean; + withAddTokenCard?: boolean; + mobileTotalCards?: number; + tabletTotalCards?: number; + desktopTotalCards?: number; + wideScreenTotalCards?: number; + + /* + When true, instead of displaying an ERC20 Token balance + the TokenCard will display the ERC20 Token amount + selected by the user for the swap transaction + */ + displayERC20TokensAmount?: boolean; + tokenCardStyleType?: TokenCardStyleType; + tokenCardClickAction?: TokenCardActionType; + variant: TokensShelfVariant; + gridClassNames?: string; +} + +/** + * Renders a list of tokens associated with a user's account. + * + * This component allows users to view a list of tokens associated with a specific account. + * It provides flexibility in displaying tokens based on various parameters and screen sizes. + * Users can interact with individual tokens, including selecting tokens for swapping and viewing token amounts. + * Additionally, the component supports the addition of custom styling and actions for token cards. + * + **/ + +export const TokensList = ({ + tokensList, + ownerAddress, + mobileTotalCards, + tabletTotalCards, + desktopTotalCards, + wideScreenTotalCards, + withPlaceholders = true, + withAddTokenCard = true, + withSelectionValidation = true, + displayERC20TokensAmount = false, + variant = TokensShelfVariant.Your, + tokenCardStyleType = TokenCardStyleType.NORMAL, + tokenCardClickAction = TokenCardActionType.SELECT_TOKEN_FOR_SWAP, + gridClassNames = "w-full h-full grid grid-cols-3 md:grid-cols-6 lg:grid-cols-6 gap-3", +}: TokensListProps) => { + const [selectTokenAmountOf, setSelectTokenAmountOf] = + useState(null); + const [selectTokenAmountFor, setSelectTokenAmountFor] = + useState(null); + + const openTokenAmountSelectionModal = ( + owner: EthereumAddress, + token: Token, + ) => { + setSelectTokenAmountFor(token); + setSelectTokenAmountOf(owner); + }; + + const onCloseModal = () => { + setSelectTokenAmountFor(null); + setSelectTokenAmountOf(null); + }; + + /* Filter TokenList so that TokenCard receives the filtered array and does not display tokens with a zero balance on the screen */ + tokensList = tokensList.filter( + (token) => (token as ERC20).rawBalance !== EMPTY_ERC_20_BALANCE, + ); + + const placeholders = withPlaceholders + ? TokenCardsPlaceholder({ + totalCardsLength: tokensList.length, + mobileTotalSquares: mobileTotalCards, + tabletTotalSquares: tabletTotalCards, + desktopTotalSquares: desktopTotalCards, + wideScreenTotalSquares: wideScreenTotalCards, + styleType: tokenCardStyleType, + }) + : [<>]; + const tokenCards = tokensList.map((token: Token, index) => ( +
+ +
+ )); + + let allSquares = [...tokenCards, ...placeholders]; + + const addTokenSquare = withAddTokenCard ? AddTokenCardManually() : <>; + + const Layout = (squares: React.JSX.Element[]) => { + return ( +
+ {squares} + +
+ ); + }; + + if (variant === TokensShelfVariant.Your) { + placeholders.pop(); // Removes the last element to fill with addToken + allSquares = [...allSquares, addTokenSquare]; + return Layout(allSquares); + } + return Layout(allSquares); +}; diff --git a/components/02-molecules/UserInfo.tsx b/components/02-molecules/UserInfo.tsx new file mode 100644 index 00000000..12dd4c5c --- /dev/null +++ b/components/02-molecules/UserInfo.tsx @@ -0,0 +1,14 @@ +import { + AccountBalanceWalletSidebar, + EnsNameAndAddressWallet, +} from "@/components/02-molecules"; +import React from "react"; + +export const UserInfo = () => { + return ( +
+ + +
+ ); +}; diff --git a/components/02-molecules/UserOfferInfo.tsx b/components/02-molecules/UserOfferInfo.tsx new file mode 100644 index 00000000..04674634 --- /dev/null +++ b/components/02-molecules/UserOfferInfo.tsx @@ -0,0 +1,73 @@ +import { ENSAvatar, ENSAvatarSize } from "@/components/01-atoms"; +import { useEnsData } from "@/lib/client/hooks/useENSData"; +import { EthereumAddress } from "@/lib/shared/types"; + +export enum UserOfferVariant { + DEFAULT = "default", + SECONDARY = "secondary", +} +interface UserOfferInfoProps { + address: EthereumAddress | null; + variant?: UserOfferVariant; +} + +export const UserOfferInfo = ({ + address, + variant = UserOfferVariant.DEFAULT, +}: UserOfferInfoProps) => { + const { primaryName } = useEnsData({ + ensAddress: address, + }); + const displayAddress = address?.getEllipsedAddress(); + return variant == UserOfferVariant.DEFAULT ? ( +
+
+
+ {address && ( + + )} +
+
+ {primaryName ? ( +

{primaryName} gets

+ ) : ( +

{displayAddress} gets

+ )} +
+
+
+ ) : ( + variant === UserOfferVariant.SECONDARY && ( +
+
+
+
+ {address && ( + + )} +
+
+ {primaryName ? ( +

{primaryName} gets

+ ) : ( +

{displayAddress} gets

+ )} +
+
+ {/* TODO > Include logic to calculate tokens value */} + {/*
+

+ 0.1639 ETH +

+

+   ($252.15) +

+
*/} +
+
+ ) + ); +}; diff --git a/components/02-molecules/index.ts b/components/02-molecules/index.ts new file mode 100644 index 00000000..f4d88b06 --- /dev/null +++ b/components/02-molecules/index.ts @@ -0,0 +1,19 @@ +export * from "./AccountBalanceWalletSidebar"; +export * from "./AddTokenCardManually"; +export * from "./AddTokenOrSwapManuallyModal"; +export * from "./CardOffers"; +export * from "./ConfirmSwapModal"; +export * from "./CopyAdressButton"; +export * from "./EnsNameAndAddressWallet"; +export * from "./FilterOffers"; +export * from "./OfferSummary"; +export * from "./ProgressStatus"; +export * from "./SelectChainNetwork"; +export * from "./SwapOffersLayout"; +export * from "./TheHeader"; +export * from "./TheSidebarHeader"; +export * from "./TokenAmountSelectionModal"; +export * from "./TokenCard"; +export * from "./TokensList"; +export * from "./UserInfo"; +export * from "./UserOfferInfo"; diff --git a/components/02-molecules/index.tsx b/components/02-molecules/index.tsx deleted file mode 100644 index 9ff6d1dd..00000000 --- a/components/02-molecules/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -export * from "./CardHome"; -export * from "./TheHeader"; -export * from "../03-organisms/NftsShelf"; -export * from "./NftsList"; -export * from "./SwapStation"; -export * from "./OfferSummary"; diff --git a/components/03-organisms/ApproveTokenCard.tsx b/components/03-organisms/ApproveTokenCard.tsx new file mode 100644 index 00000000..634e453f --- /dev/null +++ b/components/03-organisms/ApproveTokenCard.tsx @@ -0,0 +1,209 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { + TokenCard, + TokenCardActionType, + TokenCardStyleType, +} from "@/components/02-molecules"; +import { + getTokenAmountOrId, + toastBlockchainTxError, +} from "@/lib/client/blockchain-utils"; +import { approveSwap } from "@/lib/service/approveSwap"; +import { SWAPLACE_SMART_CONTRACT_ADDRESS } from "@/lib/client/constants"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { isTokenSwapApproved } from "@/lib/service/verifyTokensSwapApproval"; +import { IApproveTokenSwap } from "@/lib/client/swap-utils"; +import { getTokenName } from "@/lib/client/ui-utils"; +import { Token } from "@/lib/shared/types"; +import toast from "react-hot-toast"; +import { type TransactionReceipt } from "viem"; +import { type WalletClient, useNetwork, useWalletClient } from "wagmi"; +import cc from "classcat"; +import { useEffect, useState } from "react"; + +interface ApproveTokenCardProps { + token: Token; + setTokenWasApprovedForSwap: (token: Token) => void; +} + +enum TokenApprovalStatus { + CLICK_TO_APPROVE = "CLICK_TO_APPROVE", + APPROVE_IN_YOUR_WALLET = "APPROVE_IN_YOUR_WALLET", + WAITING_BLOCKCHAIN_CONFIRMATION = "WAITING_BLOCKCHAIN_CONFIRMATION", + APPROVED = "APPROVED", +} + +export const ApproveTokenCard = ({ + token, + setTokenWasApprovedForSwap, +}: ApproveTokenCardProps) => { + const { chain } = useNetwork(); + const { data: walletClient } = useWalletClient(); + + const [isApproved, setIsApproved] = useState(false); + const [tokenApprovalStatus, setTokenApprovalStatus] = useState( + TokenApprovalStatus.CLICK_TO_APPROVE, + ); + + const { authenticatedUserAddress } = useAuthenticatedUser(); + + const checkForTokenApproval = async (token: Token) => { + let chainId: number | undefined = undefined; + + if (typeof chain?.id != "undefined") { + chainId = chain?.id; + } + + if (!chainId) { + throw new Error("User is not connected to any network"); + } + + const approved = await isTokenSwapApproved({ + token, + chainId, + }); + + setIsApproved(approved); + + return approved; + }; + + const handleTokenApproval = async () => { + let chainId: number | undefined = undefined; + + if (typeof chain?.id != "undefined") { + chainId = chain?.id; + } + + if (!chainId) { + throw new Error("User is not connected to any network"); + } + + setTokenApprovalStatus(TokenApprovalStatus.APPROVE_IN_YOUR_WALLET); + + const approved = await checkForTokenApproval(token); + + if (approved) { + toast.success(`${getTokenName(token)} was approved for swap`); + } else { + await askForTokenApproval(token).then((isApproved) => { + if (typeof isApproved !== "undefined") { + setIsApproved(true); + } + }); + } + }; + + useEffect(() => { + checkForTokenApproval(token); + }, []); + + useEffect(() => { + if (isApproved) { + setTokenWasApprovedForSwap(token); + setTokenApprovalStatus(TokenApprovalStatus.APPROVED); + } + }, [isApproved]); + + const askForTokenApproval = async ( + token: Token, + ): Promise => { + let chainId: number | undefined = undefined; + + if (typeof chain?.id != "undefined") { + chainId = chain?.id; + } + + if (!chainId || !walletClient) { + throw new Error("User's wallet is not connected"); + } + + if (!token.contract) + throw new Error(`Token contract is not defined for: ${token}`); + + const swapData: IApproveTokenSwap = { + walletClient: walletClient as WalletClient, + spender: SWAPLACE_SMART_CONTRACT_ADDRESS[chainId] as `0x${string}`, + tokenContractAddress: token.contract as `0x${string}`, + amountOrId: getTokenAmountOrId(token), + chainId, + token, + onWalletConfirmation: () => + setTokenApprovalStatus( + TokenApprovalStatus.WAITING_BLOCKCHAIN_CONFIRMATION, + ), + }; + + try { + const transactionReceipt = await approveSwap(swapData); + + if (transactionReceipt.success) { + toast.success(`'${getTokenName(token)}' swap was approved`); + setTokenWasApprovedForSwap(token); + + // Below alias is always valid since whenever a tx is successful, a receipt is returned + return transactionReceipt.receipt as TransactionReceipt; + } else { + setTokenApprovalStatus(TokenApprovalStatus.CLICK_TO_APPROVE); + toastBlockchainTxError(transactionReceipt.errorMessage || ""); + } + } catch (error) { + // TODO: map error scenarios and create corresponding error triggers + setTokenApprovalStatus(TokenApprovalStatus.CLICK_TO_APPROVE); + toastBlockchainTxError(String(error)); + console.error(error); + } + }; + + if (!authenticatedUserAddress) return null; + + return ( +
handleTokenApproval()} + role="button" + > +
+ +
+
+
+

{getTokenName(token)}

+
+
+ {tokenApprovalStatus === TokenApprovalStatus.CLICK_TO_APPROVE ? ( +

+ CLICK TO APPROVE +

+ ) : tokenApprovalStatus === + TokenApprovalStatus.APPROVE_IN_YOUR_WALLET ? ( +

+ APPROVE TRANSACTION REQUEST IN YOUR WALLET +

+ ) : tokenApprovalStatus === + TokenApprovalStatus.WAITING_BLOCKCHAIN_CONFIRMATION ? ( +

+ WAITING FOR BLOCKCHAIN CONFIRMATION +

+ ) : TokenApprovalStatus.APPROVED ? ( +
+

APPROVED

+
+ ) : null} +
+
+
+ ); +}; diff --git a/components/03-organisms/NftsShelf.tsx b/components/03-organisms/NftsShelf.tsx deleted file mode 100644 index ad324413..00000000 --- a/components/03-organisms/NftsShelf.tsx +++ /dev/null @@ -1,124 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { NftsList } from "../02-molecules"; -import { SwapContext, SwapIcon } from "../01-atoms"; -import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; - -import { NFT, ChainInfo, NFTsQueryStatus } from "@/lib/client/constants"; -import { getNftsFrom } from "@/lib/client/blockchain-data"; -import { EthereumAddress } from "@/lib/shared/types"; -import { useContext, useEffect, useState } from "react"; -import { useNetwork } from "wagmi"; - -/** - * - * The Shelf component display the NFTs of given address. - * - * @returns Shelf Nfts based in status of given address - */ - -interface INftsShelfProps { - address: string | null; -} - -export const NftsShelf = ({ address }: INftsShelfProps) => { - const { chain } = useNetwork(); - const [nftsList, setNftsList] = useState(); - const [nftsQueryStatus, setNftsQueryStatus] = useState( - NFTsQueryStatus.EMPTY_QUERY - ); - - const { authenticatedUserAddress } = useAuthenticatedUser(); - const { validatedAddressToSwap, inputAddress, destinyChain } = - useContext(SwapContext); - - useEffect(() => { - const chainId = - address === authenticatedUserAddress?.address - ? chain?.id - : ChainInfo[destinyChain].id; - - if (address && chainId) { - getNftsFrom(address, chainId, setNftsQueryStatus) - .then((nftsList) => { - setNftsList(nftsList); - }) - .catch(() => { - setNftsList([]); - }); - } - }, [address, chain, destinyChain]); - - useEffect(() => { - if ( - authenticatedUserAddress && - address && - authenticatedUserAddress.equals(new EthereumAddress(address)) - ) { - setNftsList([]); - setNftsQueryStatus(NFTsQueryStatus.EMPTY_QUERY); - } - }, [destinyChain]); - - useEffect(() => { - if (address !== authenticatedUserAddress?.address) { - setNftsList([]); - setNftsQueryStatus(NFTsQueryStatus.EMPTY_QUERY); - } - }, [chain]); - - useEffect(() => { - if ( - address !== authenticatedUserAddress?.address && - validatedAddressToSwap !== authenticatedUserAddress?.address - ) { - setNftsList([]); - setNftsQueryStatus(NFTsQueryStatus.EMPTY_QUERY); - } - }, [inputAddress]); - - useEffect(() => { - if (!validatedAddressToSwap) { - setNftsQueryStatus(NFTsQueryStatus.EMPTY_QUERY); - } - }, [validatedAddressToSwap]); - - return ( -
-
-
- {nftsQueryStatus == NFTsQueryStatus.WITH_RESULTS && nftsList ? ( -
- -
- ) : nftsQueryStatus == NFTsQueryStatus.EMPTY_QUERY || !address ? ( -
-
- -

- Select a user to start swapping -

-
-
- ) : nftsQueryStatus == NFTsQueryStatus.NO_RESULTS ? ( -
-
-

- Given address has no NFTs associated in the given network -

-
-
- ) : nftsQueryStatus == NFTsQueryStatus.LOADING ? ( -
-
-

- Loading NFTs of{" "} - {new EthereumAddress(address).getEllipsedAddress()}... -

-
-
- ) : null} -
-
-
- ); -}; diff --git a/components/03-organisms/SwapConnection.tsx b/components/03-organisms/SwapConnection.tsx new file mode 100644 index 00000000..0126c71e --- /dev/null +++ b/components/03-organisms/SwapConnection.tsx @@ -0,0 +1,17 @@ +import { SearchBar } from "@/components/01-atoms"; +import { SelectChainNetwork } from "@/components/02-molecules"; + +export const SwapConnection = () => { + return ( + <> +
+
+ +
+
+ +
+
+ + ); +}; diff --git a/components/03-organisms/SwapStation.tsx b/components/03-organisms/SwapStation.tsx new file mode 100644 index 00000000..83e42775 --- /dev/null +++ b/components/03-organisms/SwapStation.tsx @@ -0,0 +1,122 @@ +import { + PaperPlane, + SwapContext, + SwapExpireTime, + SwapIcon, + SwapIconVariant, + Tooltip, +} from "@/components/01-atoms"; +import { ConfirmSwapModal, OfferSummary } from "@/components/02-molecules"; +import { TokensShelfVariant } from "@/components/03-organisms"; +import { useContext, useEffect, useState } from "react"; +import cc from "classcat"; +import { toast } from "react-hot-toast"; + +export const SwapStation = () => { + const [isValidSwap, setIsValidSwap] = useState(false); + + const { + authenticatedUserTokensList, + searchedUserTokensList, + validatedAddressToSwap, + } = useContext(SwapContext); + + useEffect(() => { + setIsValidSwap( + !!authenticatedUserTokensList.length && + !!searchedUserTokensList.length && + !!validatedAddressToSwap, + ); + }, [ + authenticatedUserTokensList, + searchedUserTokensList, + validatedAddressToSwap, + ]); + + const [openConfirmationModal, setOpenConfirmationModal] = + useState(false); + + const validateSwapSending = () => { + if (!isValidSwap) { + if (!validatedAddressToSwap) { + toast.error("You must select a destiny wallet to swap tokens with"); + return; + } + + if (!authenticatedUserTokensList.length) { + toast.error("You must select at least one NFT from yours to swap"); + return; + } + + if (!searchedUserTokensList.length) { + toast.error( + "You must select at least one NFT from the destiny wallet to swap", + ); + return; + } + } else { + setOpenConfirmationModal(true); + } + }; + + return ( +
+
+
+

+ Swap Station +

+ +
+
+ + + +
+ +
+
+ +
+ +
+
+
+ + setOpenConfirmationModal(false)} + /> +
+ ); +}; diff --git a/components/03-organisms/SwappingShelfs.tsx b/components/03-organisms/SwappingShelfs.tsx index 6d9f8315..1be8abe7 100644 --- a/components/03-organisms/SwappingShelfs.tsx +++ b/components/03-organisms/SwappingShelfs.tsx @@ -1,11 +1,23 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import { NftsShelf } from "@/components/02-molecules"; -import { SwapContext, SwappingShelfID, Tab } from "@/components/01-atoms/"; +import { TokensShelf, TokensShelfVariant } from "@/components/03-organisms"; +import { + SearchItemsShelf, + SwapContext, + SwappingShelfID, + TokensShelfTab, +} from "@/components/01-atoms/"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { useContext, useEffect, useState } from "react"; import { useNetwork } from "wagmi"; import cc from "classcat"; +/** + * SwappingShelfs Component + * + * React component that display of tokens swapping shelves. + * + * @return The rendered SwappingShelfs component. + */ export const SwappingShelfs = () => { const { chain } = useNetwork(); const { authenticatedUserAddress } = useAuthenticatedUser(); @@ -14,27 +26,44 @@ export const SwappingShelfs = () => { const { validatedAddressToSwap, - setNftAuthUser, - setNftInputUser, + setAuthenticatedUserTokensList, + setSearchedUserTokensList, setInputAddress, } = useContext(SwapContext); useEffect(() => { - setNftAuthUser([]); - setNftInputUser([]); + setAuthenticatedUserTokensList([]); + setSearchedUserTokensList([]); setInputAddress(""); }, [chain]); return ( -
- setActiveSwappingShelfID(input)} - /> -
- +
+
+
+ + setActiveSwappingShelfID(input) + } + /> +
+
+ +
-
- +
+
+ +
+
+ +
); diff --git a/components/03-organisms/TokenOffers.tsx b/components/03-organisms/TokenOffers.tsx new file mode 100644 index 00000000..dde20bb8 --- /dev/null +++ b/components/03-organisms/TokenOffers.tsx @@ -0,0 +1,90 @@ +import { CardOffers } from "@/components/02-molecules"; +import { + TokenOfferDetails, + SwapIcon, + SwapContext, + SwapIconVariant, +} from "@/components/01-atoms"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import cc from "classcat"; +import { useContext } from "react"; + +export enum TokenOfferVariant { + HORIZONTAL = "horizontal", + VERTICAL = "vertical", +} + +interface TokenOffersProps { + variant?: TokenOfferVariant; +} + +interface TokenOffersConfig { + body: React.ReactNode; +} + +export const TokenOffers = ({ + variant = TokenOfferVariant.VERTICAL, +}: TokenOffersProps) => { + const { authenticatedUserAddress } = useAuthenticatedUser(); + const { validatedAddressToSwap } = useContext(SwapContext); + + const HorizontalVariant = () => { + return ( +
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ ); + }; + + const VerticalVariant = () => { + return ( +
+
+
+ +
+ +
+
+ +
+
+ +
+ +
+
+
+ ); + }; + + const TokenOffersPropsConfig: Record = { + [TokenOfferVariant.HORIZONTAL]: { + body: , + }, + [TokenOfferVariant.VERTICAL]: { + body: , + }, + }; + + return <>{TokenOffersPropsConfig[variant].body}; +}; diff --git a/components/03-organisms/TokensShelf.tsx b/components/03-organisms/TokensShelf.tsx new file mode 100644 index 00000000..bfc1046f --- /dev/null +++ b/components/03-organisms/TokensShelf.tsx @@ -0,0 +1,186 @@ +import { ChainInfo, TokensQueryStatus } from "@/lib/client/constants"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { + getERC721TokensFromAddress, + getERC20TokensFromAddress, +} from "@/lib/client/blockchain-utils"; +import { EthereumAddress, Token } from "@/lib/shared/types"; +import { TokensList } from "@/components/02-molecules"; +import { SelectUserIcon, SwapContext } from "@/components/01-atoms"; +import { useContext, useEffect, useState } from "react"; +import { useTheme } from "next-themes"; +import { useNetwork } from "wagmi"; +/* eslint-disable react-hooks/exhaustive-deps */ + +export enum TokensShelfVariant { + Your, + Their, +} + +interface TokensShelfProps { + address: EthereumAddress | null; + variant: TokensShelfVariant; +} + +/** + * + * The Shelf component display the tokens of a given address. + * @param address + * + * @returns Tokens Shelf based in status of given address + */ +export const TokensShelf = ({ address, variant }: TokensShelfProps) => { + const { chain } = useNetwork(); + const [allTokensList, setAllTokensList] = useState([]); + const [tokensQueryStatus, setTokensQueryStatus] = useState( + TokensQueryStatus.EMPTY_QUERY, + ); + const { theme } = useTheme(); + + const { authenticatedUserAddress } = useAuthenticatedUser(); + const { validatedAddressToSwap, inputAddress, destinyChain } = + useContext(SwapContext); + + const getUserTokens = async () => { + const chainId = authenticatedUserAddress?.equals(address) + ? chain?.id + : ChainInfo[destinyChain].id; + + let queriedTokens: Token[] = []; + let tokensCount = allTokensList.length; + + if (address && chainId) { + setTokensQueryStatus(TokensQueryStatus.LOADING); + + Promise.all([ + getERC721TokensFromAddress(address, chainId).then((tokens) => { + queriedTokens = [...queriedTokens, ...tokens]; + tokensCount = tokensCount + tokens.length; + }), + getERC20TokensFromAddress(address, chainId).then((tokens) => { + queriedTokens = [...queriedTokens, ...tokens]; + tokensCount = tokensCount + tokens.length; + }), + ]) + .catch(() => { + setTokensQueryStatus(TokensQueryStatus.ERROR); + queriedTokens = []; + }) + .finally(() => { + if (tokensCount === 0) { + setTokensQueryStatus(TokensQueryStatus.NO_RESULTS); + } else { + setAllTokensList(queriedTokens); + setTokensQueryStatus(TokensQueryStatus.WITH_RESULTS); + } + }); + } + }; + + useEffect(() => { + getUserTokens(); + }, [address, chain, destinyChain]); + + const conditionallyCleanTokensList = (condition: boolean) => { + if (condition) { + setAllTokensList([]); + setTokensQueryStatus(TokensQueryStatus.EMPTY_QUERY); + } + }; + + useEffect(() => { + conditionallyCleanTokensList( + !authenticatedUserAddress && variant === TokensShelfVariant.Your, + ); + }, [authenticatedUserAddress]); + + useEffect(() => { + conditionallyCleanTokensList( + !!authenticatedUserAddress && + !!address && + authenticatedUserAddress.equals(address) && + variant === TokensShelfVariant.Their, + ); + }, [variant]); + + useEffect(() => { + conditionallyCleanTokensList( + !!authenticatedUserAddress && + !!address && + authenticatedUserAddress.equals(address), + ); + }, [destinyChain]); + + useEffect(() => { + conditionallyCleanTokensList( + !authenticatedUserAddress?.equals(address) && + variant === TokensShelfVariant.Their, + ); + }, [chain]); + + useEffect(() => { + conditionallyCleanTokensList( + !authenticatedUserAddress?.equals(address) && + !validatedAddressToSwap?.equals(authenticatedUserAddress), + ); + }, [inputAddress]); + + useEffect(() => { + conditionallyCleanTokensList( + !validatedAddressToSwap && variant === TokensShelfVariant.Their, + ); + }, [validatedAddressToSwap]); + + return ( +
+ {tokensQueryStatus == TokensQueryStatus.WITH_RESULTS && allTokensList ? ( +
+ +
+ ) : tokensQueryStatus == TokensQueryStatus.EMPTY_QUERY || !address ? ( +
+
+
+ +
+
+

+ {variant === TokensShelfVariant.Their + ? "No user selected yet" + : "No wallet is connected yet"} +

+

+ {variant === TokensShelfVariant.Their + ? "Search for a user to start swapping items" + : "Sign in to see your tokens"} +

+
+
+
+ ) : tokensQueryStatus == TokensQueryStatus.NO_RESULTS ? ( +
+
+

+ Given address has no tokens associated in the given network +

+
+
+ ) : tokensQueryStatus == TokensQueryStatus.LOADING ? ( +
+
+

+ Loading tokens of {address.getEllipsedAddress()}... +

+
+
+ ) : null} +
+ ); +}; diff --git a/components/03-organisms/WalletSidebarTemplate.tsx b/components/03-organisms/WalletSidebarTemplate.tsx new file mode 100644 index 00000000..04d81399 --- /dev/null +++ b/components/03-organisms/WalletSidebarTemplate.tsx @@ -0,0 +1,49 @@ +import { TheSidebarHeader, UserInfo } from "@/components/02-molecules"; +import { useSidebar } from "@/lib/client/contexts/SidebarContext.tsx"; +import React from "react"; +import cc from "classcat"; +import { useTheme } from "next-themes"; + +interface WalletSidebarTemplateProps { + isOpen: boolean; + isMobile: boolean; +} + +export const WalletSidebarTemplate = ({ + isOpen, + isMobile, +}: WalletSidebarTemplateProps) => { + const { systemTheme, theme } = useTheme(); + const currentTheme = theme === "system" ? systemTheme : theme; + const isDark = currentTheme === "dark"; + const { toggleSidebar } = useSidebar(); + + return ( + <> +
toggleSidebar()} + /> + +
+
+ + +
+
+ + ); +}; diff --git a/components/03-organisms/index.ts b/components/03-organisms/index.ts new file mode 100644 index 00000000..0ea91b69 --- /dev/null +++ b/components/03-organisms/index.ts @@ -0,0 +1,7 @@ +export * from "./ApproveTokenCard"; +export * from "./SwapConnection"; +export * from "./SwapStation"; +export * from "./SwappingShelfs"; +export * from "./TokenOffers"; +export * from "./TokensShelf"; +export * from "./WalletSidebarTemplate"; diff --git a/components/03-organisms/index.tsx b/components/03-organisms/index.tsx deleted file mode 100644 index fa5458de..00000000 --- a/components/03-organisms/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from "./SwappingShelfs"; diff --git a/components/04-templates/HomeSection.tsx b/components/04-templates/HomeSection.tsx deleted file mode 100644 index 917660c8..00000000 --- a/components/04-templates/HomeSection.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { CardHome } from "@/components/02-molecules"; - -export const HomeSection = () => { - return ( -
- -
- ); -}; diff --git a/components/04-templates/Layout.tsx b/components/04-templates/Layout.tsx index abd8348f..7e59f320 100644 --- a/components/04-templates/Layout.tsx +++ b/components/04-templates/Layout.tsx @@ -1,20 +1,33 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import { useAuthedAccess } from "@/lib/client/hooks/useAuthedAccess"; -import { useRouter } from "next/router"; +import { SidebarProvider } from "@/lib/client/contexts/SidebarContext.tsx"; +import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { useSupportedNetworks } from "@/lib/client/hooks/useSupportedNetworks"; import { useEffect } from "react"; -import { useAccount } from "wagmi"; +import toast from "react-hot-toast"; +import { sepolia, useSwitchNetwork } from "wagmi"; export const Layout = ({ children }: { children: React.ReactNode }) => { - useAuthedAccess(); - - const router = useRouter(); - const { isConnected } = useAccount(); + const { isNetworkSupported } = useSupportedNetworks(); + const { switchNetwork } = useSwitchNetwork(); + const { authenticatedUserAddress } = useAuthenticatedUser(); useEffect(() => { - if (!isConnected) { - router.push("/"); + if (authenticatedUserAddress && !isNetworkSupported) { + toast.error("Network not supported, change network and try again", { + duration: 5000, + id: "network-toast", + }); + switchNetwork && switchNetwork(sepolia.id); } - }, [isConnected]); + }, [authenticatedUserAddress, isNetworkSupported]); - return <>{children}; + return ( + + + {children} + + ); }; diff --git a/components/04-templates/OfferSection.tsx b/components/04-templates/OfferSection.tsx new file mode 100644 index 00000000..3eac0767 --- /dev/null +++ b/components/04-templates/OfferSection.tsx @@ -0,0 +1,20 @@ +import { TokenOffers } from "@/components/03-organisms"; +import { FilterOffers, TheHeader } from "@/components/02-molecules"; + +export const OfferSection = () => { + return ( +
+ +
+
+
+ +
+
+ +
+
+
+
+ ); +}; diff --git a/components/04-templates/SwapSection.tsx b/components/04-templates/SwapSection.tsx index 33651c15..28af2ccd 100644 --- a/components/04-templates/SwapSection.tsx +++ b/components/04-templates/SwapSection.tsx @@ -1,15 +1,25 @@ -import { SearchBar } from "@/components/01-atoms"; -import { SwappingShelfs } from "@/components/03-organisms"; -import { SwapStation } from "@/components/02-molecules"; +import { TheHeader } from "@/components/02-molecules"; +import { + SwapConnection, + SwapStation, + SwappingShelfs, +} from "@/components/03-organisms"; export const SwapSection = () => { return ( -
-
- - +
+ +
+
+
+ + +
+
+ +
+
-
); }; diff --git a/components/04-templates/index.tsx b/components/04-templates/index.tsx index cf73a80e..8c7bfe8d 100644 --- a/components/04-templates/index.tsx +++ b/components/04-templates/index.tsx @@ -1,3 +1,3 @@ -export * from "./HomeSection"; -export * from "./SwapSection"; export * from "./Layout"; +export * from "./OfferSection"; +export * from "./SwapSection"; diff --git a/lib/client/abi.ts b/lib/client/abi.ts new file mode 100644 index 00000000..246cdb36 --- /dev/null +++ b/lib/client/abi.ts @@ -0,0 +1,1391 @@ +export const SwaplaceAbi: Readonly>> = [ + { + inputs: [ + { + internalType: "address", + name: "caller", + type: "address", + }, + ], + name: "InvalidAddress", + type: "error", + }, + { + inputs: [], + name: "InvalidAssetsLength", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "timestamp", + type: "uint256", + }, + ], + name: "InvalidExpiry", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "swapId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "allowed", + type: "address", + }, + ], + name: "SwapAccepted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "swapId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "SwapCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "swapId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "allowed", + type: "address", + }, + ], + name: "SwapCreated", + type: "event", + }, + { + inputs: [ + { + internalType: "uint256", + name: "swapId", + type: "uint256", + }, + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "acceptSwap", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "swapId", + type: "uint256", + }, + ], + name: "cancelSwap", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "uint256", + name: "config", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + internalType: "struct ISwap.Swap", + name: "swap", + type: "tuple", + }, + ], + name: "createSwap", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "swapId", + type: "uint256", + }, + ], + name: "getSwap", + outputs: [ + { + components: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "uint256", + name: "config", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + internalType: "struct ISwap.Swap", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + name: "makeAsset", + outputs: [ + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset", + name: "", + type: "tuple", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "allowed", + type: "address", + }, + { + internalType: "uint256", + name: "expiry", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + name: "makeSwap", + outputs: [ + { + components: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "uint256", + name: "config", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + internalType: "struct ISwap.Swap", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "allowed", + type: "address", + }, + { + internalType: "uint256", + name: "expiry", + type: "uint256", + }, + ], + name: "packData", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "config", + type: "uint256", + }, + ], + name: "parseData", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceID", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "totalSwaps", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, +] as const; + +export const MockERC721Abi: Readonly>> = [ + { + inputs: [], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "approved", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: false, + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "approve", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "getApproved", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "operator", + type: "address", + }, + ], + name: "isApprovedForAll", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "mintTo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "ownerOf", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + { + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceId", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "tokenURI", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; + +export const MockERC20Abi: Readonly>> = [ + { + inputs: [], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "allowance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20FailedDecreaseAllowance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "allowance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientAllowance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "uint256", + name: "balance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientBalance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "uint256", + name: "nonce", + type: "uint256", + }, + ], + name: "ERC20PermitInvalidNonce", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + ], + name: "ERC2612ExpiredSignature", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "signer", + type: "address", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "ERC2612InvalidSigner", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "requestedDecrease", + type: "uint256", + }, + ], + name: "decreaseAllowance", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "addedValue", + type: "uint256", + }, + ], + name: "increaseAllowance", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "mintTo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "nonces", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "permit", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "permitTransfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, +]; diff --git a/lib/client/blockchain-data.ts b/lib/client/blockchain-data.ts deleted file mode 100644 index 4ce8c988..00000000 --- a/lib/client/blockchain-data.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { getTimestamp } from "./utils"; -import { NFT, NFTsQueryStatus, getRpcHttpUrlForNetwork } from "./constants"; -import { Dispatch, SetStateAction } from "react"; - -export const getNftsFrom = async ( - address: string, - chainId: number, - stateSetter: Dispatch> -) => { - const baseUrl = getRpcHttpUrlForNetwork.get(chainId); - - if (!baseUrl) throw new Error("No RPC URL defined for connected chain"); - - const requestOptions = { - method: "get", - }; - - const url = `${baseUrl}/getNFTsForOwner?owner=${address}&withMetadata=true`; - - stateSetter(NFTsQueryStatus.LOADING); - - return fetch(url, requestOptions) - .then(async (response) => { - const data = await response.json(); - console.log(data); - - if (!data.ownedNfts.length) { - stateSetter(NFTsQueryStatus.NO_RESULTS); - } else { - stateSetter(NFTsQueryStatus.WITH_RESULTS); - } - - return data.ownedNfts; - }) - .catch((error) => { - console.error(error); - stateSetter(NFTsQueryStatus.ERROR); - return error; - }); -}; - -export interface Swap { - owner: string; - config: any; - biding: NFT[]; - asking: NFT[]; -} - -export async function makeConfig( - Contract: any, - allowed: any, - destinationChainSelector: any, - expiration: any -) { - const config = await Contract.packData( - allowed, - destinationChainSelector, - expiration - ); - return config; -} - -export async function makeSwap( - Contract: any, - owner: any, - allowed: any, - destinationChainSelector: any, - expiration: any, - biding: NFT[], - asking: NFT[], - chainId: number -) { - const timestamp = await getTimestamp(chainId); - if (expiration < timestamp) { - throw new Error("InvalidExpiry"); - } - - if (biding.length == 0 || asking.length == 0) { - throw new Error("InvalidNFTsLength"); - } - - const config = await makeConfig( - Contract, - allowed, - destinationChainSelector, - expiration - ); - - const swap: Swap = { - owner: owner, - config: config, - biding: biding, - asking: asking, - }; - - return swap; -} diff --git a/lib/client/blockchain-utils.ts b/lib/client/blockchain-utils.ts new file mode 100644 index 00000000..9891c147 --- /dev/null +++ b/lib/client/blockchain-utils.ts @@ -0,0 +1,247 @@ +import { getAPIKeyForNetwork, getNetwork } from "./constants"; +import { publicClient } from "../wallet/wallet-config"; +import { + Token, + ERC20, + ERC721, + TokenType, + EthereumAddress, + ERC20WithTokenAmountSelection, +} from "../shared/types"; +import { + type GetTokensForOwnerResponse, + type OwnedNftsResponse, + type OwnedToken, + type OwnedNft, + Alchemy, +} from "alchemy-sdk"; +import toast from "react-hot-toast"; +import { hexToNumber } from "viem"; + +export enum ButtonClickPossibilities { + PREVIOUS_STEP, + NEXT_STEP, +} + +export enum TransactionStatus { + SEND_TRANSACTION, + WAITING_WALLET_APPROVAL, + TRANSACTION_APPROVED, + SUCCESSFUL_TRANSACTION, +} + +export const getBlockchainTimestamp = async (chainId: number) => { + const provider = publicClient({ + chainId, + }); + + const block = await provider.getBlockNumber(); + const blockDetails = await provider.getBlock({ blockNumber: block }); + + const timestamp = blockDetails.timestamp; + + return timestamp; +}; + +export const INVALID_TOKEN_AMOUNT_OR_ID = BigInt(Number.MAX_SAFE_INTEGER); + +export const getTokenAmountOrId = (token: Token): bigint => { + /* ERC20 tokens have a transaction amount while ERC721, a token ID */ + let tokenAmountOrTokenId = undefined; + + switch (token.tokenType) { + case TokenType.ERC20: + if ((token as ERC20WithTokenAmountSelection).tokenAmount) { + tokenAmountOrTokenId = (token as ERC20WithTokenAmountSelection) + .tokenAmount; + } + case TokenType.ERC721: + if (token.id) { + tokenAmountOrTokenId = token.id as string; + } + } + + if (typeof tokenAmountOrTokenId === "undefined") + throw new Error(`Invalid token amount or ID: ${JSON.stringify(token)}`); + else return BigInt(tokenAmountOrTokenId); +}; + +// Check out the Alchemy Documentation https://docs.alchemy.com/reference/getnfts-sdk-v3 +export const getERC721TokensFromAddress = async ( + address: EthereumAddress, + chainId: number, +) => { + const networkAPIKey = getAPIKeyForNetwork.get(chainId); + const networkName = getNetwork.get(chainId); + + if (!networkAPIKey) { + throw new Error("No API Key for this network."); + } + + if (!networkName) { + throw new Error("No Network Name is defined for this network."); + } + + const config = { + apiKey: networkAPIKey, + network: networkName, + }; + + const alchemy = new Alchemy(config); + + return alchemy.nft + .getNftsForOwner(address.address) + .then((response: OwnedNftsResponse) => { + return parseAlchemyERC721Tokens(response.ownedNfts); + }) + .catch((error) => { + toastBlockchainTxError(error); + throw new Error("Error getting user's ERC721 tokens."); + }); +}; + +const parseAlchemyERC721Tokens = (tokens: OwnedNft[]): ERC721[] => { + return tokens.map((token) => { + return { + tokenType: TokenType.ERC721, + id: token.tokenId, + name: token.contract.name, + metadata: token.raw.metadata, + contract: token.contract.address, + contractMetadata: token.contract, + }; + }); +}; + +// Check out the Alchemy Documentation https://docs.alchemy.com/reference/gettokensforowner-sdk-v3 +export const getERC20TokensFromAddress = async ( + address: EthereumAddress, + chainId: number, +): Promise => { + const alchemyApiKey = getAPIKeyForNetwork.get(chainId); + const networkName = getNetwork.get(chainId); + + if (!alchemyApiKey) { + throw new Error("No API Key for this network."); + } + if (!networkName) { + throw new Error("No Network Name is defined for this network."); + } + + const config = { + apiKey: alchemyApiKey, + network: networkName, + }; + const alchemy = new Alchemy(config); + + const ownerAddress = address; + + return alchemy.core + .getTokensForOwner(ownerAddress.address) + .then((response: GetTokensForOwnerResponse) => { + return parseAlchemyERC20Tokens(response.tokens); + }) + .catch((error) => { + toastBlockchainTxError(error); + throw new Error("Error getting user's ERC20 tokens."); + }); +}; + +export const EMPTY_ERC_20_BALANCE = 0; + +const parseAlchemyERC20Tokens = (tokens: OwnedToken[]): ERC20[] => { + return tokens.map((token) => { + const rawBalanceAsNumber = token.rawBalance + ? hexToNumber(token.rawBalance as `0x${string}`) + : EMPTY_ERC_20_BALANCE; + + return { + tokenType: TokenType.ERC20, + /* + This ID is only used for TokenCard selection, in the Ui of the dApp. + We want it to be as randomic and unique as possible besides being + yet, mathematically possible to have same IDs on two different + tokens. Possible, but very unlikely to generate non-unique + IDs, below maths solve our ID generation goal, today. + */ + id: ((Date.now() * Math.random()) / Math.random()).toFixed(0), + name: token.name, + logo: token.logo, + symbol: token.symbol, + rawBalance: rawBalanceAsNumber, + contract: token.contractAddress, + }; + }); +}; + +// Unused for now +// export const getTokenBalance = async ( +// owner: EthereumAddress, +// token: Token, +// chainId: number, +// ): Promise => { +// const alchemyApiKey = getAPIKeyForNetwork.get(chainId); +// const networkName = getNetwork.get(chainId); + +// if (!alchemyApiKey) { +// throw new Error("No API Key for this network."); +// } +// if (!networkName) { +// throw new Error("No Network Name is defined for this network."); +// } +// if (!token.contract) { +// throw new Error("Selected token has no known contract address."); +// } + +// const config = { +// apiKey: alchemyApiKey, +// network: networkName, +// }; +// const alchemy = new Alchemy(config); + +// return alchemy.core +// .getTokenBalances(owner.address, [token.contract]) +// .then((response: TokenBalancesResponseErc20) => { +// if (!response.tokenBalances[0].tokenBalance) return null; + +// let balance = 0; +// if (isAddress(response.tokenBalances[0].tokenBalance)) { +// balance = hexToNumber(response.tokenBalances[0].tokenBalance); +// } + +// return balance; +// }) +// .catch((error) => { +// toastBlockchainTxError(error); +// throw new Error("Error getting token balance."); +// }); +// }; + +export interface TokenApprovalData { + approved: boolean; + tokenAddress: `0x${string}`; + amountOrId: bigint; +} + +export async function packingData( + Contract: any, + allowed: EthereumAddress, + expiration: bigint, +): Promise { + const config = await Contract.read.packData([allowed.address, expiration]); + return config; +} + +export const toastBlockchainTxError = (e: string) => { + /* + Below condition should include all possible Wallet Provider's + error messages on User transaction decline action in order + to patternize inside Swaplace the Transaction "Cancelled" + state response to the User. + */ + if (e.includes("rejected")) { + toast.error("Transaction rejected"); + } else { + toast.error("Transaction failed. Please contact our team."); + } +}; diff --git a/lib/client/constants.ts b/lib/client/constants.ts index 698658c8..174a616e 100644 --- a/lib/client/constants.ts +++ b/lib/client/constants.ts @@ -1,17 +1,8 @@ -/* eslint-disable prefer-const */ -export const ADDRESS_ZERO = "0x0000000000000000000000000000000000000000"; - -export const WIDE_SCREEN_SIZE = 1279; -export const DESKTOP_SCREEN_SIZE = 1023; -export const TABLET_SCREEN_SIZE = 768; +import { Network } from "alchemy-sdk"; -export interface NFT { - id?: Record; - metadata?: Record; - contract?: Record; -} +export const ADDRESS_ZERO = "0x0000000000000000000000000000000000000000"; -export enum NFTsQueryStatus { +export enum TokensQueryStatus { EMPTY_QUERY = "EMPTY_QUERY", LOADING = "LOADING", ERROR = "ERROR", @@ -20,8 +11,22 @@ export enum NFTsQueryStatus { } export enum SupportedNetworks { + HARDHAT = "HARDHAT", + ETHEREUM = "ETHEREUM", SEPOLIA = "SEPOLIA", + POLYGON = "POLYGON", MUMBAI = "MUMBAI", + OPTIMISM = "OPTIMISM", + OPGOERLI = "OPGOERLI", + OPSEPOLIA = "OPSEPOLIA", + AVALANCHE = "AVALANCHE", + FUJI = "FUJI", + BASE = "BASE", + BASEGOERLI = "BASE_GOERLI", + BNB = "BNB", + BNBTESTNET = "BNB_TESTNET", + ARBITRUMONE = "ARBITRUM_ONE", + ARBITRUMSEPOLIA = "ARBITRUM_SEPOLIA", } interface ChainProps { @@ -30,22 +35,147 @@ interface ChainProps { } export const ChainInfo: Record = { + [SupportedNetworks.HARDHAT]: { + id: 31337, + name: "Hardhat", + }, + [SupportedNetworks.ETHEREUM]: { + id: 1, + name: "Ethereum", + }, [SupportedNetworks.SEPOLIA]: { id: 11155111, name: "Sepolia", }, + [SupportedNetworks.POLYGON]: { + id: 137, + name: "Polygon", + }, [SupportedNetworks.MUMBAI]: { id: 80001, name: "Polygon Mumbai", }, + [SupportedNetworks.OPTIMISM]: { + id: 10, + name: "Optimism", + }, + [SupportedNetworks.OPGOERLI]: { + id: 420, + name: "Optimism Goerli", + }, + [SupportedNetworks.OPSEPOLIA]: { + id: 11155420, + name: "Optimism Sepolia", + }, + [SupportedNetworks.AVALANCHE]: { + id: 43114, + name: "Avalanche", + }, + [SupportedNetworks.FUJI]: { + id: 43113, + name: "Fuji", + }, + [SupportedNetworks.BASE]: { + id: 8453, + name: "Base", + }, + [SupportedNetworks.BASEGOERLI]: { + id: 84531, + name: "Base Goerli", + }, + [SupportedNetworks.BNB]: { + id: 56, + name: "Bnb", + }, + [SupportedNetworks.BNBTESTNET]: { + id: 97, + name: "Bnb Testnet", + }, + [SupportedNetworks.ARBITRUMONE]: { + id: 42161, + name: "Arbitrum", + }, + [SupportedNetworks.ARBITRUMSEPOLIA]: { + id: 421614, + name: "Arbitrum Sepolia", + }, }; -export let getRpcHttpUrlForNetwork: Map = new Map([ +export const getNetwork: Map = new Map([ + [ChainInfo.SEPOLIA.id, Network.ETH_SEPOLIA], + [ChainInfo.MUMBAI.id, Network.MATIC_MUMBAI], +]); + +export const getRpcHttpUrlForNetwork: Map = new Map([ + [ChainInfo.HARDHAT.id, "http://127.0.0.1:8545/"], + [ChainInfo.ETHEREUM.id, process.env.NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP ?? ""], [ChainInfo.SEPOLIA.id, process.env.NEXT_PUBLIC_ALCHEMY_SEPOLIA_HTTP ?? ""], + [ChainInfo.POLYGON.id, process.env.NEXT_PUBLIC_ALCHEMY_POLYGON_HTTP ?? ""], [ChainInfo.MUMBAI.id, process.env.NEXT_PUBLIC_ALCHEMY_MUMBAI_HTTP ?? ""], + [ChainInfo.OPTIMISM.id, process.env.NEXT_PUBLIC_ALCHEMY_OPTIMISM_HTTP ?? ""], + [ChainInfo.OPGOERLI.id, process.env.NEXT_PUBLIC_ALCHEMY_OPGOERLI_HTTP ?? ""], + [ + ChainInfo.OPSEPOLIA.id, + process.env.NEXT_PUBLIC_ALCHEMY_OPSEPOLIA_HTTP ?? "", + ], + [ + ChainInfo.AVALANCHE.id, + process.env.NEXT_PUBLIC_ALCHEMY_AVALANCHE_HTTP ?? "", + ], + [ChainInfo.FUJI.id, process.env.NEXT_PUBLIC_ALCHEMY_FUJI_HTTP ?? ""], + [ChainInfo.BASE.id, process.env.NEXT_PUBLIC_ALCHEMY_BASE_HTTP ?? ""], + [ + ChainInfo.BASE_GOERLI.id, + process.env.NEXT_PUBLIC_ALCHEMY_BASEGOERLI_HTTP ?? "", + ], + [ChainInfo.BNB.id, process.env.NEXT_PUBLIC_ALCHEMY_BNB_HTTP ?? ""], + [ + ChainInfo.BNB_TESTNET.id, + process.env.NEXT_PUBLIC_ALCHEMY_BNBTESTNET_HTTP ?? "", + ], + [ + ChainInfo.ARBITRUM_ONE.id, + process.env.NEXT_PUBLIC_ALCHEMY_ARBITRUMONE_HTTP ?? "", + ], + [ + ChainInfo.ARBITRUM_SEPOLIA.id, + process.env.NEXT_PUBLIC_ALCHEMY_ARBITRUMSEPOLIA_HTTP ?? "", + ], ]); +export const getAPIKeyForNetwork: Map = new Map([ + [ChainInfo.SEPOLIA.id, process.env.NEXT_PUBLIC_ALCHEMY_SEPOLIA_KEY], + [ChainInfo.MUMBAI.id, process.env.NEXT_PUBLIC_ALCHEMY_MUMBAI_KEY], +]); + +export const getCurrentNetworkHttpUrl = (chainId: number) => { + const httpUrl = getRpcHttpUrlForNetwork.get(chainId); + + if (!httpUrl) + throw new Error(`No RPC URL was defined for chain ID: ${chainId}`); + + return httpUrl; +}; + export const SWAPLACE_SMART_CONTRACT_ADDRESS = { - [ChainInfo.SEPOLIA.id]: "0xcB003ed4Df4679D15b8863BB8F7609855A6a380d", + [ChainInfo.HARDHAT.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.ETHEREUM.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.SEPOLIA.id]: "0xb7A42919ae66745Ffa69940De9d3DD99703eACb1", + [ChainInfo.POLYGON.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", [ChainInfo.MUMBAI.id]: "0xcB003ed4Df4679D15b8863BB8F7609855A6a380d", + [ChainInfo.OPTIMISM.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.OPGOERLI.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.OPSEPOLIA.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.AVALANCHE.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.FUJI.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.BASE.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.BASE_GOERLI.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.BNB.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.BNB_TESTNET.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.ARBITRUM_ONE.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.ARBITRUM_SEPOLIA.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", }; + +//SEPOLIA MOCKS +export const MOCKERC721 = "0x83dB434Db5014e24AdF5962457334122F1d4ab13"; +export const MOCKERC20 = "0x31a59e0f7fD0724545fCD912bcC2c5A1debddd0C"; diff --git a/lib/client/contexts/SidebarContext.tsx.tsx b/lib/client/contexts/SidebarContext.tsx.tsx new file mode 100644 index 00000000..0957c595 --- /dev/null +++ b/lib/client/contexts/SidebarContext.tsx.tsx @@ -0,0 +1,36 @@ +import React, { + createContext, + useContext, + useState, + ReactNode, + useCallback, +} from "react"; + +interface SidebarContextType { + isSidebarOpen: boolean; + toggleSidebar: (necessarilyOpen?: boolean) => void; +} + +const SidebarContext = createContext(undefined); + +export const SidebarProvider = ({ children }: { children: ReactNode }) => { + const [isSidebarOpen, setIsSidebarOpen] = useState(false); + + const toggleSidebar = useCallback(() => { + setIsSidebarOpen((prevState) => !prevState); + }, []); + + return ( + + {children} + + ); +}; + +export const useSidebar = () => { + const context = useContext(SidebarContext); + if (context === undefined) { + throw new Error("useSidebar must be used within a SidebarProvider"); + } + return context; +}; diff --git a/lib/client/hooks/useAuthedAccess.tsx b/lib/client/hooks/useAuthedAccess.tsx index a536d655..6138d402 100644 --- a/lib/client/hooks/useAuthedAccess.tsx +++ b/lib/client/hooks/useAuthedAccess.tsx @@ -14,9 +14,6 @@ export const useAuthedAccess = () => { toast.success(`Welcome to Swaplace!`, { id: "welcome-toast", }); - router.push("/swap"); - } else { - router.push("/"); } }, [router.pathname, authenticatedUserAddress]); }; diff --git a/lib/client/hooks/useAuthenticatedUser.tsx b/lib/client/hooks/useAuthenticatedUser.tsx index 1854b38d..31edbe28 100644 --- a/lib/client/hooks/useAuthenticatedUser.tsx +++ b/lib/client/hooks/useAuthenticatedUser.tsx @@ -1,9 +1,9 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import { ADDRESS_ZERO, getRpcHttpUrlForNetwork } from "../constants"; +import { ADDRESS_ZERO } from "../constants"; import { EthereumAddress } from "../../shared/types"; import { signOut, useSession } from "next-auth/react"; import { useEffect, useState } from "react"; -import { useAccount, useDisconnect, useEnsName, useNetwork } from "wagmi"; +import { useAccount, useDisconnect, useEnsName } from "wagmi"; interface AuthenticatedUserHook { loadingEnsName: boolean; @@ -14,7 +14,6 @@ interface AuthenticatedUserHook { } export const useAuthenticatedUser = (): AuthenticatedUserHook => { - const { chain } = useNetwork(); const { disconnect } = useDisconnect(); const { data: nextAuthUser } = useSession(); const { address, isConnected } = useAccount(); @@ -23,16 +22,6 @@ export const useAuthenticatedUser = (): AuthenticatedUserHook => { const [loadingAuthenticatedUser, setLoadingAuthenticatedUser] = useState(true); - useEffect(() => { - if ( - typeof chain?.id === "number" && - !getRpcHttpUrlForNetwork.get(chain?.id) - ) { - disconnect(); - return; - } - }, [chain]); - const { data: ensName, isLoading: loadingEnsName, @@ -62,7 +51,7 @@ export const useAuthenticatedUser = (): AuthenticatedUserHook => { setAuthenticatedAccountAddress( accountAuthenticated && address ? new EthereumAddress(address.toLowerCase()) - : null + : null, ); setLoadingAuthenticatedUser(false); }, [nextAuthUser, isConnected, address]); diff --git a/lib/client/hooks/useENSData.tsx b/lib/client/hooks/useENSData.tsx new file mode 100644 index 00000000..71315a2f --- /dev/null +++ b/lib/client/hooks/useENSData.tsx @@ -0,0 +1,68 @@ +import { EthereumAddress } from "@/lib/shared/types"; +import { createPublicClient, http } from "viem"; +import { useEffect, useState } from "react"; +import { mainnet } from "viem/chains"; + +export enum ENSAvatarQueryStatus { + LOADING, + SUCCESS, + ERROR, +} + +interface Props { + ensAddress: EthereumAddress | null; +} + +export const useEnsData = ({ ensAddress }: Props) => { + const [primaryName, setPrimaryName] = useState( + undefined, + ); + const [avatarQueryStatus, setAvatarQueryStatus] = + useState(ENSAvatarQueryStatus.LOADING); + + useEffect(() => { + if (ensAddress) { + const mainnetRPCUrl = process.env.NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP; + + if (!mainnetRPCUrl) + throw new Error( + "No RPC URL was defined for mainnet, cannot get ENS name without it.", + ); + + const mainnetClient = createPublicClient({ + chain: mainnet, + transport: http(), + }); + + setAvatarQueryStatus(ENSAvatarQueryStatus.LOADING); + + mainnetClient + .getEnsName({ + address: ensAddress.address as `0x${string}`, + }) + .then((name) => { + if (name) { + setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); + setPrimaryName(name); + } else { + setAvatarQueryStatus(ENSAvatarQueryStatus.ERROR); + setPrimaryName(null); + } + }) + .catch(() => { + setAvatarQueryStatus(ENSAvatarQueryStatus.ERROR); + setPrimaryName(null); + }); + } else { + setPrimaryName(null); + } + }, [ensAddress]); + + return { + primaryName, + avatarQueryStatus: avatarQueryStatus, + avatarSrc: primaryName + ? `https://metadata.ens.domains/mainnet/avatar/${primaryName}` + : null, + }; +}; diff --git a/lib/client/hooks/usePonder.ts b/lib/client/hooks/usePonder.ts new file mode 100644 index 00000000..f87f696f --- /dev/null +++ b/lib/client/hooks/usePonder.ts @@ -0,0 +1,137 @@ +import { SwapContext } from "@/components/01-atoms"; +import axios from "axios"; +import { useContext, useEffect, useState } from "react"; + +interface Swap { + swapId: string; + status: string; + owner: string; + allowed: string | null; + expiry: bigint; + bid: string; + ask: string; +} + +export enum PonderFilter { + ALL_OFFERS = "All Offers", // + CREATED = "created", + RECEIVED = "received", // Not yet + ACCEPTED = "accepted", + CANCELED = "canceled", + EXPIRED = "expired", // Not yet +} + +interface Ponder { + operationName: string; + query: string; + variables: { + orderBy: string; + orderDirection: string; + inputAddress: string; + ponderFilterStatus?: string; + }; +} + +export const usePonder = () => { + const { inputAddress, ponderFilterStatus } = useContext(SwapContext); + const [allSwaps, setAllSwaps] = useState([]); + + useEffect(() => { + const fetchAllSwaps = async () => { + try { + const response = await axios(config); + console.log("response =", response); + + const allSwapsResponseData = response.data.data.databases.items; + console.log("allSwapsResponseData", allSwapsResponseData); + + setAllSwaps(allSwapsResponseData); + } catch (error) { + console.error(error); + return []; + } + }; + + fetchAllSwaps(); + }, [ponderFilterStatus, inputAddress]); + + const endpoint = process.env.NEXT_PUBLIC_PONDER_ENDPOINT; + const headers = { + "content-type": "application/json", + }; + + const formattedInputAddress = inputAddress.startsWith("0x") + ? inputAddress + : `0x${inputAddress}`; + + let ponderQuery: Ponder; + if (ponderFilterStatus === PonderFilter.ALL_OFFERS) { + ponderQuery = { + operationName: "databases", + query: `query databases($orderBy: String!, $orderDirection: String!, $inputAddress: String! ) { + databases(orderBy: $orderBy, orderDirection: $orderDirection, where: { owner: $inputAddress }, limit: 20) { + items { + swapId + status + owner + allowed + expiry + bid + ask + blockTimestamp + transactionHash + } + pageInfo { + hasNextPage + endCursor + } + } + }`, + variables: { + orderBy: "blockTimestamp", + orderDirection: "desc", + inputAddress: formattedInputAddress, + // after: after, + }, + }; + } else { + ponderQuery = { + operationName: "databases", + query: `query databases($orderBy: String!, $orderDirection: String!, $inputAddress: String!, $ponderFilterStatus: Status! ) { + databases(orderBy: $orderBy, orderDirection: $orderDirection, where: { owner: $inputAddress, status: $ponderFilterStatus }, limit: 20) { + items { + swapId + status + owner + allowed + expiry + bid + ask + blockTimestamp + transactionHash + } + pageInfo { + hasNextPage + endCursor + } + } + }`, + variables: { + orderBy: "blockTimestamp", + orderDirection: "desc", + inputAddress: formattedInputAddress, + ponderFilterStatus: ponderFilterStatus, + // after: after, + }, + }; + } + + const config = { + url: endpoint, + method: "post", + headers: headers, + data: ponderQuery, + }; + + return { allSwaps }; +}; diff --git a/lib/client/hooks/useScreenSize.tsx b/lib/client/hooks/useScreenSize.tsx index 7d0e8e56..504343e1 100644 --- a/lib/client/hooks/useScreenSize.tsx +++ b/lib/client/hooks/useScreenSize.tsx @@ -2,7 +2,7 @@ import { DESKTOP_SCREEN_SIZE, TABLET_SCREEN_SIZE, WIDE_SCREEN_SIZE, -} from "../constants"; +} from "../ui-utils"; import { useState, useEffect } from "react"; export const useScreenSize = () => { @@ -13,16 +13,16 @@ export const useScreenSize = () => { const checkIfIsMobile = () => { setIsMobile( - window.matchMedia(`(max-width: ${TABLET_SCREEN_SIZE - 1}px)`).matches + window.matchMedia(`(max-width: ${TABLET_SCREEN_SIZE}px)`).matches, ); setIsTablet( - window.matchMedia(`(max-width: ${DESKTOP_SCREEN_SIZE - 1}px)`).matches + window.matchMedia(`(min-width: ${TABLET_SCREEN_SIZE - 1}px)`).matches, ); setIsDesktop( - window.matchMedia(`(min-width: ${DESKTOP_SCREEN_SIZE}px)`).matches + window.matchMedia(`(min-width: ${DESKTOP_SCREEN_SIZE}px)`).matches, ); setIsWideScreen( - window.matchMedia(`(min-width: ${WIDE_SCREEN_SIZE}px)`).matches + window.matchMedia(`(min-width: ${WIDE_SCREEN_SIZE}px)`).matches, ); }; diff --git a/lib/client/hooks/useSupportedNetworks.tsx b/lib/client/hooks/useSupportedNetworks.tsx new file mode 100644 index 00000000..6409936c --- /dev/null +++ b/lib/client/hooks/useSupportedNetworks.tsx @@ -0,0 +1,25 @@ +import { ChainInfo } from "../constants"; +import { useEffect, useState } from "react"; +import { useNetwork } from "wagmi"; + +export const useSupportedNetworks = () => { + const [isNetworkSupported, setIsNetworkSupported] = useState(true); + const supportedNetworksId = Object.values(ChainInfo).map((net) => net.id); + const { chain } = useNetwork(); + + useEffect(() => { + if ( + chain && + supportedNetworksId.includes(chain.id) && + chain.id === 11155111 // Hardcoded for now to accept only Sepolia for now, until we accept others chains afther alpha + ) { + setIsNetworkSupported(true); + } else { + setIsNetworkSupported(false); + } + }, [supportedNetworksId, chain]); + + return { + isNetworkSupported, + }; +}; diff --git a/lib/client/hooks/useWalletBalance.tsx b/lib/client/hooks/useWalletBalance.tsx new file mode 100644 index 00000000..fa469e45 --- /dev/null +++ b/lib/client/hooks/useWalletBalance.tsx @@ -0,0 +1,62 @@ +import { getRpcHttpUrlForNetwork } from "../constants"; +import { EthereumAddress } from "@/lib/shared/types"; +import { useEffect, useState } from "react"; +import { createPublicClient, formatUnits, http } from "viem"; +import { useNetwork } from "wagmi"; + +export enum WalletBalanceQueryStatus { + LOADING, + SUCCESS, + ERROR, +} + +interface Props { + walletAddress: EthereumAddress | null; +} + +export const useWalletBalance = ({ walletAddress }: Props) => { + const [balance, setBalance] = useState(null); + const [balanceQueryStatus, setBalanceQueryStatus] = + useState(WalletBalanceQueryStatus.LOADING); + + const { chain } = useNetwork(); + + const RpcHttpUrlForNetwork = chain + ? getRpcHttpUrlForNetwork.get(chain?.id) + : ""; + + useEffect(() => { + if (walletAddress && chain && !!RpcHttpUrlForNetwork) { + const client = createPublicClient({ + chain: chain, + transport: http(RpcHttpUrlForNetwork), + }); + + setBalanceQueryStatus(WalletBalanceQueryStatus.LOADING); + + client + .getBalance({ + address: walletAddress.address as `0x${string}`, + }) + .then((fetchedBalance) => { + setBalanceQueryStatus(WalletBalanceQueryStatus.SUCCESS); + !!chain && + setBalance( + formatUnits(fetchedBalance, chain.nativeCurrency.decimals), + ); + }) + .catch(() => { + setBalanceQueryStatus(WalletBalanceQueryStatus.ERROR); + setBalance(null); + }); + } else { + setBalance(null); + setBalanceQueryStatus(WalletBalanceQueryStatus.ERROR); + } + }, [walletAddress, chain, RpcHttpUrlForNetwork]); + + return { + balance, + balanceQueryStatus, + }; +}; diff --git a/lib/client/swap-utils.ts b/lib/client/swap-utils.ts new file mode 100644 index 00000000..487220b8 --- /dev/null +++ b/lib/client/swap-utils.ts @@ -0,0 +1,238 @@ +import { getBlockchainTimestamp, getTokenAmountOrId } from "./blockchain-utils"; +import { ERC20, EthereumAddress, Token, TokenType } from "../shared/types"; +import { type WalletClient } from "wagmi"; + +export interface Asset { + addr: `0x${string}`; + amountOrId: bigint; +} + +export interface Swap { + owner: string; + config: number; + biding: Asset[]; + asking: Asset[]; +} + +export interface ICreateSwap { + walletClient: WalletClient; + expireDate: bigint; + searchedUserTokensList: Token[]; + authenticatedUserTokensList: Token[]; + validatedAddressToSwap: string; + authenticatedUserAddress: EthereumAddress; + chain: number; +} + +export type TokenWithSwapInfo = { + tokenAddress: `0x${string}`; + amountOrId: bigint; +}; + +export interface IApproveTokenSwap { + walletClient: WalletClient; + tokenContractAddress: `0x${string}`; + spender: `0x${string}`; + amountOrId: bigint; + chainId: number; + token: Token; + onWalletConfirmation: () => void; +} + +export enum TimeStampDate { + ONE_DAY = 24 * 60 * 60 * 1000, + ONE_WEEK = ONE_DAY * 7, + ONE_MONTH = ONE_WEEK * 4, + SIX_MONTH = ONE_MONTH * 6, + ONE_YEAR = SIX_MONTH * 2, +} + +export function getTokenInfoBeforeSwap(token: Token): TokenWithSwapInfo { + const amountOrId = getTokenAmountOrId(token); + + const contractAddress = token.contract; + + if (amountOrId == undefined || contractAddress == undefined) { + throw new Error(`Invalid token swap info: ${JSON.stringify(token)}`); + } else { + return { + tokenAddress: contractAddress as `0x${string}`, + amountOrId: amountOrId, + }; + } +} + +export async function makeAsset( + addr: string, + amountOrId: bigint, +): Promise { + // validate if its an ethereum address + try { + new EthereumAddress(addr); + } catch { + throw new Error("InvalidAddressFormat"); + } + + // if the amount is negative, it will throw an error + if (BigInt(amountOrId) < 0n) { + throw new Error("AmountOrIdCannotBeNegative"); + } + + /** + * @dev Create a new Asset type described by the contract interface. + * + * NOTE: If the amount is in number format, it will be converted to bigint. + * EVM works with a lot of decimals and might overload using number type. + */ + const asset: Asset = { + addr: addr as `0x${string}`, + amountOrId, + }; + + return asset; +} + +export async function fromTokensToAssets( + tokensList: Token[], +): Promise { + const tokenAssetArray: Asset[] = []; + const assetPromisesArray: Promise[] = []; + + for (let i = 0; i < tokensList.length; i += 1) { + const addr = tokensList[i]?.contract as `0x${string}`; + const amountOrId = getTokenAmountOrId(tokensList[i]); + + if (amountOrId !== undefined && addr !== undefined) { + const assetPromise = makeAsset(addr, amountOrId).then((asset) => { + tokenAssetArray.push(asset); + }); + assetPromisesArray.push(assetPromise); + } + } + + await Promise.all(assetPromisesArray); + + return tokenAssetArray; +} + +export async function getSwapConfig( + owner: EthereumAddress, + packedData: number, + expiry: bigint, + biding: Asset[], + asking: Asset[], + chainId: number, // To Do remove thee chainId in params +) { + // check for the current `block.timestamp` because `expiry` cannot be in the past + const timestamp = await getBlockchainTimestamp(chainId); + if (expiry < timestamp) { + throw new Error("InvalidExpiry"); + } + + /** + * @dev one of the swapped assets should never be empty or it should be directly + * transfered using {ERC20-transferFrom} or {ERC721-safeTransferFrom} + * + * NOTE: if the purpose of the swap is to transfer the asset directly using Swaplace, + * then any small token quantity should be used as the swap asset. + */ + if (biding.length == 0 || asking.length == 0) { + throw new Error("InvalidAssetsLength"); + } + + const swap: Swap = { + owner: owner.address, + config: packedData, + biding: biding, + asking: asking, + }; + + return swap; +} + +/** + * @dev Facilitate to create a swap when the swap is too large. + * + * Directly composing swaps to avoid to calling {ISwapFactory-makeAsset} + * multiple times. + * + * NOTE: + * + * - This function is not implemented in the contract. + * - This function needs to be async because it calls for `block.timestamp`. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `expiry` cannot be in the past timestamp. + * - `bidingAddr` and `askingAddr` cannot be empty. + * - `bidingAddr` and `bidingAmountOrId` must have the same length. + * - `askingAddr` and `askingAmountOrId` must have the same length. + */ +export async function composeSwap( + owner: any, + config: any, + expiry: bigint, + bidingAddr: any[], + bidingAmountOrId: any[], + askingAddr: any[], + askingAmountOrId: any[], +) { + // lenght of addresses and their respective amounts must be equal + if ( + bidingAddr.length != bidingAmountOrId.length || + askingAddr.length != askingAmountOrId.length + ) { + throw new Error("InvalidAssetsLength"); + } + + // push new assets to the array of bids and asks + const biding: any[] = []; + bidingAddr.forEach(async (addr, index) => { + biding.push(await makeAsset(addr, bidingAmountOrId[index])); + }); + + const asking: any[] = []; + askingAddr.forEach(async (addr, index) => { + asking.push(await makeAsset(addr, askingAmountOrId[index])); + }); + + const chainId = 0; + + return await getSwapConfig(owner, config, expiry, biding, asking, chainId); // To Do remove thee chainId in params +} + +export function getTokensInfoBeforeSwap( + tokensList: Token[], +): TokenWithSwapInfo[] { + const tokensWithInfo: TokenWithSwapInfo[] = []; + + for (let i = 0; i < tokensList.length; i++) { + let nftAmountOrTokenId = undefined; + + switch (tokensList[i].tokenType) { + case TokenType.ERC20: + if ((tokensList[i] as ERC20).rawBalance) { + nftAmountOrTokenId = (tokensList[i] as ERC20).rawBalance; + } + case TokenType.ERC721: + if (tokensList[i]?.id as unknown as number) { + nftAmountOrTokenId = tokensList[i]?.id as unknown as number; + } + } + + const tokenContractAddress = tokensList[i]?.contract as `0x${string}`; + + if ( + nftAmountOrTokenId !== undefined && + tokenContractAddress !== undefined + ) { + tokensWithInfo.push({ + tokenAddress: tokenContractAddress, + amountOrId: BigInt(nftAmountOrTokenId), + }); + } + } + + return tokensWithInfo; +} diff --git a/lib/client/ui-utils.ts b/lib/client/ui-utils.ts new file mode 100644 index 00000000..8a149e25 --- /dev/null +++ b/lib/client/ui-utils.ts @@ -0,0 +1,62 @@ +import { TimeStampDate } from "./swap-utils"; +import { + ERC20, + ERC20WithTokenAmountSelection, + ERC721, + Token, + TokenType, +} from "../shared/types"; + +export const WIDE_SCREEN_SIZE = 1279; +export const DESKTOP_SCREEN_SIZE = 1023; +export const TABLET_SCREEN_SIZE = 768; + +export interface ExpireOption { + label: string; + value: TimeStampDate; +} + +export enum SwapModalSteps { + APPROVE_TOKENS, + CREATE_SWAP, + CREATING_SWAP, + CREATED_SWAP, +} + +export const ExpireDate: ExpireOption[] = [ + { label: "1 day", value: TimeStampDate.ONE_DAY }, + { label: "1 week", value: TimeStampDate.ONE_WEEK }, + { label: "1 month", value: TimeStampDate.ONE_MONTH }, + { label: "1 year", value: TimeStampDate.ONE_YEAR }, +]; + +export const getTokenName = ( + token: Token, + prefix = { + withAmountPrefix: false, + displayTokenAmount: false, + }, +): string => { + if (token.tokenType === TokenType.ERC20) { + const erc20balancePrefix = prefix.withAmountPrefix + ? prefix.displayTokenAmount + ? (token as ERC20WithTokenAmountSelection).tokenAmount + " - " + : (token as ERC20).rawBalance + " - " + : ""; + + return token.name + ? erc20balancePrefix + token.name + : erc20balancePrefix + token.tokenType; + } else if (token.tokenType === TokenType.ERC721) { + const metadataName = (token as ERC721).metadata?.name; + const tokenName = (token as ERC721).name; + + return metadataName + ? metadataName + : tokenName + ? `${token.name} - ${token.tokenType}` + : `${token.tokenType}`; + } else { + return `${token.tokenType} - Token Name Not Found`; + } +}; diff --git a/lib/client/utils.ts b/lib/client/utils.ts index 5ab3ad95..3dd51c98 100644 --- a/lib/client/utils.ts +++ b/lib/client/utils.ts @@ -10,6 +10,27 @@ export const capitalizeFirstLetter = (str: string) => { return str.charAt(0).toUpperCase() + str.slice(1).toLocaleLowerCase(); }; +/** + * This function capitalizes the first letter of each word in a phrase. + * It also replaces underscores ('_') between words with spaces and capitalizes the next letter. + * + * @param {string} name - The input phrase to be capitalized. + * @returns {string} - The input phrase with the first letter of each word capitalized. + */ +export const capitalizeFirstLetterPrhases = (name: string): string => { + let capitalizedName = capitalizeFirstLetter(name.replace("_", " ")); + + const words = capitalizedName.split(" "); + + const capitalizedWords = words.map((word) => { + return capitalizeFirstLetter(word); + }); + + capitalizedName = capitalizedWords.join(" "); + + return capitalizedName; +}; + export const getTimestamp = async (chainId: number) => { const provider = publicClient({ chainId, @@ -22,3 +43,26 @@ export const getTimestamp = async (chainId: number) => { return timestamp; }; + +export const collapseAddress = ( + address: string, + startLength = 4, + endLength = 4, +) => { + // Check if the address is valid (starts with '0x' and is long enough) + if ( + !address.startsWith("0x") || + address.length < startLength + endLength + 2 + ) { + return address; // Return the original address if it's too short to collapse + } + + // Extract the start and end parts of the address + const start = address.substring(2, 2 + startLength); + const end = address.substring(address.length - endLength); + + // Concatenate with ellipsis + const collapsedAddress = `0x${start}...${end}`; + + return collapsedAddress; +}; diff --git a/lib/service/approveSwap.ts b/lib/service/approveSwap.ts new file mode 100644 index 00000000..20843e96 --- /dev/null +++ b/lib/service/approveSwap.ts @@ -0,0 +1,75 @@ +import { MockERC20Abi, MockERC721Abi } from "../client/abi"; +import { IApproveTokenSwap } from "../client/swap-utils"; +import { TokenType } from "../shared/types"; +import { publicClient } from "../wallet/wallet-config"; +import { type Hash, type TransactionReceipt } from "viem"; + +export interface ApproveSwapResponse { + receipt: TransactionReceipt | null; + errorMessage: string | null; + success: boolean; +} + +export async function approveSwap({ + walletClient, + spender, + tokenContractAddress, + amountOrId, + chainId, + token, + onWalletConfirmation, +}: IApproveTokenSwap): Promise { + const abi = + token.tokenType === TokenType.ERC20 ? MockERC20Abi : MockERC721Abi; + const functionName = "approve"; + + try { + const { request } = await publicClient({ chainId }).simulateContract({ + account: walletClient.account.address as `0x${string}`, + address: tokenContractAddress, + args: [spender, amountOrId], + functionName, + abi, + }); + + const transactionHash: Hash = await walletClient.writeContract(request); + onWalletConfirmation(); + + let txReceipt = {} as TransactionReceipt; + + while (typeof txReceipt.blockHash === "undefined") { + /* + It is guaranteed that at some point we'll have a valid TransactionReceipt in here. + If we had a valid transaction sent (which is confirmed at this point by the try/catch block), + it is a matter of waiting the transaction to be mined in order to know whether it was successful or not. + + So why are we using a while loop here? + - Because it is possible that the transaction was not yet mined by the time + we reach this point. So we keep waiting until we have a valid TransactionReceipt. + */ + + const transactionReceipt = await publicClient({ + chainId, + }).waitForTransactionReceipt({ + hash: transactionHash, + }); + + if (transactionReceipt) { + txReceipt = transactionReceipt; + } + } + + return { + success: true, + receipt: txReceipt, + errorMessage: null, + }; + } catch (error) { + console.error(error); + return { + receipt: null, + success: false, + errorMessage: String(error), + }; + } +} diff --git a/lib/service/createSwap.ts b/lib/service/createSwap.ts new file mode 100644 index 00000000..43515cf7 --- /dev/null +++ b/lib/service/createSwap.ts @@ -0,0 +1,122 @@ +import { Swap } from "../client/swap-utils"; +import { SWAPLACE_SMART_CONTRACT_ADDRESS } from "../client/constants"; +import { publicClient } from "../wallet/wallet-config"; +import { encodeFunctionData } from "viem"; + +export interface SwapUserConfiguration { + walletClient: any; + chain: number; +} + +export async function createSwap( + swap: Swap, + configurations: SwapUserConfiguration, +) { + // const SwaplaceContract = getContract({ + // address: SWAPLACE_SMART_CONTRACT_ADDRESS[chain] as `0x${string}`, + // abi: SwaplaceAbi, + // publicClient: publicClientViem, + // }); + // const config = await packData( + // SwaplaceContract, + // validatedAddressToSwap as `0x${string}`, + // expireDate, + // ); + + const data = encodeFunctionData({ + abi: [ + { + inputs: [ + { + components: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "uint256", + name: "config", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + internalType: "struct ISwap.Swap", + name: "swap", + type: "tuple", + }, + ], + name: "createSwap", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + ], + args: [ + { + owner: swap.owner as `0x${string}`, + config: BigInt(swap.config), + biding: swap.biding, + asking: swap.asking, + }, + ], + }); + try { + const transactionHash = await configurations.walletClient.sendTransaction({ + data: data, + to: SWAPLACE_SMART_CONTRACT_ADDRESS[ + configurations.chain + ] as `0x${string}`, + }); + + const transactionReceipt = await publicClient({ + chainId: configurations.chain, + }).waitForTransactionReceipt({ + hash: transactionHash, + }); + + return transactionReceipt; + } catch (error) { + console.error(error); + throw new Error(String(error)); + } +} diff --git a/lib/service/verifyTokensSwapApproval.ts b/lib/service/verifyTokensSwapApproval.ts new file mode 100644 index 00000000..ca26b141 --- /dev/null +++ b/lib/service/verifyTokensSwapApproval.ts @@ -0,0 +1,62 @@ +import { TokenApprovalData } from "../client/blockchain-utils"; +import { publicClient } from "../wallet/wallet-config"; +import { MockERC721Abi } from "../client/abi"; +import { SWAPLACE_SMART_CONTRACT_ADDRESS } from "../client/constants"; +import { Token, TokenType } from "../shared/types"; +import { getTokenInfoBeforeSwap } from "../client/swap-utils"; + +export async function isTokenSwapApproved({ + token, + chainId, +}: { + token: Token; + chainId: number; +}): Promise { + try { + const tokenSwapInfo = getTokenInfoBeforeSwap(token); + + let data; + if (token.tokenType === TokenType.ERC20) { + // Todo: implement ERC20 approval amount checker + return false; + } else if (token.tokenType === TokenType.ERC721) { + const tokenTypeAbi = MockERC721Abi; + const getApprovedStatusMethod = "getApproved"; + data = await publicClient({ chainId }).readContract({ + abi: tokenTypeAbi, + functionName: getApprovedStatusMethod, + address: tokenSwapInfo.tokenAddress, + args: [tokenSwapInfo.amountOrId.toString()], + }); + } + + /* + Whenever a token is approved to be exchanged by a given Smart-Contract, + the returned string of 'getApproved()' informs the given Smart-Contract + address. If the token is not approved to be swap by this given + Smart-Contract, 'getApproved()' returns 'ADDRESS_ZERO' + */ + return data === SWAPLACE_SMART_CONTRACT_ADDRESS[chainId]; + } catch (e) { + console.error(e); + return false; + } +} + +export async function getMultipleTokensApprovalStatus( + tokensList: Token[], + chainId: number, +): Promise { + const promises = tokensList.map(async (token) => { + const tokenSwapInfo = getTokenInfoBeforeSwap(token); + + return { + ...tokenSwapInfo, + approved: await isTokenSwapApproved({ token, chainId }), + }; + }); + + const tokensListWithApprovalStatus = Promise.all(promises); + + return tokensListWithApprovalStatus; +} diff --git a/lib/shared/types.ts b/lib/shared/types.ts index 5deb5b2e..281a7834 100644 --- a/lib/shared/types.ts +++ b/lib/shared/types.ts @@ -1,21 +1,55 @@ +export type Token = ERC20 | ERC721; + +export enum TokenType { + ERC20 = "ERC20", + ERC721 = "ERC721", +} + +export interface ERC721 { + tokenType: TokenType; + id?: string; + name?: string; + contract?: string; + metadata?: Record; + contractMetadata?: Record; +} + +export interface ERC20 { + tokenType: TokenType; + id?: string; + name?: string; + logo?: string; + symbol?: string; + contract?: string; + rawBalance: number; +} + +export interface ERC20WithTokenAmountSelection extends ERC20 { + tokenAmount: number; +} + export class EthereumAddress { static readonly ETHEREUM_ADDRESS_LENGTH = 40; static readonly pattern = new RegExp( - `^0x[a-fA-F0-9]{${EthereumAddress.ETHEREUM_ADDRESS_LENGTH}}$` + `^0x[a-fA-F0-9]{${EthereumAddress.ETHEREUM_ADDRESS_LENGTH}}$`, ); - private readonly _value: string; + public address: `0x${string}`; + public erc20List: ERC20[]; + public erc721List: ERC721[]; - constructor(public address: string) { - if (!EthereumAddress.pattern.test(address)) { - throw new Error(`Invalid Ethereum address: ${address}`); + constructor(private add: string) { + if (!EthereumAddress.pattern.test(add)) { + throw new Error(`Invalid Ethereum address: ${add}`); } - this._value = address.toLowerCase(); + this.erc20List = []; + this.erc721List = []; + this.address = add.toLowerCase() as `0x${string}`; } toString() { - return this._value; + return this.address; } equals(otherAddress: EthereumAddress | undefined | null) { @@ -23,13 +57,13 @@ export class EthereumAddress { let isEqual = false; try { - isEqual = this._value === otherAddress._value; + isEqual = this.address === otherAddress.address; } finally { return isEqual; } } getEllipsedAddress() { - return this._value.slice(0, 6) + "..." + this._value.slice(-4); + return this.address.slice(0, 6) + "..." + this.address.slice(-4); } } diff --git a/lib/wallet/wallet-config.ts b/lib/wallet/wallet-config.ts index cf9952db..3c45b12d 100644 --- a/lib/wallet/wallet-config.ts +++ b/lib/wallet/wallet-config.ts @@ -1,5 +1,5 @@ -import { getRpcHttpUrlForNetwork } from "../client/constants"; -import { polygonMumbai, sepolia } from "@wagmi/core/chains"; +import { getCurrentNetworkHttpUrl } from "../client/constants"; +import { sepolia } from "@wagmi/core/chains"; import { configureChains, createConfig } from "wagmi"; import { trustWallet, @@ -13,19 +13,19 @@ import { connectorsForWallets } from "@rainbow-me/rainbowkit"; import { jsonRpcProvider } from "wagmi/providers/jsonRpc"; export const { chains, webSocketPublicClient, publicClient } = configureChains( - [sepolia, polygonMumbai], + [sepolia], [ jsonRpcProvider({ rpc: (chain) => ({ - http: getRpcHttpUrlForNetwork.get(chain.id) ?? "", + http: getCurrentNetworkHttpUrl(chain.id), }), }), - ] + ], ); const connectorArgs = { appName: "Swaplace dApp", - chains: [sepolia, polygonMumbai], + chains: [sepolia], projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID ?? "", }; diff --git a/package-lock.json b/package-lock.json index 14cb4980..57f11338 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,16 +10,18 @@ "dependencies": { "@headlessui-float/react": "^0.13.0", "@headlessui/react": "^1.7.17", - "@rainbow-me/rainbowkit": "1.0.4", + "@rainbow-me/rainbowkit": "^1.3.0", "@rainbow-me/rainbowkit-siwe-next-auth": "0.1.8", "@typescript-eslint/eslint-plugin": "5.54.1", + "alchemy-sdk": "^3.1.2", + "axios": "^1.6.7", + "boring-avatars": "1.7.0", "classcat": "^5.0.4", - "eslint": "8.7.0", - "eslint-config-next": "13.4.19", "eslint-plugin-unused-imports": "2.0.0", "ethers": "^5.7.2", "next": "14.0.3", "next-auth": "^4.20.1", + "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", "react-hot-toast": "^2.4.1", @@ -34,8 +36,9 @@ "@types/node-fetch": "^2.6.9", "@types/react": "^18", "@types/react-dom": "^18", - "@typescript-eslint/eslint-plugin": "5.54.1", + "@typescript-eslint/parser": "^6.13.1", "autoprefixer": "^10.0.1", + "dotenv": "^16.4.1", "eslint": "8.7.0", "eslint-config-next": "13.4.19", "postcss": "^8", @@ -70,9 +73,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", - "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -107,10 +110,18 @@ "node": ">= 10.0.0" } }, + "node_modules/@coinbase/wallet-sdk/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "node_modules/@eslint/eslintrc": { "version": "1.4.1", @@ -135,6 +146,28 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@ethereumjs/rlp": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", @@ -843,29 +876,29 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.2.tgz", - "integrity": "sha512-Ii3MrfY/GAIN3OhXNzpCKaLxHQfJF9qvwq/kEJYdqDxeIHa01K8sldugal6TmeeXl+WMvhv9cnVzUTaFFJF09A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", "dependencies": { - "@floating-ui/utils": "^0.1.3" + "@floating-ui/utils": "^0.2.1" } }, "node_modules/@floating-ui/dom": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", - "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", "dependencies": { - "@floating-ui/core": "^1.4.2", - "@floating-ui/utils": "^0.1.3" + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/react": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.3.tgz", - "integrity": "sha512-iKH8WRR0L/nLiM6qavFZxkyegIZRMxGnM9aKEc71M4wRlUNkgTamjPsOQXy11oZbDOH37MiTbk/nAPn9M2+shA==", + "version": "0.26.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.9.tgz", + "integrity": "sha512-p86wynZJVEkEq2BBjY/8p2g3biQ6TlgT4o/3KgFKyTWoJLU1GZ8wpctwRqtkEl2tseYA+kw7dBAIDFcednfI5w==", "dependencies": { - "@floating-ui/react-dom": "^2.0.3", - "@floating-ui/utils": "^0.1.5", + "@floating-ui/react-dom": "^2.0.8", + "@floating-ui/utils": "^0.2.1", "tabbable": "^6.0.1" }, "peerDependencies": { @@ -874,11 +907,11 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.4.tgz", - "integrity": "sha512-CF8k2rgKeh/49UrnIBs4BdxPUV6vize/Db1d/YbCLyp9GiVZ0BEwf5AiDSxJRCr6yOkGqTFHtmrULxkEfYZ7dQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", + "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==", "dependencies": { - "@floating-ui/dom": "^1.5.1" + "@floating-ui/dom": "^1.6.1" }, "peerDependencies": { "react": ">=16.8.0", @@ -886,18 +919,18 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", - "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, "node_modules/@headlessui-float/react": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@headlessui-float/react/-/react-0.13.0.tgz", - "integrity": "sha512-DKL6av8rOrxQNBCIhGSfvn0AzW3jrQQKe2nwH9T29LegtuRJPBWF/AtMRi4piHPtjbeDRzvZdIYyrR1S9CSlew==", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@headlessui-float/react/-/react-0.13.2.tgz", + "integrity": "sha512-+SWOuKhfMvNZ6yqPsLAC4/N8FnHASBXIJxJQ9kqDZmeP08V5nzfnsQh1UxKJPktpfPWQkPaL+RoONxNqkQfM8A==", "dependencies": { - "@floating-ui/core": "^1.3.0", - "@floating-ui/dom": "^1.3.0", - "@floating-ui/react": "^0.26.0" + "@floating-ui/core": "^1.5.3", + "@floating-ui/dom": "^1.5.4", + "@floating-ui/react": "^0.26.5" }, "peerDependencies": { "@headlessui/react": "^1.0.0", @@ -906,10 +939,11 @@ } }, "node_modules/@headlessui/react": { - "version": "1.7.17", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.17.tgz", - "integrity": "sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==", + "version": "1.7.18", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.18.tgz", + "integrity": "sha512-4i5DOrzwN4qSgNsL4Si61VMkUcWbcSKueUV7sFhpHzQcSShdlHENE5+QBntMSRvHt8NyoFO2AGG8si9lq+w4zQ==", "dependencies": { + "@tanstack/react-virtual": "^3.0.0-beta.60", "client-only": "^0.0.1" }, "engines": { @@ -934,6 +968,28 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -945,6 +1001,96 @@ "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -960,9 +1106,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" @@ -984,24 +1130,19 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@ledgerhq/connect-kit-loader": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ledgerhq/connect-kit-loader/-/connect-kit-loader-1.1.2.tgz", - "integrity": "sha512-mscwGroSJQrCTjtNGBu+18FQbZYA4+q6Tyx6K7CXHl6AwgZKbWfZYdgP2F+fyZcRUdGRsMX8QtvU61VcGGtO1A==" - }, "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.2.tgz", - "integrity": "sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz", + "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==" }, "node_modules/@lit/reactive-element": { "version": "1.6.3", @@ -1039,45 +1180,45 @@ } }, "node_modules/@motionone/animation": { - "version": "10.16.3", - "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.16.3.tgz", - "integrity": "sha512-QUGWpLbMFLhyqKlngjZhjtxM8IqiJQjLK0DF+XOF6od9nhSvlaeEpOY/UMCRVcZn/9Tr2rZO22EkuCIjYdI74g==", + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.17.0.tgz", + "integrity": "sha512-ANfIN9+iq1kGgsZxs+Nz96uiNcPLGTXwfNo2Xz/fcJXniPYpaz/Uyrfa+7I5BPLxCP82sh7quVDudf1GABqHbg==", "dependencies": { - "@motionone/easing": "^10.16.3", - "@motionone/types": "^10.16.3", - "@motionone/utils": "^10.16.3", + "@motionone/easing": "^10.17.0", + "@motionone/types": "^10.17.0", + "@motionone/utils": "^10.17.0", "tslib": "^2.3.1" } }, "node_modules/@motionone/dom": { - "version": "10.16.4", - "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.16.4.tgz", - "integrity": "sha512-HPHlVo/030qpRj9R8fgY50KTN4Ko30moWRTA3L3imrsRBmob93cTYmodln49HYFbQm01lFF7X523OkKY0DX6UA==", - "dependencies": { - "@motionone/animation": "^10.16.3", - "@motionone/generators": "^10.16.4", - "@motionone/types": "^10.16.3", - "@motionone/utils": "^10.16.3", + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.17.0.tgz", + "integrity": "sha512-cMm33swRlCX/qOPHWGbIlCl0K9Uwi6X5RiL8Ma6OrlJ/TP7Q+Np5GE4xcZkFptysFjMTi4zcZzpnNQGQ5D6M0Q==", + "dependencies": { + "@motionone/animation": "^10.17.0", + "@motionone/generators": "^10.17.0", + "@motionone/types": "^10.17.0", + "@motionone/utils": "^10.17.0", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "node_modules/@motionone/easing": { - "version": "10.16.3", - "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.16.3.tgz", - "integrity": "sha512-HWTMZbTmZojzwEuKT/xCdvoMPXjYSyQvuVM6jmM0yoGU6BWzsmYMeB4bn38UFf618fJCNtP9XeC/zxtKWfbr0w==", + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.17.0.tgz", + "integrity": "sha512-Bxe2wSuLu/qxqW4rBFS5m9tMLOw+QBh8v5A7Z5k4Ul4sTj5jAOfZG5R0bn5ywmk+Fs92Ij1feZ5pmC4TeXA8Tg==", "dependencies": { - "@motionone/utils": "^10.16.3", + "@motionone/utils": "^10.17.0", "tslib": "^2.3.1" } }, "node_modules/@motionone/generators": { - "version": "10.16.4", - "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.16.4.tgz", - "integrity": "sha512-geFZ3w0Rm0ZXXpctWsSf3REGywmLLujEjxPYpBR0j+ymYwof0xbV6S5kGqqsDKgyWKVWpUInqQYvQfL6fRbXeg==", + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.17.0.tgz", + "integrity": "sha512-T6Uo5bDHrZWhIfxG/2Aut7qyWQyJIWehk6OB4qNvr/jwA/SRmixwbd7SOrxZi1z5rH3LIeFFBKK1xHnSbGPZSQ==", "dependencies": { - "@motionone/types": "^10.16.3", - "@motionone/utils": "^10.16.3", + "@motionone/types": "^10.17.0", + "@motionone/utils": "^10.17.0", "tslib": "^2.3.1" } }, @@ -1091,16 +1232,16 @@ } }, "node_modules/@motionone/types": { - "version": "10.16.3", - "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.16.3.tgz", - "integrity": "sha512-W4jkEGFifDq73DlaZs3HUfamV2t1wM35zN/zX7Q79LfZ2sc6C0R1baUHZmqc/K5F3vSw3PavgQ6HyHLd/MXcWg==" + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.0.tgz", + "integrity": "sha512-EgeeqOZVdRUTEHq95Z3t8Rsirc7chN5xFAPMYFobx8TPubkEfRSm5xihmMUkbaR2ErKJTUw3347QDPTHIW12IA==" }, "node_modules/@motionone/utils": { - "version": "10.16.3", - "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.16.3.tgz", - "integrity": "sha512-WNWDksJIxQkaI9p9Z9z0+K27xdqISGNFy1SsWVGaiedTHq0iaT6iZujby8fT/ZnZxj1EOaxJtSfUPCFNU5CRoA==", + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.17.0.tgz", + "integrity": "sha512-bGwrki4896apMWIj9yp5rAS2m0xyhxblg6gTB/leWDPt+pb410W8lYWsxyurX+DH+gO1zsQsfx2su/c1/LtTpg==", "dependencies": { - "@motionone/types": "^10.16.3", + "@motionone/types": "^10.17.0", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } @@ -1109,6 +1250,7 @@ "version": "10.16.4", "resolved": "https://registry.npmjs.org/@motionone/vue/-/vue-10.16.4.tgz", "integrity": "sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg==", + "deprecated": "Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion", "dependencies": { "@motionone/dom": "^10.16.4", "tslib": "^2.3.1" @@ -1326,9 +1468,9 @@ } }, "node_modules/@parcel/watcher": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.3.0.tgz", - "integrity": "sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.0.tgz", + "integrity": "sha512-XJLGVL0DEclX5pcWa2N9SX1jCGTDd8l972biNooLFtjneuGqodupPQh6XseXIBBeVIMaaJ7bTcs3qGvXwsp4vg==", "hasInstallScript": true, "dependencies": { "detect-libc": "^1.0.3", @@ -1344,24 +1486,24 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.3.0", - "@parcel/watcher-darwin-arm64": "2.3.0", - "@parcel/watcher-darwin-x64": "2.3.0", - "@parcel/watcher-freebsd-x64": "2.3.0", - "@parcel/watcher-linux-arm-glibc": "2.3.0", - "@parcel/watcher-linux-arm64-glibc": "2.3.0", - "@parcel/watcher-linux-arm64-musl": "2.3.0", - "@parcel/watcher-linux-x64-glibc": "2.3.0", - "@parcel/watcher-linux-x64-musl": "2.3.0", - "@parcel/watcher-win32-arm64": "2.3.0", - "@parcel/watcher-win32-ia32": "2.3.0", - "@parcel/watcher-win32-x64": "2.3.0" + "@parcel/watcher-android-arm64": "2.4.0", + "@parcel/watcher-darwin-arm64": "2.4.0", + "@parcel/watcher-darwin-x64": "2.4.0", + "@parcel/watcher-freebsd-x64": "2.4.0", + "@parcel/watcher-linux-arm-glibc": "2.4.0", + "@parcel/watcher-linux-arm64-glibc": "2.4.0", + "@parcel/watcher-linux-arm64-musl": "2.4.0", + "@parcel/watcher-linux-x64-glibc": "2.4.0", + "@parcel/watcher-linux-x64-musl": "2.4.0", + "@parcel/watcher-win32-arm64": "2.4.0", + "@parcel/watcher-win32-ia32": "2.4.0", + "@parcel/watcher-win32-x64": "2.4.0" } }, "node_modules/@parcel/watcher-android-arm64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.3.0.tgz", - "integrity": "sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.0.tgz", + "integrity": "sha512-+fPtO/GsbYX1LJnCYCaDVT3EOBjvSFdQN9Mrzh9zWAOOfvidPWyScTrHIZHHfJBvlHzNA0Gy0U3NXFA/M7PHUA==", "cpu": [ "arm64" ], @@ -1378,9 +1520,9 @@ } }, "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.3.0.tgz", - "integrity": "sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.0.tgz", + "integrity": "sha512-T/At5pansFuQ8VJLRx0C6C87cgfqIYhW2N/kBfLCUvDhCah0EnLLwaD/6MW3ux+rpgkpQAnMELOCTKlbwncwiA==", "cpu": [ "arm64" ], @@ -1397,9 +1539,9 @@ } }, "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.3.0.tgz", - "integrity": "sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.0.tgz", + "integrity": "sha512-vZMv9jl+szz5YLsSqEGCMSllBl1gU1snfbRL5ysJU03MEa6gkVy9OMcvXV1j4g0++jHEcvzhs3Z3LpeEbVmY6Q==", "cpu": [ "x64" ], @@ -1416,9 +1558,9 @@ } }, "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.3.0.tgz", - "integrity": "sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.0.tgz", + "integrity": "sha512-dHTRMIplPDT1M0+BkXjtMN+qLtqq24sLDUhmU+UxxLP2TEY2k8GIoqIJiVrGWGomdWsy5IO27aDV1vWyQ6gfHA==", "cpu": [ "x64" ], @@ -1435,9 +1577,9 @@ } }, "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.3.0.tgz", - "integrity": "sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.0.tgz", + "integrity": "sha512-9NQXD+qk46RwATNC3/UB7HWurscY18CnAPMTFcI9Y8CTbtm63/eex1SNt+BHFinEQuLBjaZwR2Lp+n7pmEJPpQ==", "cpu": [ "arm" ], @@ -1454,9 +1596,9 @@ } }, "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.3.0.tgz", - "integrity": "sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.0.tgz", + "integrity": "sha512-QuJTAQdsd7PFW9jNGaV9Pw+ZMWV9wKThEzzlY3Lhnnwy7iW23qtQFPql8iEaSFMCVI5StNNmONUopk+MFKpiKg==", "cpu": [ "arm64" ], @@ -1473,9 +1615,9 @@ } }, "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.3.0.tgz", - "integrity": "sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.0.tgz", + "integrity": "sha512-oyN+uA9xcTDo/45bwsd6TFHa7Lc7hKujyMlvwrCLvSckvWogndCEoVYFNfZ6JJ2KNL/6fFiGPcbjp8jJmEh5Ng==", "cpu": [ "arm64" ], @@ -1492,9 +1634,9 @@ } }, "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.3.0.tgz", - "integrity": "sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.0.tgz", + "integrity": "sha512-KphV8awJmxU3q52JQvJot0QMu07CIyEjV+2Tb2ZtbucEgqyRcxOBDMsqp1JNq5nuDXtcCC0uHQICeiEz38dPBQ==", "cpu": [ "x64" ], @@ -1511,9 +1653,9 @@ } }, "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.3.0.tgz", - "integrity": "sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.0.tgz", + "integrity": "sha512-7jzcOonpXNWcSijPpKD5IbC6xC7yTibjJw9jviVzZostYLGxbz8LDJLUnLzLzhASPlPGgpeKLtFUMjAAzM+gSA==", "cpu": [ "x64" ], @@ -1530,9 +1672,9 @@ } }, "node_modules/@parcel/watcher-wasm": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.3.0.tgz", - "integrity": "sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.4.0.tgz", + "integrity": "sha512-MNgQ4WCbBybqQ97KwR/hqJGYTg3+s8qHpgIyFWB2qJOBvoJWbXuJGmm4ZkPLq2bMaANqCZqrXwmKYagZTkMKZA==", "bundleDependencies": [ "napi-wasm" ], @@ -1555,9 +1697,9 @@ "license": "MIT" }, "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.3.0.tgz", - "integrity": "sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.0.tgz", + "integrity": "sha512-NOej2lqlq8bQNYhUMnOD0nwvNql8ToQF+1Zhi9ULZoG+XTtJ9hNnCFfyICxoZLXor4bBPTOnzs/aVVoefYnjIg==", "cpu": [ "arm64" ], @@ -1574,9 +1716,9 @@ } }, "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.3.0.tgz", - "integrity": "sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.0.tgz", + "integrity": "sha512-IO/nM+K2YD/iwjWAfHFMBPz4Zqn6qBDqZxY4j2n9s+4+OuTSRM/y/irksnuqcspom5DjkSeF9d0YbO+qpys+JA==", "cpu": [ "ia32" ], @@ -1593,9 +1735,9 @@ } }, "node_modules/@parcel/watcher-win32-x64": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.3.0.tgz", - "integrity": "sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.0.tgz", + "integrity": "sha512-pAUyUVjfFjWaf/pShmJpJmNxZhbMvJASUpdes9jL6bTEJ+gDxPRSpXTIemNyNsb9AtbiGXs9XduP1reThmd+dA==", "cpu": [ "x64" ], @@ -1612,21 +1754,35 @@ } }, "node_modules/@parcel/watcher/node_modules/node-addon-api": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", - "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", + "integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==", + "engines": { + "node": "^16 || ^18 || >= 20" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } }, "node_modules/@rainbow-me/rainbowkit": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@rainbow-me/rainbowkit/-/rainbowkit-1.0.4.tgz", - "integrity": "sha512-ceW0azA1EynlM21zG/bpA7QsXx8taX3NoR78Z1RgbZwujM//6PWJQRGBA4VvHJkmuio/R2lfP51inJucs+i4gg==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@rainbow-me/rainbowkit/-/rainbowkit-1.3.6.tgz", + "integrity": "sha512-NA9jAX3Niw0T0OMJQ1jsjPmB3XHbifK2+6e75YJEwxPR4JDFRF0wjW25kzHBSpn6VgayPK7dOZM5Z+zURClvug==", "dependencies": { - "@vanilla-extract/css": "1.9.1", - "@vanilla-extract/dynamic": "2.0.2", - "@vanilla-extract/sprinkles": "1.5.0", - "clsx": "1.1.1", - "qrcode": "1.5.0", - "react-remove-scroll": "2.5.4" + "@vanilla-extract/css": "1.14.0", + "@vanilla-extract/dynamic": "2.1.0", + "@vanilla-extract/sprinkles": "1.6.1", + "clsx": "2.1.0", + "qrcode": "1.5.3", + "react-remove-scroll": "2.5.7", + "ua-parser-js": "^1.0.37" }, "engines": { "node": ">=12.4" @@ -1635,7 +1791,7 @@ "react": ">=17", "react-dom": ">=17", "viem": "~0.3.19 || ^1.0.0", - "wagmi": "~1.0.1 || ~1.1.0 || ~1.2.0 || ~1.3.0" + "wagmi": "~1.0.1 || ~1.1.0 || ~1.2.0 || ~1.3.0 || ~1.4.0" } }, "node_modules/@rainbow-me/rainbowkit-siwe-next-auth": { @@ -1653,27 +1809,27 @@ } }, "node_modules/@rushstack/eslint-patch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz", - "integrity": "sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz", + "integrity": "sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==", "dev": true }, "node_modules/@safe-global/safe-apps-provider": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.17.1.tgz", - "integrity": "sha512-lYfRqrbbK1aKU1/UGkYWc/X7PgySYcumXKc5FB2uuwAs2Ghj8uETuW5BrwPqyjBknRxutFbTv+gth/JzjxAhdQ==", + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.2.tgz", + "integrity": "sha512-yHHAcppwE7aIUWEeZiYAClQzZCdP5l0Kbd0CBlhKAsTcqZnx4Gh3G3G3frY5LlWcGzp9qmQ5jv+J1GBpaZLDgw==", "dependencies": { - "@safe-global/safe-apps-sdk": "8.0.0", + "@safe-global/safe-apps-sdk": "^9.0.0", "events": "^3.3.0" } }, "node_modules/@safe-global/safe-apps-provider/node_modules/@safe-global/safe-apps-sdk": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-8.0.0.tgz", - "integrity": "sha512-gYw0ki/EAuV1oSyMxpqandHjnthZjYYy+YWpTAzf8BqfXM3ItcZLpjxfg+3+mXW8HIO+3jw6T9iiqEXsqHaMMw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.0.0.tgz", + "integrity": "sha512-fEqmQBU3JqTjORSl3XYrcaxdxkUqeeM39qsQjqCzzTHioN8DEfg3JCLq6EBoXzcKTVOYi8SPzLV7KJccdDw+4w==", "dependencies": { "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", - "viem": "^1.0.0" + "viem": "^1.6.0" } }, "node_modules/@safe-global/safe-apps-sdk": { @@ -1686,17 +1842,17 @@ } }, "node_modules/@safe-global/safe-gateway-typescript-sdk": { - "version": "3.13.2", - "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.13.2.tgz", - "integrity": "sha512-kGlJecJHBzGrGTq/yhLANh56t+Zur6Ubpt+/w03ARX1poDb4TM8vKU3iV8tuYpk359PPWp+Qvjnqb9oW2YQcYw==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.15.0.tgz", + "integrity": "sha512-zAzhPgUwzdp89ZrZwCAOImUyAQMQE0LQKcK4vLO5eMbfAcNOxz5g4eVdBRBRa+kVXxjyW5wii58ZlGaYUVBa7g==", "engines": { "node": ">=16" } }, "node_modules/@scure/base": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", - "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", + "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", "funding": { "url": "https://paulmillr.com/funding/" } @@ -1738,15 +1894,15 @@ } }, "node_modules/@solana/web3.js": { - "version": "1.87.6", - "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.87.6.tgz", - "integrity": "sha512-LkqsEBgTZztFiccZZXnawWa8qNCATEqE97/d0vIwjTclmVlc8pBpD1DmjfVHtZ1HS5fZorFlVhXfpwnCNDZfyg==", + "version": "1.90.0", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.90.0.tgz", + "integrity": "sha512-p0cb/COXb8NNVSMkGMPwqQ6NvObZgUitN80uOedMB+jbYWOKOeJBuPnzhenkIV9RX0krGwyuY1Ltn5O8MGFsEw==", "dependencies": { - "@babel/runtime": "^7.23.2", + "@babel/runtime": "^7.23.4", "@noble/curves": "^1.2.0", - "@noble/hashes": "^1.3.1", - "@solana/buffer-layout": "^4.0.0", - "agentkeepalive": "^4.3.0", + "@noble/hashes": "^1.3.2", + "@solana/buffer-layout": "^4.0.1", + "agentkeepalive": "^4.5.0", "bigint-buffer": "^1.1.5", "bn.js": "^5.2.1", "borsh": "^0.7.0", @@ -1754,7 +1910,7 @@ "buffer": "6.0.3", "fast-stable-stringify": "^1.0.0", "jayson": "^4.1.0", - "node-fetch": "^2.6.12", + "node-fetch": "^2.7.0", "rpc-websockets": "^7.5.1", "superstruct": "^0.14.2" } @@ -1995,6 +2151,31 @@ "@tanstack/react-query": "^4.36.1" } }, + "node_modules/@tanstack/react-virtual": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.1.1.tgz", + "integrity": "sha512-9tW9xwEW7exSa/8bxu29IPCcB5c9Xlq+whETixIIgYZYKuUY4ZOr000q3oLpL4bkOkolQbB4WXM0MoQGgJXqDg==", + "dependencies": { + "@tanstack/virtual-core": "3.1.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.1.1.tgz", + "integrity": "sha512-I5lerX+RWxLM+zw35gwwQIoLvtkOm0ecuQUlEjNey+Ga6TnR66WKLBnSHre59onugxhpDLT2nofRYzxf+izDFQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -2014,8 +2195,7 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -2029,17 +2209,17 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "20.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", - "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", + "version": "20.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", + "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", "dev": true, "dependencies": { "@types/node": "*", @@ -2053,9 +2233,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.41", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.41.tgz", - "integrity": "sha512-CwOGr/PiLiNBxEBqpJ7fO3kocP/2SSuC9fpH5K7tusrg4xPSRT/193rzolYwQnTN02We/ATXKnb6GqA5w4fRxw==", + "version": "18.2.57", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.57.tgz", + "integrity": "sha512-ZvQsktJgSYrQiMirAN60y4O/LRevIV8hUzSOSNB6gfR3/o3wCBFQx3sPwIYtuDMeiVgsSS3UzCV26tEzgnfvQw==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -2064,9 +2244,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.17", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.17.tgz", - "integrity": "sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz", + "integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==", "dev": true, "dependencies": { "@types/react": "*" @@ -2081,8 +2261,7 @@ "node_modules/@types/semver": { "version": "7.5.7", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", - "dev": true + "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==" }, "node_modules/@types/trusted-types": { "version": "2.0.7", @@ -2101,7 +2280,6 @@ "version": "5.54.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz", "integrity": "sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==", - "dev": true, "dependencies": { "@typescript-eslint/scope-manager": "5.54.1", "@typescript-eslint/type-utils": "5.54.1", @@ -2131,44 +2309,58 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz", - "integrity": "sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==", + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/visitor-keys": "5.54.1" + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz", - "integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "node_modules/@typescript-eslint/scope-manager": { "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz", - "integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==", - "dev": true, + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz", + "integrity": "sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==", "dependencies": { "@typescript-eslint/types": "5.54.1", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/visitor-keys": "5.54.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2178,45 +2370,28 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.1.tgz", - "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", - "debug": "^4.3.4" - }, + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "5.54.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz", + "integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", - "dev": true, + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.54.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz", + "integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==", "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "5.54.1", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", @@ -2227,7 +2402,6 @@ "version": "5.54.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz", "integrity": "sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==", - "dev": true, "dependencies": { "@typescript-eslint/typescript-estree": "5.54.1", "@typescript-eslint/utils": "5.54.1", @@ -2254,7 +2428,6 @@ "version": "5.54.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz", "integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2267,7 +2440,6 @@ "version": "5.54.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz", "integrity": "sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.54.1", "@typescript-eslint/visitor-keys": "5.54.1", @@ -2294,7 +2466,6 @@ "version": "5.54.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz", "integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.54.1", "eslint-visitor-keys": "^3.3.0" @@ -2308,9 +2479,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2321,16 +2492,17 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -2351,7 +2523,6 @@ "version": "5.54.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.1.tgz", "integrity": "sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", @@ -2373,15 +2544,10 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz", - "integrity": "sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/visitor-keys": "5.54.1" - }, + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz", + "integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2390,24 +2556,10 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz", - "integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { "version": "5.54.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz", "integrity": "sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.54.1", "@typescript-eslint/visitor-keys": "5.54.1", @@ -2434,7 +2586,6 @@ "version": "5.54.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz", "integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==", - "dev": true, "dependencies": { "@typescript-eslint/types": "5.54.1", "eslint-visitor-keys": "^3.3.0" @@ -2447,35 +2598,13 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2487,27 +2616,27 @@ } }, "node_modules/@vanilla-extract/css": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.9.1.tgz", - "integrity": "sha512-pu2SFiff5jRhPwvGoj8cM5l/qIyLvigOmy22ss5DGjwV5pJYezRjDLxWumi2luIwioMWvh9EozCjyfH8nq+7fQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.14.0.tgz", + "integrity": "sha512-rYfm7JciWZ8PFzBM/HDiE2GLnKI3xJ6/vdmVJ5BSgcCZ5CxRlM9Cjqclni9lGzF3eMOijnUhCd/KV8TOzyzbMA==", "dependencies": { - "@emotion/hash": "^0.8.0", + "@emotion/hash": "^0.9.0", "@vanilla-extract/private": "^1.0.3", - "ahocorasick": "1.0.2", "chalk": "^4.1.1", - "css-what": "^5.0.1", + "css-what": "^6.1.0", "cssesc": "^3.0.0", "csstype": "^3.0.7", - "deep-object-diff": "^1.1.0", + "deep-object-diff": "^1.1.9", "deepmerge": "^4.2.2", "media-query-parser": "^2.0.2", + "modern-ahocorasick": "^1.0.0", "outdent": "^0.8.0" } }, "node_modules/@vanilla-extract/dynamic": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@vanilla-extract/dynamic/-/dynamic-2.0.2.tgz", - "integrity": "sha512-U4nKaEQ8Kuz+exXEr51DUpyaOuzo24/S/k1YbDPQR06cYcNjQqvwFRnwWtZ+9ImocqM1wTKtzrdUgSTtLGIwAg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vanilla-extract/dynamic/-/dynamic-2.1.0.tgz", + "integrity": "sha512-8zl0IgBYRtgD1h+56Zu13wHTiMTJSVEa4F7RWX9vTB/5Xe2KtjoiqApy/szHPVFA56c+ex6A4GpCQjT1bKXbYw==", "dependencies": { "@vanilla-extract/private": "^1.0.3" } @@ -2518,17 +2647,17 @@ "integrity": "sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ==" }, "node_modules/@vanilla-extract/sprinkles": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vanilla-extract/sprinkles/-/sprinkles-1.5.0.tgz", - "integrity": "sha512-W58f2Rzz5lLmk0jbhgStVlZl5wEiPB1Ur3fRvUaBM+MrifZ3qskmFq/CiH//fEYeG5Dh9vF1qRviMMH46cX9Nw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vanilla-extract/sprinkles/-/sprinkles-1.6.1.tgz", + "integrity": "sha512-N/RGKwGAAidBupZ436RpuweRQHEFGU+mvAqBo8PRMAjJEmHoPDttV8RObaMLrJHWLqvX+XUMinHUnD0hFRQISw==", "peerDependencies": { "@vanilla-extract/css": "^1.0.0" } }, "node_modules/@wagmi/connectors": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-3.1.5.tgz", - "integrity": "sha512-aE4rWZbivqWa9HqjiLDPtwROH2b1Az+lBVMeZ3o/aFxGNGNEkdrSAMOUG15/UFy3VnN6HqGOtTobOBZ10JhfNQ==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-3.1.11.tgz", + "integrity": "sha512-wzxp9f9PtSUFjDUP/QDjc1t7HON4D8wrVKsw35ejdO8hToDpx1gU9lwH/47Zo/1zExGezQc392sjoHSszYd7OA==", "funding": [ { "type": "gitcoin", @@ -2541,13 +2670,12 @@ ], "dependencies": { "@coinbase/wallet-sdk": "^3.6.6", - "@ledgerhq/connect-kit-loader": "^1.1.0", - "@safe-global/safe-apps-provider": "^0.17.1", - "@safe-global/safe-apps-sdk": "^8.0.0", - "@walletconnect/ethereum-provider": "2.10.2", + "@safe-global/safe-apps-provider": "^0.18.1", + "@safe-global/safe-apps-sdk": "^8.1.0", + "@walletconnect/ethereum-provider": "2.11.0", "@walletconnect/legacy-provider": "^2.0.0", "@walletconnect/modal": "2.6.2", - "@walletconnect/utils": "2.10.2", + "@walletconnect/utils": "2.11.0", "abitype": "0.8.7", "eventemitter3": "^4.0.7" }, @@ -2576,9 +2704,9 @@ } }, "node_modules/@wagmi/core": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-1.4.7.tgz", - "integrity": "sha512-PiOIGni8ArQoPmuDylHX38zMt2nPnTYRIluIqiduKyGCM61X/tf10a0rafUMOOphDPudZu1TacNDhCSeoh/LEA==", + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-1.4.13.tgz", + "integrity": "sha512-ytMCvXbBOgfDu9Qw67279wq/jNEe7EZLjLyekX7ROnvHRADqFr3lwZI6ih41UmtRZAmXAx8Ghyuqy154EjB5mQ==", "funding": [ { "type": "gitcoin", @@ -2590,7 +2718,7 @@ } ], "dependencies": { - "@wagmi/connectors": "3.1.5", + "@wagmi/connectors": "3.1.11", "abitype": "0.8.7", "eventemitter3": "^4.0.7", "zustand": "^4.3.1" @@ -2620,24 +2748,25 @@ } }, "node_modules/@walletconnect/core": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.10.2.tgz", - "integrity": "sha512-JQz/xp3SLEpTeRQctdck2ugSBVEpMxoSE+lFi2voJkZop1hv6P+uqr6E4PzjFluAjeAnKlT1xvra0aFWjPWVcw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.11.0.tgz", + "integrity": "sha512-2Tjp5BCevI7dbmqo/OrCjX4tqgMqwJNQLlQAlphqPfvwlF9+tIu6pGcVbSN3U9zyXzWIZCeleqEaWUeSeET4Ew==", "dependencies": { "@walletconnect/heartbeat": "1.2.1", "@walletconnect/jsonrpc-provider": "1.0.13", "@walletconnect/jsonrpc-types": "1.0.3", "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/jsonrpc-ws-connection": "1.0.13", - "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/jsonrpc-ws-connection": "1.0.14", + "@walletconnect/keyvaluestorage": "^1.1.1", "@walletconnect/logger": "^2.0.1", "@walletconnect/relay-api": "^1.0.9", "@walletconnect/relay-auth": "^1.0.4", "@walletconnect/safe-json": "^1.0.2", "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.10.2", - "@walletconnect/utils": "2.10.2", + "@walletconnect/types": "2.11.0", + "@walletconnect/utils": "2.11.0", "events": "^3.3.0", + "isomorphic-unfetch": "3.1.0", "lodash.isequal": "4.5.0", "uint8arrays": "^3.1.0" } @@ -2655,6 +2784,11 @@ "tslib": "1.14.1" } }, + "node_modules/@walletconnect/crypto/node_modules/aes-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", + "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==" + }, "node_modules/@walletconnect/crypto/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -2689,27 +2823,20 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@walletconnect/ethereum-provider": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@walletconnect/ethereum-provider/-/ethereum-provider-2.10.2.tgz", - "integrity": "sha512-QMYFZ6+rVq2CJLdIPdKK0j1Qm66UA27oQU5V2SrL8EVwl7wFfm0Bq7fnL+qAWeDpn612dNeNErpk/ROa1zWlWg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@walletconnect/ethereum-provider/-/ethereum-provider-2.11.0.tgz", + "integrity": "sha512-YrTeHVjuSuhlUw7SQ6xBJXDuJ6iAC+RwINm9nVhoKYJSHAy3EVSJZOofMKrnecL0iRMtD29nj57mxAInIBRuZA==", "dependencies": { "@walletconnect/jsonrpc-http-connection": "^1.0.7", "@walletconnect/jsonrpc-provider": "^1.0.13", "@walletconnect/jsonrpc-types": "^1.0.3", "@walletconnect/jsonrpc-utils": "^1.0.8", - "@walletconnect/sign-client": "2.10.2", - "@walletconnect/types": "2.10.2", - "@walletconnect/universal-provider": "2.10.2", - "@walletconnect/utils": "2.10.2", + "@walletconnect/modal": "^2.6.2", + "@walletconnect/sign-client": "2.11.0", + "@walletconnect/types": "2.11.0", + "@walletconnect/universal-provider": "2.11.0", + "@walletconnect/utils": "2.11.0", "events": "^3.3.0" - }, - "peerDependencies": { - "@walletconnect/modal": ">=2" - }, - "peerDependenciesMeta": { - "@walletconnect/modal": { - "optional": true - } } }, "node_modules/@walletconnect/events": { @@ -2802,22 +2929,16 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@walletconnect/jsonrpc-ws-connection": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.13.tgz", - "integrity": "sha512-mfOM7uFH4lGtQxG+XklYuFBj6dwVvseTt5/ahOkkmpcAEgz2umuzu7fTR+h5EmjQBdrmYyEBOWADbeaFNxdySg==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz", + "integrity": "sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA==", "dependencies": { "@walletconnect/jsonrpc-utils": "^1.0.6", "@walletconnect/safe-json": "^1.0.2", "events": "^3.3.0", - "tslib": "1.14.1", "ws": "^7.5.1" } }, - "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", @@ -2885,23 +3006,6 @@ "qrcode": "^1.5.1" } }, - "node_modules/@walletconnect/legacy-modal/node_modules/qrcode": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", - "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", - "dependencies": { - "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@walletconnect/legacy-provider": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@walletconnect/legacy-provider/-/legacy-provider-2.0.0.tgz", @@ -2980,23 +3084,6 @@ "qrcode": "1.5.3" } }, - "node_modules/@walletconnect/modal-ui/node_modules/qrcode": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", - "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", - "dependencies": { - "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@walletconnect/randombytes": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@walletconnect/randombytes/-/randombytes-1.0.3.tgz", @@ -3059,18 +3146,18 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@walletconnect/sign-client": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.10.2.tgz", - "integrity": "sha512-vviSLV3f92I0bReX+OLr1HmbH0uIzYEQQFd1MzIfDk9PkfFT/LLAHhUnDaIAMkIdippqDcJia+5QEtT4JihL3Q==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.11.0.tgz", + "integrity": "sha512-H2ukscibBS+6WrzQWh+WyVBqO5z4F5et12JcwobdwgHnJSlqIoZxqnUYYWNCI5rUR5UKsKWaUyto4AE9N5dw4Q==", "dependencies": { - "@walletconnect/core": "2.10.2", + "@walletconnect/core": "2.11.0", "@walletconnect/events": "^1.0.1", "@walletconnect/heartbeat": "1.2.1", "@walletconnect/jsonrpc-utils": "1.0.8", "@walletconnect/logger": "^2.0.1", "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.10.2", - "@walletconnect/utils": "2.10.2", + "@walletconnect/types": "2.11.0", + "@walletconnect/utils": "2.11.0", "events": "^3.3.0" } }, @@ -3088,38 +3175,38 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@walletconnect/types": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.10.2.tgz", - "integrity": "sha512-luNV+07Wdla4STi9AejseCQY31tzWKQ5a7C3zZZaRK/di+rFaAAb7YW04OP4klE7tw/mJRGPTlekZElmHxO8kQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.11.0.tgz", + "integrity": "sha512-AB5b1lrEbCGHxqS2vqfCkIoODieH+ZAUp9rA1O2ftrhnqDJiJK983Df87JhYhECsQUBHHfALphA8ydER0q+9sw==", "dependencies": { "@walletconnect/events": "^1.0.1", "@walletconnect/heartbeat": "1.2.1", "@walletconnect/jsonrpc-types": "1.0.3", - "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/keyvaluestorage": "^1.1.1", "@walletconnect/logger": "^2.0.1", "events": "^3.3.0" } }, "node_modules/@walletconnect/universal-provider": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.10.2.tgz", - "integrity": "sha512-wFgI0LbQ3D56sgaUMsgOHCM5m8WLxiC71BGuCKQfApgsbNMVKugYVy2zWHyUyi8sqTQHI+uSaVpDev4UHq9LEw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.11.0.tgz", + "integrity": "sha512-zgJv8jDvIMP4Qse/D9oIRXGdfoNqonsrjPZanQ/CHNe7oXGOBiQND2IIeX+tS0H7uNA0TPvctljCLiIN9nw4eA==", "dependencies": { "@walletconnect/jsonrpc-http-connection": "^1.0.7", "@walletconnect/jsonrpc-provider": "1.0.13", "@walletconnect/jsonrpc-types": "^1.0.2", "@walletconnect/jsonrpc-utils": "^1.0.7", "@walletconnect/logger": "^2.0.1", - "@walletconnect/sign-client": "2.10.2", - "@walletconnect/types": "2.10.2", - "@walletconnect/utils": "2.10.2", + "@walletconnect/sign-client": "2.11.0", + "@walletconnect/types": "2.11.0", + "@walletconnect/utils": "2.11.0", "events": "^3.3.0" } }, "node_modules/@walletconnect/utils": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.10.2.tgz", - "integrity": "sha512-syxXRpc2yhSknMu3IfiBGobxOY7fLfLTJuw+ppKaeO6WUdZpIit3wfuGOcc0Ms3ZPFCrGfyGOoZsCvgdXtptRg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.11.0.tgz", + "integrity": "sha512-hxkHPlTlDQILHfIKXlmzgNJau/YcSBC3XHUSuZuKZbNEw3duFT6h6pm3HT/1+j1a22IG05WDsNBuTCRkwss+BQ==", "dependencies": { "@stablelib/chacha20poly1305": "1.0.1", "@stablelib/hkdf": "1.0.1", @@ -3129,7 +3216,7 @@ "@walletconnect/relay-api": "^1.0.9", "@walletconnect/safe-json": "^1.0.2", "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.10.2", + "@walletconnect/types": "2.11.0", "@walletconnect/window-getters": "^1.0.1", "@walletconnect/window-metadata": "^1.0.1", "detect-browser": "5.3.0", @@ -3205,9 +3292,9 @@ } }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "bin": { "acorn": "bin/acorn" }, @@ -3224,11 +3311,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/aes-js": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", - "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==" - }, "node_modules/agentkeepalive": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", @@ -3240,11 +3322,6 @@ "node": ">= 8.0.0" } }, - "node_modules/ahocorasick": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ahocorasick/-/ahocorasick-1.0.2.tgz", - "integrity": "sha512-hCOfMzbFx5IDutmWLAt6MZwOUjIfSM9G9FyVxytmE4Rs/5YDPWQrD/+IR1w+FweD9H2oOZEnv36TmkjhNURBVA==" - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -3261,6 +3338,27 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/alchemy-sdk": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/alchemy-sdk/-/alchemy-sdk-3.1.2.tgz", + "integrity": "sha512-xpCgQRLektp6imKdGdHyuVHvbMGpaSe22+qvg9jjGx0Wwkh0XgPzSfKwAzFDlkCGMMdazhKCsHu22XP0xh1noQ==", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/contracts": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/providers": "^5.7.0", + "@ethersproject/units": "^5.7.0", + "@ethersproject/wallet": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "axios": "^1.6.5", + "sturdy-websocket": "^0.2.1", + "websocket": "^1.0.34" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -3306,25 +3404,6 @@ "resolved": "https://registry.npmjs.org/apg-js/-/apg-js-4.3.0.tgz", "integrity": "sha512-8U8MULS+JocCnm11bfrVS4zxtAcE3uOiCAI21SnjDrV9LNhMSGwTGGeko3QfyK1JLWwT7KebFqJMB2puzfdFMQ==" }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -3347,13 +3426,16 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3386,17 +3468,36 @@ "node": ">=8" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "node_modules/array.prototype.filter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", + "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", + "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3442,30 +3543,31 @@ } }, "node_modules/array.prototype.tosorted": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", - "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -3501,8 +3603,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/atomic-sleep": { "version": "1.0.0", @@ -3513,9 +3614,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.16", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", - "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", + "version": "10.4.17", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", + "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", "dev": true, "funding": [ { @@ -3532,9 +3633,9 @@ } ], "dependencies": { - "browserslist": "^4.21.10", - "caniuse-lite": "^1.0.30001538", - "fraction.js": "^4.3.6", + "browserslist": "^4.22.2", + "caniuse-lite": "^1.0.30001578", + "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", "postcss-value-parser": "^4.2.0" @@ -3550,9 +3651,9 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", + "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", "engines": { "node": ">= 0.4" }, @@ -3569,6 +3670,16 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", @@ -3654,6 +3765,11 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" }, + "node_modules/boring-avatars": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/boring-avatars/-/boring-avatars-1.7.0.tgz", + "integrity": "sha512-ZNHd8J7C/V0IjQMGQowLJ5rScEFU23WxePigH6rqKcT2Esf0qhYvYxw8s9i3srmlfCnCV00ddBjaoGey1eNOfA==" + }, "node_modules/borsh": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", @@ -3665,13 +3781,12 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -3691,9 +3806,9 @@ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -3710,8 +3825,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -3758,7 +3873,6 @@ "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", "hasInstallScript": true, - "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" }, @@ -3778,13 +3892,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3817,9 +3936,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001565", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz", - "integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==", + "version": "1.0.30001588", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001588.tgz", + "integrity": "sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==", "funding": [ { "type": "opencollective", @@ -3851,15 +3970,9 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -3872,6 +3985,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -3888,9 +4004,9 @@ } }, "node_modules/citty": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.5.tgz", - "integrity": "sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", "dependencies": { "consola": "^3.2.3" } @@ -3906,16 +4022,16 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, "node_modules/clipboardy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", - "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-4.0.0.tgz", + "integrity": "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==", "dependencies": { - "arch": "^2.2.0", - "execa": "^5.1.1", - "is-wsl": "^2.2.0" + "execa": "^8.0.1", + "is-wsl": "^3.1.0", + "is64bit": "^2.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3932,9 +4048,9 @@ } }, "node_modules/clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", "engines": { "node": ">=6" } @@ -3967,7 +4083,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -4051,10 +4166,15 @@ "node": ">= 8" } }, + "node_modules/crossws": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.1.1.tgz", + "integrity": "sha512-c9c/o7bS3OjsdpSkvexpka0JNlesBF2JU9B2V1yNsYGwRbAafxhJQ7VI9b48D5bpONz/oxbPGMzBojy9sXoQIQ==" + }, "node_modules/css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "engines": { "node": ">= 6" }, @@ -4074,9 +4194,18 @@ } }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -4136,16 +4265,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -4166,9 +4298,9 @@ } }, "node_modules/defu": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.3.tgz", - "integrity": "sha512-Vy2wmG3NTkmHNg/kzpuvHhkqeIx3ODWqasgCRbKtbXEN0G+HpEEv9BtJLp7ZG1CZloFaC41Ah3ZFbq7aqCqMeQ==" + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" }, "node_modules/delay": { "version": "5.0.0", @@ -4185,7 +4317,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -4273,6 +4404,18 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.4", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.4.tgz", + "integrity": "sha512-XvPXc8XAQThSjAbY6cQ/9PcBXmFoWuw1sQ3b8HqUCR6ziGXjkTi//kB9SWa2UwqlgdAIuRqAa/9hVljzPehbYg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/duplexify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", @@ -4284,10 +4427,16 @@ "stream-shift": "^1.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/electron-to-chromium": { - "version": "1.4.601", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.601.tgz", - "integrity": "sha512-SpwUMDWe9tQu8JX5QCO1+p/hChAi9AE9UpoC3rcHVc+gdCGlbT3SGb5I1klgb952HRIyvt9wZhSz9bNBYz9swA==", + "version": "1.4.675", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.675.tgz", + "integrity": "sha512-+1u3F/XPNIdUwv8i1lDxHAxCvNNU0QIqgb1Ycn+Jnng8ITzWSvUqixRSM7NOazJuwhf65IV17f/VbKj8DmL26A==", "dev": true }, "node_modules/elliptic": { @@ -4342,50 +4491,52 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", + "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.2", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", + "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.8", "string.prototype.trimend": "^1.0.7", "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", + "typed-array-buffer": "^1.0.1", "typed-array-byte-length": "^1.0.0", "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4394,26 +4545,55 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-iterator-helpers": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", - "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", + "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", "dev": true, "dependencies": { "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.1", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", + "es-abstract": "^1.22.4", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.2", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", + "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", + "internal-slot": "^1.0.7", "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.0.1" + "safe-array-concat": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-set-tostringtag": { @@ -4456,6 +4636,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, "node_modules/es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -4469,10 +4673,19 @@ "es6-promise": "^4.0.3" } }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -4640,9 +4853,9 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", - "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "dependencies": { "array-includes": "^3.1.7", @@ -4661,7 +4874,7 @@ "object.groupby": "^1.0.1", "object.values": "^1.1.7", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -4670,6 +4883,16 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -4691,6 +4914,18 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4730,6 +4965,28 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-react": { "version": "7.33.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", @@ -4772,6 +5029,16 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -4784,6 +5051,18 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -4839,26 +5118,29 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "estraverse": "^4.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" } }, "node_modules/eslint-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -4876,7 +5158,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, "engines": { "node": ">=10" } @@ -4892,6 +5173,44 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -5015,31 +5334,31 @@ } }, "node_modules/ethereum-cryptography": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", - "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", + "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", "dependencies": { - "@noble/curves": "1.1.0", - "@noble/hashes": "1.3.1", - "@scure/bip32": "1.3.1", - "@scure/bip39": "1.2.1" + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@scure/bip32": "1.3.3", + "@scure/bip39": "1.2.2" } }, "node_modules/ethereum-cryptography/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", "dependencies": { - "@noble/hashes": "1.3.1" + "@noble/hashes": "1.3.3" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", "engines": { "node": ">= 16" }, @@ -5048,13 +5367,25 @@ } }, "node_modules/ethereum-cryptography/node_modules/@scure/bip32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", - "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", + "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", "dependencies": { - "@noble/curves": "~1.1.0", - "@noble/hashes": "~1.3.1", - "@scure/base": "~1.1.0" + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@scure/bip39": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", + "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", + "dependencies": { + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -5121,27 +5452,40 @@ } }, "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=16.17" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, "node_modules/eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", @@ -5213,9 +5557,9 @@ "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==" }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { "reusify": "^1.0.4" } @@ -5256,6 +5600,18 @@ "node": ">=0.10.0" } }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -5276,6 +5632,25 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -5284,11 +5659,26 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -5380,15 +5770,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5402,29 +5796,30 @@ } }, "node_modules/get-port-please": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.1.1.tgz", - "integrity": "sha512-3UBAyM3u4ZBVYDsxOQfJDxEa6XTbpBDrOjp4mf7ExFRt5BKs/QywQQiJsh2B+hxcZLSapWqCRvElUe8DnKcFHA==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.1.2.tgz", + "integrity": "sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==" }, "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -5482,6 +5877,28 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -5532,9 +5949,9 @@ } }, "node_modules/goober": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.13.tgz", - "integrity": "sha512-jFj3BQeleOoy7t93E9rZ2de+ScC4lQICLwiAQmKMg9F6roKGaLSHoCDYKkWlSafg138jejvq/mTdvmnwDQgqoQ==", + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz", + "integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==", "peerDependencies": { "csstype": "^3.0.10" } @@ -5558,22 +5975,22 @@ "node_modules/grapheme-splitter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" }, "node_modules/h3": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/h3/-/h3-1.9.0.tgz", - "integrity": "sha512-+F3ZqrNV/CFXXfZ2lXBINHi+rM4Xw3CDC5z2CDK3NMPocjonKipGLLDSkrqY9DOrioZNPTIdDMWfQKm//3X2DA==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.10.2.tgz", + "integrity": "sha512-r1iNNcFGL4G9pL3lgYxwX0O2ZmqdKqhILAJsnlw5icn5I1QHnADM4TgVdYRtHUqy+NntVpHIEFwnw/XCbebICg==", "dependencies": { "cookie-es": "^1.0.0", - "defu": "^6.1.3", + "defu": "^6.1.4", "destr": "^2.0.2", "iron-webcrypto": "^1.0.0", + "ohash": "^1.1.3", "radix3": "^1.1.0", "ufo": "^1.3.2", "uncrypto": "^0.1.3", - "unenv": "^1.7.4" + "unenv": "^1.9.0" } }, "node_modules/has-bigints": { @@ -5594,20 +6011,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -5627,11 +6044,11 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -5650,9 +6067,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", "dependencies": { "function-bind": "^1.1.2" }, @@ -5685,11 +6102,11 @@ } }, "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "engines": { - "node": ">=10.17.0" + "node": ">=16.17.0" } }, "node_modules/humanize-ms": { @@ -5725,9 +6142,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "engines": { "node": ">= 4" } @@ -5773,12 +6190,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", + "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" }, @@ -5841,14 +6258,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5947,14 +6366,14 @@ } }, "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "bin": { "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6013,6 +6432,23 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -6023,9 +6459,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -6095,11 +6531,11 @@ } }, "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6136,11 +6572,11 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -6189,14 +6625,31 @@ } }, "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dependencies": { - "is-docker": "^2.0.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is64bit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is64bit/-/is64bit-2.0.0.tgz", + "integrity": "sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==", + "dependencies": { + "system-architecture": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isarray": { @@ -6210,6 +6663,15 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/isomorphic-unfetch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", + "integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==", + "dependencies": { + "node-fetch": "^2.6.1", + "unfetch": "^4.2.0" + } + }, "node_modules/isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", @@ -6245,6 +6707,24 @@ "set-function-name": "^2.0.1" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jayson": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz", @@ -6280,26 +6760,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, - "node_modules/jayson/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/jiti": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", @@ -6391,9 +6851,9 @@ } }, "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==" }, "node_modules/jsonparse": { "version": "1.3.1", @@ -6508,26 +6968,27 @@ "dev": true }, "node_modules/listhen": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/listhen/-/listhen-1.5.5.tgz", - "integrity": "sha512-LXe8Xlyh3gnxdv4tSjTjscD1vpr/2PRpzq8YIaMJgyKzRG8wdISlWVWnGThJfHnlJ6hmLt2wq1yeeix0TEbuoA==", - "dependencies": { - "@parcel/watcher": "^2.3.0", - "@parcel/watcher-wasm": "2.3.0", - "citty": "^0.1.4", - "clipboardy": "^3.0.0", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/listhen/-/listhen-1.6.0.tgz", + "integrity": "sha512-z0RcEXVX5oTpY1bO02SKoTU/kmZSrFSngNNzHRM6KICR17PTq7ANush6AE6ztGJwJD4RLpBrVHd9GnV51J7s3w==", + "dependencies": { + "@parcel/watcher": "^2.4.0", + "@parcel/watcher-wasm": "2.4.0", + "citty": "^0.1.5", + "clipboardy": "^4.0.0", "consola": "^3.2.3", - "defu": "^6.1.2", - "get-port-please": "^3.1.1", - "h3": "^1.8.1", + "crossws": "^0.1.0", + "defu": "^6.1.4", + "get-port-please": "^3.1.2", + "h3": "^1.10.1", "http-shutdown": "^1.2.2", - "jiti": "^1.20.0", - "mlly": "^1.4.2", + "jiti": "^1.21.0", + "mlly": "^1.5.0", "node-forge": "^1.3.1", - "pathe": "^1.1.1", - "std-env": "^3.4.3", - "ufo": "^1.3.0", - "untun": "^0.1.2", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "ufo": "^1.3.2", + "untun": "^0.1.3", "uqr": "^0.1.2" }, "bin": { @@ -6563,6 +7024,17 @@ "@types/trusted-types": "^2.0.2" } }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", @@ -6654,7 +7126,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -6663,7 +7134,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -6672,11 +7142,14 @@ } }, "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimalistic-assert": { @@ -6690,15 +7163,18 @@ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -6710,17 +7186,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mlly": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", - "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.5.0.tgz", + "integrity": "sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==", "dependencies": { - "acorn": "^8.10.0", - "pathe": "^1.1.1", + "acorn": "^8.11.3", + "pathe": "^1.1.2", "pkg-types": "^1.0.3", - "ufo": "^1.3.0" + "ufo": "^1.3.2" } }, + "node_modules/modern-ahocorasick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modern-ahocorasick/-/modern-ahocorasick-1.0.1.tgz", + "integrity": "sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA==" + }, "node_modules/motion": { "version": "10.16.2", "resolved": "https://registry.npmjs.org/motion/-/motion-10.16.2.tgz", @@ -6789,8 +7279,7 @@ "node_modules/natural-compare-lite": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" }, "node_modules/next": { "version": "14.0.3", @@ -6838,9 +7327,9 @@ } }, "node_modules/next-auth": { - "version": "4.20.1", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.20.1.tgz", - "integrity": "sha512-ZcTUN4qzzZ/zJYgOW0hMXccpheWtAol8QOMdMts+LYRcsPGsqf2hEityyaKyECQVw1cWInb9dF3wYwI5GZdEmQ==", + "version": "4.24.6", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.6.tgz", + "integrity": "sha512-djQt3ZEaWEIxcsuh3HTW2uuzLfXMRjHH+ugAsichlQSbH4iA5MRcgMA2HvTNvsDTDLh44tyU72+/gWsxgTbAKg==", "dependencies": { "@babel/runtime": "^7.20.13", "@panva/hkdf": "^1.0.2", @@ -6853,7 +7342,7 @@ "uuid": "^8.3.2" }, "peerDependencies": { - "next": "^12.2.5 || ^13", + "next": "^12.2.5 || ^13 || ^14", "nodemailer": "^6.6.5", "react": "^17.0.2 || ^18", "react-dom": "^17.0.2 || ^18" @@ -6864,6 +7353,21 @@ } } }, + "node_modules/next-themes": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", + "integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==", + "peerDependencies": { + "next": "*", + "react": "*", + "react-dom": "*" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -6916,9 +7420,9 @@ } }, "node_modules/node-fetch-native": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.4.1.tgz", - "integrity": "sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w==" + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.2.tgz", + "integrity": "sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==" }, "node_modules/node-forge": { "version": "1.3.1", @@ -6929,9 +7433,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.1.tgz", - "integrity": "sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -6962,14 +7466,28 @@ } }, "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", "dependencies": { - "path-key": "^3.0.0" + "path-key": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/oauth": { @@ -6987,10 +7505,9 @@ } }, "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", "engines": { "node": ">= 6" } @@ -7062,15 +7579,16 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", + "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "array.prototype.filter": "^1.0.3", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0" } }, "node_modules/object.hasown": { @@ -7113,6 +7631,11 @@ "ufo": "^1.3.0" } }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==" + }, "node_modules/oidc-token-hash": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", @@ -7135,25 +7658,25 @@ } }, "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/openid-client": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.6.1.tgz", - "integrity": "sha512-PtrWsY+dXg6y8mtMPyL/namZSYVz8pjXz3yJiBNZsEdCnu9miHLB4ELVC85WvneMKo2Rg62Ay7NkuCpM0bgiLQ==", + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.6.4.tgz", + "integrity": "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA==", "dependencies": { - "jose": "^4.15.1", + "jose": "^4.15.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" @@ -7162,14 +7685,6 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/openid-client/node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "engines": { - "node": ">= 6" - } - }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -7192,6 +7707,31 @@ "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz", "integrity": "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==" }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -7243,6 +7783,31 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -7252,9 +7817,9 @@ } }, "node_modules/pathe": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz", - "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" }, "node_modules/picocolors": { "version": "1.0.0", @@ -7344,9 +7909,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "dev": true, "funding": [ { @@ -7443,12 +8008,15 @@ } }, "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "dev": true, "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/postcss-nested": { @@ -7471,9 +8039,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -7490,9 +8058,9 @@ "dev": true }, "node_modules/preact": { - "version": "10.19.2", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.2.tgz", - "integrity": "sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg==", + "version": "10.19.5", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.5.tgz", + "integrity": "sha512-OPELkDmSVbKjbFqF9tgvOowiiQ9TmsJljIzXRyNE8nGiis94pwv1siF78rQkAP1Q1738Ce6pellRg/Ns/CtHqQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -7544,6 +8112,11 @@ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.1.tgz", "integrity": "sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -7554,9 +8127,9 @@ } }, "node_modules/qrcode": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.0.tgz", - "integrity": "sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", + "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", "dependencies": { "dijkstrajs": "^1.0.1", "encode-utf8": "^1.0.3", @@ -7683,11 +8256,11 @@ "dev": true }, "node_modules/react-remove-scroll": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.4.tgz", - "integrity": "sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==", + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz", + "integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==", "dependencies": { - "react-remove-scroll-bar": "^2.3.3", + "react-remove-scroll-bar": "^2.3.4", "react-style-singleton": "^2.2.1", "tslib": "^2.1.0", "use-callback-ref": "^1.3.0", @@ -7707,9 +8280,9 @@ } }, "node_modules/react-remove-scroll-bar": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", - "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.5.tgz", + "integrity": "sha512-3cqjOqg6s0XbOjWvmasmqHch+RLxIEk2r/70rzGXuz3iIGQsQheEQyqYCBb5EECoD01Vo2SIbDqW4paLeLTASw==", "dependencies": { "react-style-singleton": "^2.2.1", "tslib": "^2.0.0" @@ -7810,15 +8383,16 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", + "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0", + "get-intrinsic": "^1.2.3", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" }, @@ -7830,19 +8404,20 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -7855,7 +8430,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, "engines": { "node": ">=8" }, @@ -7936,9 +8510,9 @@ } }, "node_modules/rpc-websockets": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.8.0.tgz", - "integrity": "sha512-AStkq6KDvSAmA4WiwlK1pDvj/33BWmExTATUokC0v+NhWekXSTNzXS5OGXeYwq501/pj6lBZMofg/h4dx4/tCg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.9.0.tgz", + "integrity": "sha512-DwKewQz1IUA5wfLvgM8wDpPRcr+nWSxuFxx5CbrI2z/MyyZ4nXLM86TvIA+cI1ZAdqC8JIBR1mZR55dzaLU+Hw==", "dependencies": { "@babel/runtime": "^7.17.2", "eventemitter3": "^4.0.7", @@ -7954,6 +8528,26 @@ "utf-8-validate": "^5.0.2" } }, + "node_modules/rpc-websockets/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7993,13 +8587,13 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -8030,15 +8624,18 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8065,9 +8662,9 @@ "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -8084,14 +8681,16 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -8148,22 +8747,32 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/siwe": { "version": "1.1.6", @@ -8224,9 +8833,9 @@ "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" }, "node_modules/std-env": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.6.0.tgz", - "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==" + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" }, "node_modules/stream-browserify": { "version": "3.0.0", @@ -8238,9 +8847,9 @@ } }, "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" }, "node_modules/streamsearch": { "version": "1.1.0", @@ -8279,6 +8888,27 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -8360,6 +8990,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -8370,11 +9013,14 @@ } }, "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-json-comments": { @@ -8389,6 +9035,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sturdy-websocket": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/sturdy-websocket/-/sturdy-websocket-0.2.1.tgz", + "integrity": "sha512-NnzSOEKyv4I83qbuKw9ROtJrrT6Z/Xt7I0HiP/e6H6GnpeTDvzwGIGeJ8slai+VwODSHQDooW2CAilJwT9SpRg==" + }, "node_modules/styled-jsx": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", @@ -8412,14 +9063,14 @@ } }, "node_modules/sucrase": { - "version": "3.34.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", - "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", - "glob": "7.1.6", + "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", @@ -8430,24 +9081,26 @@ "sucrase-node": "bin/sucrase-node" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -8481,15 +9134,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/system-architecture": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/system-architecture/-/system-architecture-0.1.0.tgz", + "integrity": "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" }, "node_modules/tailwindcss": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz", - "integrity": "sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -8523,6 +9187,15 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss/node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -8599,12 +9272,12 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -8617,9 +9290,9 @@ "dev": true }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", @@ -8637,7 +9310,6 @@ "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, "dependencies": { "tslib": "^1.8.1" }, @@ -8651,8 +9323,12 @@ "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, "node_modules/type-check": { "version": "0.4.0", @@ -8679,14 +9355,14 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz", + "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -8711,16 +9387,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.1.tgz", + "integrity": "sha512-tcqKMrTRXjqvHN9S3553NPCaGL0VPgFI92lXszmrE8DMhiDPLBYLlvo8Uu4WZAAX/aGqp/T1sbA4ph8EWjDF9Q==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.7", "for-each": "^0.3.3", + "gopd": "^1.0.1", "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -8752,9 +9429,9 @@ } }, "node_modules/typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -8764,10 +9441,32 @@ "node": ">=14.17" } }, + "node_modules/ua-parser-js": { + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", + "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "engines": { + "node": "*" + } + }, "node_modules/ufo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", - "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", + "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==" }, "node_modules/uint8arrays": { "version": "3.1.1", @@ -8803,17 +9502,22 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unenv": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-1.8.0.tgz", - "integrity": "sha512-uIGbdCWZfhRRmyKj1UioCepQ0jpq638j/Cf0xFTn4zD1nGJ2lSdzYHLzfdXN791oo/0juUiSWW1fBklXMTsuqg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-1.9.0.tgz", + "integrity": "sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==", "dependencies": { "consola": "^3.2.3", "defu": "^6.1.3", "mime": "^3.0.0", - "node-fetch-native": "^1.4.1", + "node-fetch-native": "^1.6.1", "pathe": "^1.1.1" } }, + "node_modules/unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" + }, "node_modules/unstorage": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.10.1.tgz", @@ -8885,19 +9589,19 @@ } }, "node_modules/unstorage/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "engines": { "node": "14 || >=16.14" } }, "node_modules/untun": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/untun/-/untun-0.1.2.tgz", - "integrity": "sha512-wLAMWvxfqyTiBODA1lg3IXHQtjggYLeTK7RnSfqtOXixWJ3bAa2kK/HHmOOg19upteqO3muLvN6O/icbyQY33Q==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/untun/-/untun-0.1.3.tgz", + "integrity": "sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==", "dependencies": { - "citty": "^0.1.3", + "citty": "^0.1.5", "consola": "^3.2.3", "pathe": "^1.1.1" }, @@ -8950,9 +9654,9 @@ } }, "node_modules/use-callback-ref": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", - "integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.1.tgz", + "integrity": "sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==", "dependencies": { "tslib": "^2.0.0" }, @@ -9003,7 +9707,6 @@ "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", "hasInstallScript": true, - "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" }, @@ -9067,9 +9770,9 @@ } }, "node_modules/viem": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/viem/-/viem-1.19.11.tgz", - "integrity": "sha512-dbsXEWDBZkByuzJXAs/e01j7dpUJ5ICF5WcyntFwf8Y97n5vnC/91lAleSa6DA5V4WJvYZbhDpYeTctsMAQnhA==", + "version": "1.21.4", + "resolved": "https://registry.npmjs.org/viem/-/viem-1.21.4.tgz", + "integrity": "sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ==", "funding": [ { "type": "github", @@ -9095,10 +9798,30 @@ } } }, + "node_modules/viem/node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/wagmi": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/wagmi/-/wagmi-1.4.7.tgz", - "integrity": "sha512-/k8gA9S6RnwU6Qroxs630jAFvRIx+DSKpCP1owgAEGWc7D2bAJHljwRSCRTGENz48HyJ4V3R7KYV1yImxPvM3A==", + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/wagmi/-/wagmi-1.4.13.tgz", + "integrity": "sha512-AScVYFjqNt1wMgL99Bob7MLdhoTZ3XKiOZL5HVBdy4W1sh7QodA3gQ8IsmTuUrQ7oQaTxjiXEhwg7sWNrPBvJA==", "funding": [ { "type": "gitcoin", @@ -9113,7 +9836,7 @@ "@tanstack/query-sync-storage-persister": "^4.27.1", "@tanstack/react-query": "^4.28.0", "@tanstack/react-query-persist-client": "^4.28.0", - "@wagmi/core": "1.4.7", + "@wagmi/core": "1.4.13", "abitype": "0.8.7", "use-sync-external-store": "^1.2.0" }, @@ -9155,16 +9878,16 @@ } }, "node_modules/web3": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/web3/-/web3-4.3.0.tgz", - "integrity": "sha512-YiLCsb5wmgJlSxRLzt7Z7H+CmlVVIKD8VaUQaZ+xKVG3Q7CpsO5Z6jmeKnlr6M9c6fDDsDnRM6G8g+nchZehbA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/web3/-/web3-4.5.0.tgz", + "integrity": "sha512-qWvmuFwmu1b4IVZz1/vahEP1VrRlnXLJJO6s88oRcOgOf21Q26rIyxqIDtKgKe7a4X29TqBocC1eP4CtZulAGA==", "dependencies": { "web3-core": "^4.3.2", "web3-errors": "^1.1.4", - "web3-eth": "^4.3.1", - "web3-eth-abi": "^4.1.4", - "web3-eth-accounts": "^4.1.0", - "web3-eth-contract": "^4.1.4", + "web3-eth": "^4.4.0", + "web3-eth-abi": "^4.2.0", + "web3-eth-accounts": "^4.1.1", + "web3-eth-contract": "^4.2.0", "web3-eth-ens": "^4.0.8", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", @@ -9172,9 +9895,9 @@ "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.1.4", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.0", - "web3-validator": "^2.0.3" + "web3-types": "^1.4.0", + "web3-utils": "^4.2.0", + "web3-validator": "^2.0.4" }, "engines": { "node": ">=14.0.0", @@ -9203,21 +9926,6 @@ "web3-providers-ipc": "^4.0.7" } }, - "node_modules/web3-core/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/web3-errors": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.1.4.tgz", @@ -9231,21 +9939,21 @@ } }, "node_modules/web3-eth": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.3.1.tgz", - "integrity": "sha512-zJir3GOXooHQT85JB8SrufE+Voo5TtXdjhf1D8IGXmxM8MrhI8AT+Pgt4siBTupJcu5hF17iGmTP/Nj2XnaibQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.4.0.tgz", + "integrity": "sha512-HswKdzF44wUrciRAtEJaml9O7rDYDxElHmFs+27WcO3nel2zku+n0xs4e2ZAehfrCZ+05/y7TgnOZnaDU8Fb/A==", "dependencies": { "setimmediate": "^1.0.5", - "web3-core": "^4.3.0", - "web3-errors": "^1.1.3", - "web3-eth-abi": "^4.1.4", - "web3-eth-accounts": "^4.1.0", + "web3-core": "^4.3.2", + "web3-errors": "^1.1.4", + "web3-eth-abi": "^4.2.0", + "web3-eth-accounts": "^4.1.1", "web3-net": "^4.0.7", "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "web3-validator": "^2.0.3" + "web3-rpc-methods": "^1.1.4", + "web3-types": "^1.3.1", + "web3-utils": "^4.1.1", + "web3-validator": "^2.0.4" }, "engines": { "node": ">=14", @@ -9253,15 +9961,15 @@ } }, "node_modules/web3-eth-abi": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.1.4.tgz", - "integrity": "sha512-YLOBVVxxxLYKXjaiwZjEWYEnkMmmrm0nswZsvzSsINy/UgbWbzfoiZU+zn4YNWIEhORhx1p37iS3u/dP6VyC2w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.2.0.tgz", + "integrity": "sha512-x7dUCmk6th+5N63s5kUusoNtsDJKUUQgl9+jECvGTBOTiyHe/V6aOY0120FUjaAGaapOnR7BImQdhqHv6yT2YQ==", "dependencies": { "abitype": "0.7.1", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "web3-validator": "^2.0.3" + "web3-errors": "^1.1.4", + "web3-types": "^1.3.1", + "web3-utils": "^4.1.1", + "web3-validator": "^2.0.4" }, "engines": { "node": ">=14", @@ -9282,48 +9990,18 @@ } } }, - "node_modules/web3-eth-abi/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/web3-eth-accounts": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.1.0.tgz", - "integrity": "sha512-UFtAsOANsvihTQ6SSvOKguupmQkResyR9M9JNuOxYpKh7+3W+sTnbLXw2UbOSYIsKlc1mpqqW9bVr1SjqHDpUQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.1.1.tgz", + "integrity": "sha512-9JqhRi1YhO1hQOEmmBHgEGsME/B1FHMxpA/AK3vhpvQ8QeP6KbJW+cForTLfPpUbkmPxnRunG4PNNaETNlZfrA==", "dependencies": { "@ethereumjs/rlp": "^4.0.1", "crc-32": "^1.2.2", - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-accounts/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { "ethereum-cryptography": "^2.0.0", "web3-errors": "^1.1.4", "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" + "web3-utils": "^4.1.1", + "web3-validator": "^2.0.4" }, "engines": { "node": ">=14", @@ -9331,32 +10009,17 @@ } }, "node_modules/web3-eth-contract": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.1.4.tgz", - "integrity": "sha512-tJ4z6QLgtu8EQu2sXnLA7g427oxmngnbAUh+9kJKbP6Yep/oe+z79PqJv7H3MwqwUNW9T+/FeB2PnSQSyxz6ig==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.2.0.tgz", + "integrity": "sha512-K7bUypsomTs8/Oa0Lgvq5plsSB5afgKJ79NMuXxvC5jfV+AxNrQyKcr5Vd5yEGNqrdQuIPduGQa8DpuY+rMe1g==", "dependencies": { "web3-core": "^4.3.2", "web3-errors": "^1.1.4", - "web3-eth": "^4.3.1", - "web3-eth-abi": "^4.1.4", + "web3-eth": "^4.4.0", + "web3-eth-abi": "^4.2.0", "web3-types": "^1.3.1", - "web3-utils": "^4.1.0", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-contract/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" + "web3-utils": "^4.1.1", + "web3-validator": "^2.0.4" }, "engines": { "node": ">=14", @@ -9383,21 +10046,6 @@ "npm": ">=6.12.0" } }, - "node_modules/web3-eth-ens/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/web3-eth-iban": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-4.0.7.tgz", @@ -9413,21 +10061,6 @@ "npm": ">=6.12.0" } }, - "node_modules/web3-eth-iban/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/web3-eth-personal": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-4.0.8.tgz", @@ -9445,36 +10078,6 @@ "npm": ">=6.12.0" } }, - "node_modules/web3-eth-personal/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/web3-net": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-4.0.7.tgz", @@ -9490,21 +10093,6 @@ "npm": ">=6.12.0" } }, - "node_modules/web3-net/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/web3-providers-http": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-4.1.0.tgz", @@ -9528,21 +10116,6 @@ "node-fetch": "^2.6.12" } }, - "node_modules/web3-providers-http/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/web3-providers-ipc": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-4.0.7.tgz", @@ -9558,22 +10131,6 @@ "npm": ">=6.12.0" } }, - "node_modules/web3-providers-ipc/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "optional": true, - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/web3-providers-ws": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-4.0.7.tgz", @@ -9607,19 +10164,24 @@ "ws": "*" } }, - "node_modules/web3-providers-ws/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" - }, + "node_modules/web3-providers-ws/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/web3-rpc-methods": { @@ -9637,39 +10199,39 @@ } }, "node_modules/web3-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.3.1.tgz", - "integrity": "sha512-8fXi7h/t95VKRtgU4sxprLPZpsTh3jYDfSghshIDBgUD/OoGe5S+syP24SUzBZYllZ/L+hMr2gdp/0bGJa8pYQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.4.0.tgz", + "integrity": "sha512-QnGDNredYqtZ49YD1pIPhsQTJJTOnYPCOnvrUs4/3XzeQLuDM+bAJ8fZ6U2nGEV77h81z2Ins6RE/f40yltvww==", "engines": { "node": ">=14", "npm": ">=6.12.0" } }, - "node_modules/web3-validator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.3.tgz", - "integrity": "sha512-fJbAQh+9LSNWy+l5Ze6HABreml8fra98o5+vS073T35jUcLbRZ0IOjF/ZPJhJNbJDt+jP1vseZsc3z3uX9mxxQ==", + "node_modules/web3-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.0.tgz", + "integrity": "sha512-UE7tmqPnC6sD0kpHhZiO9Zu8q7hiBItCQhnmxoMxk8OI91qlBWw6L7w1VNZo7TMBWH1Qe4R5l8h2vaoQCizVyA==", "dependencies": { "ethereum-cryptography": "^2.0.0", - "util": "^0.12.5", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "zod": "^3.21.4" + "web3-errors": "^1.1.4", + "web3-types": "^1.4.0", + "web3-validator": "^2.0.4" }, "engines": { "node": ">=14", "npm": ">=6.12.0" } }, - "node_modules/web3/node_modules/web3-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.1.0.tgz", - "integrity": "sha512-+VJWR6FtCsgwuJr5tvSvQlSEG06586df8h2CxGc9tcNtIDyJKNkSDDWJkdNPvyDhhXFzQYFh8QOGymD1CIP6fw==", + "node_modules/web3-validator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.4.tgz", + "integrity": "sha512-qRxVePwdW+SByOmTpDZFWHIUAa7PswvxNszrOua6BoGqAhERo5oJZBN+EbWtK/+O+ApNxt5FR3nCPmiZldiOQA==", "dependencies": { "ethereum-cryptography": "^2.0.0", + "util": "^0.12.5", "web3-errors": "^1.1.4", "web3-types": "^1.3.1", - "web3-validator": "^2.0.3" + "zod": "^3.21.4" }, "engines": { "node": ">=14", @@ -9681,6 +10243,35 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, + "node_modules/websocket": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", + "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -9767,15 +10358,15 @@ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -9797,21 +10388,39 @@ "node": ">=8" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", "engines": { - "node": ">=10.0.0" + "node": ">=8.3.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -9835,6 +10444,14 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, + "node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", + "engines": { + "node": ">=0.10.32" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -9882,54 +10499,6 @@ "node": ">=6" } }, - "node_modules/yargs/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/zod": { "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", @@ -9939,9 +10508,9 @@ } }, "node_modules/zustand": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz", - "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.1.tgz", + "integrity": "sha512-XlauQmH64xXSC1qGYNv00ODaQ3B+tNPoy22jv2diYiP4eoDKr9LA+Bh5Bc3gplTrFdb6JVI+N4kc1DZ/tbtfPg==", "dependencies": { "use-sync-external-store": "1.2.0" }, @@ -9950,7 +10519,7 @@ }, "peerDependencies": { "@types/react": ">=16.8", - "immer": ">=9.0", + "immer": ">=9.0.6", "react": ">=16.8" }, "peerDependenciesMeta": { diff --git a/package.json b/package.json index 1459f5c0..a3188a26 100644 --- a/package.json +++ b/package.json @@ -10,20 +10,23 @@ "start": "next start", "lint": "next lint", "semantic-release": "semantic-release" + "lint": "next lint --config .eslintrc" }, "dependencies": { "@headlessui-float/react": "^0.13.0", "@headlessui/react": "^1.7.17", - "@rainbow-me/rainbowkit": "1.0.4", + "@rainbow-me/rainbowkit": "^1.3.0", "@rainbow-me/rainbowkit-siwe-next-auth": "0.1.8", "@typescript-eslint/eslint-plugin": "5.54.1", - "eslint-plugin-unused-imports": "2.0.0", - "eslint-config-next": "13.4.19", - "eslint": "8.7.0", + "alchemy-sdk": "^3.1.2", + "axios": "^1.6.7", + "boring-avatars": "1.7.0", "classcat": "^5.0.4", + "eslint-plugin-unused-imports": "2.0.0", "ethers": "^5.7.2", "next": "14.0.3", "next-auth": "^4.20.1", + "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", "react-hot-toast": "^2.4.1", @@ -42,10 +45,11 @@ "@types/node-fetch": "^2.6.9", "@types/react": "^18", "@types/react-dom": "^18", + "@typescript-eslint/parser": "^6.13.1", + "autoprefixer": "^10.0.1", + "dotenv": "^16.4.1", "eslint": "8.7.0", "eslint-config-next": "13.4.19", - "@typescript-eslint/eslint-plugin": "5.54.1", - "autoprefixer": "^10.0.1", "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5" diff --git a/pages/_app.tsx b/pages/_app.tsx index 8251dc38..0de8b71c 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -19,6 +19,14 @@ import { } from "@rainbow-me/rainbowkit"; import { RainbowKitSiweNextAuthProvider } from "@rainbow-me/rainbowkit-siwe-next-auth"; import { Toaster } from "react-hot-toast"; +import localFont from "next/font/local"; +import cc from "classcat"; +import { ThemeProvider } from "next-themes"; + +const onest = localFont({ + src: "../public/fonts/Onest-VariableFont_wght.woff2", + variable: "--font-onest", +}); function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) { return ( @@ -46,7 +54,11 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) { chains={chains} > - + +
+ +
+
diff --git a/pages/_document.tsx b/pages/_document.tsx index cec067eb..44dec0a2 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -4,7 +4,7 @@ export default function Document() { return ( - +
diff --git a/pages/index.tsx b/pages/index.tsx index c257890b..de56fd13 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,15 +1,15 @@ -import { HomeSection, Layout } from "@/components/04-templates"; +import { Layout, SwapSection } from "@/components/04-templates"; import cc from "classcat"; -export default function Index() { +export default function IndexPage() { return (
- +
); diff --git a/pages/offers.tsx b/pages/offers.tsx new file mode 100644 index 00000000..135732c7 --- /dev/null +++ b/pages/offers.tsx @@ -0,0 +1,16 @@ +import { Layout, OfferSection } from "@/components/04-templates"; +import cc from "classcat"; + +export default function Offers() { + return ( + +
+ +
+
+ ); +} diff --git a/pages/swap.tsx b/pages/swap.tsx deleted file mode 100644 index 2a1cd7bb..00000000 --- a/pages/swap.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { TheHeader } from "@/components/02-molecules"; -import { Layout, SwapSection } from "@/components/04-templates"; -import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import cc from "classcat"; - -export default function SwapPage() { - const { authenticatedUserAddress } = useAuthenticatedUser(); - - return ( - - {authenticatedUserAddress && ( -
- - -
- )} -
- ); -} diff --git a/public/chains/FujiIcon.png b/public/chains/FujiIcon.png new file mode 100644 index 00000000..76db7525 Binary files /dev/null and b/public/chains/FujiIcon.png differ diff --git a/public/chains/arbitrumSepoliaIcon.png b/public/chains/arbitrumSepoliaIcon.png new file mode 100644 index 00000000..65a349f0 Binary files /dev/null and b/public/chains/arbitrumSepoliaIcon.png differ diff --git a/public/chains/baseGoerliIcon.png b/public/chains/baseGoerliIcon.png new file mode 100644 index 00000000..562554f0 Binary files /dev/null and b/public/chains/baseGoerliIcon.png differ diff --git a/public/chains/bnbChainIcon.png b/public/chains/bnbChainIcon.png new file mode 100644 index 00000000..4035b003 Binary files /dev/null and b/public/chains/bnbChainIcon.png differ diff --git a/public/chains/optimismIcon.png b/public/chains/optimismIcon.png new file mode 100644 index 00000000..ed44203e Binary files /dev/null and b/public/chains/optimismIcon.png differ diff --git a/public/chains/polygonMumbai.png b/public/chains/polygonMumbai.png new file mode 100644 index 00000000..3078ff45 Binary files /dev/null and b/public/chains/polygonMumbai.png differ diff --git a/public/chains/sepoliaIcon.png b/public/chains/sepoliaIcon.png new file mode 100644 index 00000000..e6fbfc57 Binary files /dev/null and b/public/chains/sepoliaIcon.png differ diff --git a/public/favicon.ico b/public/favicon.ico index 742f347c..49789438 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/fonts/Onest-VariableFont_wght.woff2 b/public/fonts/Onest-VariableFont_wght.woff2 new file mode 100644 index 00000000..277374c4 Binary files /dev/null and b/public/fonts/Onest-VariableFont_wght.woff2 differ diff --git a/styles/global.css b/styles/global.css index 69c92b45..7fcd2897 100644 --- a/styles/global.css +++ b/styles/global.css @@ -1,11 +1,216 @@ html, body { - width: 100vw; overflow-x: hidden; } + input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-results-button, input[type="search"]::-webkit-search-results-decoration { display: none; } +/* Change Autocomplete styles in Chrome*/ +input:-webkit-autofill, +input:-webkit-autofill:hover, +input:-webkit-autofill:focus { + font-size: inherit; + -webkit-text-fill-color: none; + -webkit-box-shadow: 0 0 0px 1000px transparent inset; + transition: background-color 5000s ease-in-out 0s; +} + +/* Chrome, Safari, Edge, Opera */ +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.no-transition * { + transition: none !important; +} + +/* Firefox */ +input[type="number"] { + -moz-appearance: textfield; +} + +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer utilities { + /* Hide scrollbar for Chrome, Safari and Opera */ + .no-scrollbar::-webkit-scrollbar { + display: none; + } + + /* Hide scrollbar for IE, Edge and Firefox */ + .no-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } + + .shadow-add-manually-card { + box-shadow: 0px 0px 12px 1px #00000066; + } + .shadow-add-manually-button { + box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.3); + } + + .shadow-token { + box-shadow: 0px 1px 4px 1px #00000026 inset; + } + + .shadow-tag { + box-shadow: 0px 0px 6px 1px #0000004d; + } + + .shadow-three-dots { + box-shadow: 0px 0px 12px 1px #00000066; + } + + .shadow-swap-station { + box-shadow: 0px 0px 6px 1px #00000066; + } + + .shadow-button-swap-station-offer { + box-shadow: 0px 0px 6px 1px #0000004d; + } + + .shadow-swap-connection { + box-shadow: 0px 0px 6px 1px #0000004d; + } + .shadow-swap-connection-light { + box-shadow: 0px 0px 6px 0px #00000014; + } + + .shadow-swap-station-light { + box-shadow: 0px 0px 6px 0px #00000014; + } + + .shadow-swap-connection-dropwdown { + box-shadow: 0px 0px 12px 1px #00000066; + } + + .title-h1 { + } + + .title-h2-medium { + @apply font-onest font-medium text-[32px] leading-[40.8px] text-[#333333]; + } + .title-h2-medium-dark { + @apply font-onest font-medium text-[32px] leading-[40.8px] text-[#F6F6F6]; + } + + .title-h3-normal { + @apply font-onest font-normal text-[20px] leading-[25.5px] text-[#333333]; + } + + .title-h3-normal-dark { + @apply font-onest font-normal text-[20px] leading-[25.5px] text-[#F6F6F6]; + } + + .p-semibold-dark { + @apply font-onest font-semibold text-[12px] leading-[16px] text-[#F6F6F6]; + } + + .p-medium-2 { + @apply font-onest font-medium text-[16px] leading-[20px] text-[#212322]; + } + .p-medium-2-dark { + @apply font-onest font-medium text-[16px] leading-[20px] text-[#F6F6F6]; + } + + .p-medium-2-small { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#212322]; + } + .p-medium-2-small-dark { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#F6F6F6]; + } + .p-medium-2-variant-yellow { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#AABE13]; + } + .p-medium-2-variant-grey { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#707572]; + } + + .p-normal-2 { + @apply font-onest font-normal text-[16px] leading-[20px] text-[#707572]; + } + .p-normal-2-dark { + @apply font-onest font-normal text-[16px] leading-[20px] text-[#F6F6F6]; + } + .p-normal-2-light { + @apply font-onest font-normal text-[16px] leading-[20px] text-[#212322]; + } + + .p-medium-bold-2 { + @apply font-onest font-medium text-[16px] leading-[20px] text-[#707572]; + } + .p-medium-bold-2-dark { + @apply font-onest font-medium text-[16px] leading-[20px] text-[#F6F6F6]; + } + .p-medium-bold-2-dark-variant-black { + @apply font-onest font-medium text-[16px] leading-[20px] text-black; + } + + .p-medium-bold-variant-black { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#181A19]; + } + .p-medium-bold { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#707572]; + } + .p-medium-bold-dark { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#F6F6F6]; + } + + .p-medium { + @apply font-onest font-medium text-[14px] leading-[20px] text-[#707572]; + } + .p-medium-dark { + @apply font-onest font-medium text-[14px] leading-[20px] text-[#F6F6F6]; + } + + .p-small-variant-black { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#181A19]; + } + .p-small { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#707572]; + } + .p-small-dark { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#F6F6F6]; + } + .p-small-dark-variant-grey { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#A3A9A5]; + } + .p-small-variant-black-2 { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#353836]; + } + .p-small-variant-black-3 { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#212322]; + } + .p-small-variant-light-2 { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#F6F6F1]; + } + + .card-token-normal { + @apply shadow-inner w-[90px] h-[90px] lg:w-[80px] lg:h-[80px] relative rounded-xl border border-[#E0E0E0] bg-[#E0E0E0] dark:bg-[#353836] dark:border-[#212322] flex flex-col shadow-token; + } + .card-token-small { + @apply shadow-inner mx-auto w-[44px] h-[44px] lg:w-[44px] lg:h-[44px] relative rounded-lg border-2 border-[#E0E0E0] bg-[#E0E0E0] dark:bg-[#353836] dark:border-[#212322] flex flex-col shadow-token; + } + .card-token-medium { + @apply shadow-inner w-[72px] h-[72px] lg:w-[72px] lg:h-[72px] relative rounded-xl border border-[#E0E0E0] bg-[#E0E0E0] dark:bg-[#353836] dark:border-[#212322] flex flex-col shadow-token; + } + .card-token-large { + @apply shadow-inner mx-auto w-[90px] h-[90px] lg:w-[80px] lg:h-[80px] relative rounded-xl border-2 border-[#E0E0E0] bg-[#E0E0E0] dark:bg-[#353836] dark:border-[#212322] flex flex-col shadow-token; + } + + .ens-avatar-small { + @apply w-6 h-6 rounded-md overflow-hidden; + } + .ens-avatar-medium { + @apply w-10 h-10 rounded-[10px] overflow-hidden; + } +} diff --git a/tailwind.config.ts b/tailwind.config.ts index ce518de3..cd6c8c88 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,10 +1,23 @@ import type { Config } from "tailwindcss"; const config: Config = { + darkMode: ["class"], content: [ + "./styles/*.{js,ts,jsx,tsx,mdx}", "./pages/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", ], + theme: { + extend: { + fontFamily: { + onest: ["var(--font-onest)"], + }, + boxShadow: { + sidebarLight: "0px 0px 6px 1px rgba(0, 0, 0, 0.30)", + sidebarDark: "0px 0px 12px 1px rgba(0, 0, 0, 0.40)" + }, + }, + }, plugins: [], }; export default config;