diff --git a/.env.example b/.env.example index 84b4040..1ee8fe3 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ -RPC_URL= PINATA_API_SECRET= PINATA_API_KEY= -PINATA_JWT= IPFS_URL= DUNE_API_KEY= +ALCHEMY_API_KEY= +ENSO_API_KEY= \ No newline at end of file diff --git a/components/SocialMediaLinks.tsx b/components/SocialMediaLinks.tsx index cc8700e..60e2ec2 100644 --- a/components/SocialMediaLinks.tsx +++ b/components/SocialMediaLinks.tsx @@ -1,28 +1,24 @@ import DiscordIcon from "@/components/svg/socialMedia/DiscordIcon"; import MediumIcon from "@/components/svg/socialMedia/MediumIcon"; import RedditIcon from "@/components/svg/socialMedia/RedditIcon"; -import TelegramIcon from "@/components/svg/socialMedia/TelegramIcon"; import TwitterIcon from "@/components/svg/socialMedia/TwitterIcon"; import YoutubeIcon from "@/components/svg/socialMedia/YoutubeIcon"; export default function SocialMediaLinks() { return <> - + - + - - - - + - + - + diff --git a/components/button/PseudoRadioButton.tsx b/components/button/PseudoRadioButton.tsx index e239e90..5f789e2 100644 --- a/components/button/PseudoRadioButton.tsx +++ b/components/button/PseudoRadioButton.tsx @@ -6,10 +6,10 @@ interface PseudoRadioButtonProps { extraClasses?: string; } -export default function PseudoRadioButton({ label, handleClick, isActive, activeClass, extraClasses, }: PseudoRadioButtonProps): JSX.Element { +export default function PseudoRadioButton({ label, handleClick, isActive, activeClass, extraClasses}: PseudoRadioButtonProps): JSX.Element { return ( ); -}; \ No newline at end of file +}; diff --git a/components/button/TertiaryActionButton.tsx b/components/button/TertiaryActionButton.tsx index 27b1731..92c67ce 100644 --- a/components/button/TertiaryActionButton.tsx +++ b/components/button/TertiaryActionButton.tsx @@ -1,16 +1,30 @@ +import RightArrowIcon from "@/components/svg/RightArrowIcon"; +import React, { useState } from "react"; import { ButtonProps } from "@/components/button/MainActionButton"; -export default function TertiaryActionButton({ label, handleClick, disabled = false, hidden = false }: ButtonProps): JSX.Element { +export default function TertiaryActionButton({ label, handleClick, hidden, disabled = false }: ButtonProps): JSX.Element { + const [arrowColor, setArrowColor] = useState("645F4B"); + const [arrowClass, setArrowClass] = useState("transform translate-x-0"); + + const animateArrow = () => { + setArrowColor("000000"); + setArrowClass("transform -translate-x-1/2"); + setTimeout(() => { + setArrowColor("645F4B"); + setArrowClass("transform translate-x-0"); + }, 500); + }; return ( ); -}; - +}; \ No newline at end of file diff --git a/components/common/TokenIcon.tsx b/components/common/TokenIcon.tsx index 4aa70ef..068529f 100644 --- a/components/common/TokenIcon.tsx +++ b/components/common/TokenIcon.tsx @@ -21,6 +21,6 @@ export default function TokenIcon({ return token icon } return ( - token icon + token icon ); } \ No newline at end of file diff --git a/components/input/InputTokenWithError.tsx b/components/input/InputTokenWithError.tsx index 109e216..6a0b526 100644 --- a/components/input/InputTokenWithError.tsx +++ b/components/input/InputTokenWithError.tsx @@ -62,7 +62,7 @@ export default function InputTokenWithError({

- {`${formatNumber(Number(selectedToken?.balance) / (10 ** (selectedToken?.decimals as number)))}`} + {`${formatNumber(Number(selectedToken?.balance) / (10 ** (selectedToken?.decimals as number)))}`}

} diff --git a/components/landing/Hero.tsx b/components/landing/Hero.tsx index 1dd9663..19d60ef 100644 --- a/components/landing/Hero.tsx +++ b/components/landing/Hero.tsx @@ -1,11 +1,15 @@ import StatusWithLabel from "@/components/common/StatusWithLabel"; -import { Networth, getTotalNetworth } from "@/lib/getNetworth"; +import { vaultsAtom } from "@/lib/atoms/vaults"; +import { Networth, getTotalNetworth, getVaultNetworthByChain } from "@/lib/getNetworth"; +import { SUPPORTED_NETWORKS } from "@/lib/utils/connectors"; import { NumberFormatter } from "@/lib/utils/formatBigNumber"; +import { useAtom } from "jotai"; import { useEffect, useState } from "react"; -import { useAccount } from "wagmi"; +import { Address, useAccount } from "wagmi"; export default function Hero(): JSX.Element { const { address: account } = useAccount(); + const [vaults] = useAtom(vaultsAtom) const [networth, setNetworth] = useState({ pop: 0, stake: 0, vault: 0, total: 0 }); const [tvl, setTvl] = useState("0"); const [loading, setLoading] = useState(true); @@ -19,13 +23,15 @@ export default function Hero(): JSX.Element { )) }, []) + useEffect(() => { - if (account && loading) - // fetch and set networth - getTotalNetworth({ account }).then(res => { - setNetworth(res.total); - setLoading(false); - }); + async function fetchNetworth() { + const vaultNetworth = SUPPORTED_NETWORKS.map(chain => getVaultNetworthByChain({ vaults, chainId: chain.id })).reduce((a, b) => a + b, 0) + const totalNetworth = await getTotalNetworth({ account: account as Address }) + setNetworth({ ...totalNetworth.total, vault: vaultNetworth, total: totalNetworth.total.total + vaultNetworth }); + setLoading(false); + } + if (account && loading && vaults.length > 0) fetchNetworth() }, [account]); @@ -43,7 +49,7 @@ export default function Hero(): JSX.Element { content={

$ {loading ? "..." : NumberFormatter.format(networth.stake)}

} /> $ {loading ? "..." : NumberFormatter.format(networth.pop)}

} /> diff --git a/components/landing/Products.tsx b/components/landing/Products.tsx index 644e9b4..2bd40a3 100644 --- a/components/landing/Products.tsx +++ b/components/landing/Products.tsx @@ -44,14 +44,14 @@ export default function Products(): JSX.Element { } customContent={} - description="Lock stake your POP LP to boost your rewards with call options on POP" + description="Lock stake your VCX LP to boost your rewards with call options on VCX" stats={[ { label: "TVL", content:

Coming soon

, }, ]} - route="" + route="boost" /> -
+
toggleMenu(false)}>
diff --git a/components/navbar/MobileMenu.tsx b/components/navbar/MobileMenu.tsx index 2c751f2..a643bcc 100644 --- a/components/navbar/MobileMenu.tsx +++ b/components/navbar/MobileMenu.tsx @@ -65,12 +65,7 @@ export default function MobileMenu(): JSX.Element { const closePopUp = () => { setShowPopUp(false); }; - - function handleCloseAll() { - toggleMenu(false); - toggleProductsMenu(false); - } - + return ( <>
diff --git a/components/navbar/NavbarLinks.tsx b/components/navbar/NavbarLinks.tsx index 457489f..216e222 100644 --- a/components/navbar/NavbarLinks.tsx +++ b/components/navbar/NavbarLinks.tsx @@ -3,13 +3,21 @@ import NavbarLink from "@/components/navbar/NavbarLink" const links: { label: string, url: string, onClick?: Function }[] = [ { - label: "Vaults", + label: "Smart Vaults", url: "/vaults", }, + { + label: "Boost Vaults", + url: "/boost", + }, { label: "Stats", url: "/stats" }, + { + label: "Pop to VCX Migration", + url: "/migration" + }, { label: "VaultCraft", url: "https://vaultcraft.io/", diff --git a/components/page/Footer.tsx b/components/page/Footer.tsx index d132183..1534eaf 100644 --- a/components/page/Footer.tsx +++ b/components/page/Footer.tsx @@ -29,7 +29,7 @@ const GeneralLinks = [ }, { label: "Gitbook", - href: "https://popcorn-dao.gitbook.io/popcorndao-gitbook/about-popcorn/welcome-to-popcorn", + href: "https://docs.vaultcraft.io/welcome-to-vaultcraft/introduction", }, { label: "Disclaimer", diff --git a/components/page/Page.tsx b/components/page/Page.tsx index dc547c8..7701db7 100644 --- a/components/page/Page.tsx +++ b/components/page/Page.tsx @@ -9,19 +9,24 @@ import Navbar from "@/components/navbar/NavBar"; import { useAtom } from "jotai"; import { yieldOptionsAtom } from "@/lib/atoms/sdk"; import { CachedProvider, YieldOptions } from "vaultcraft-sdk"; +import { SUPPORTED_NETWORKS } from "@/lib/utils/connectors"; +import { getVaultsByChain } from "@/lib/vault/getVault"; +import { vaultsAtom } from "@/lib/atoms/vaults"; +import { useAccount } from "wagmi"; async function setUpYieldOptions() { const ttl = 360_000; const provider = new CachedProvider(); - await provider.initialize("https://raw.githubusercontent.com/Popcorn-Limited/apy-data/main/apy-data.json"); + await provider.initialize("https://raw.githubusercontent.com/Popcorn-Limited/defi-db/main/apy-data.json"); - return new YieldOptions(provider, ttl); + return new YieldOptions({ provider, ttl }); } - export default function Page({ children }: { children: JSX.Element }): JSX.Element { const { pathname } = useRouter(); + const { address: account } = useAccount() const [yieldOptions, setYieldOptions] = useAtom(yieldOptionsAtom) + const [, setVaults] = useAtom(vaultsAtom) useEffect(() => { if (!yieldOptions) { @@ -29,10 +34,21 @@ export default function Page({ children }: { children: JSX.Element }): JSX.Eleme } }, []) + useEffect(() => { + async function getVaults() { + // get vaults + const fetchedVaults = (await Promise.all( + SUPPORTED_NETWORKS.map(async (chain) => getVaultsByChain({ chain, account, yieldOptions: yieldOptions as YieldOptions })) + )).flat(); + setVaults(fetchedVaults) + } + if (yieldOptions) getVaults() + }, [account, yieldOptions]) + return ( <> -
+
diff --git a/components/svg/SwitchIcon.tsx b/components/svg/SwitchIcon.tsx new file mode 100644 index 0000000..0d7b717 --- /dev/null +++ b/components/svg/SwitchIcon.tsx @@ -0,0 +1,12 @@ +import { IconProps } from "@/lib/types" + + +const SwitchIcon: React.FC = ({ className, color, size}) => { + return ( + + + + ) +} + +export default SwitchIcon; diff --git a/components/vault/ActionSteps.tsx b/components/vault/ActionSteps.tsx new file mode 100644 index 0000000..62b8b72 --- /dev/null +++ b/components/vault/ActionSteps.tsx @@ -0,0 +1,35 @@ +import { ActionStep } from "@/lib/vault/getActionSteps" +import { XMarkIcon } from "@heroicons/react/24/outline" + +function getStepColor(preFix: string, step: any): string { + if (step.loading || step.success) return `${preFix}-green-500` + if (step.error) return `${preFix}-red-500` + return `${preFix}-warmGray` +} + +interface ActionStepsProps { + steps: ActionStep[]; + stepCounter: number; +} + +export default function ActionSteps({ steps, stepCounter }: ActionStepsProps): JSX.Element { + return ( +
+ { + steps.map((step, i) => <> +
+ {step.loading && } + {!step.loading && step.error && } + {!step.loading && step.success && } + {!step.loading && !step.error && !step.success &&
} +
+ {step.step < steps.length &&

________

} + ) + } +
+ ) +} \ No newline at end of file diff --git a/components/vault/AssetWithName.tsx b/components/vault/AssetWithName.tsx index 1dc6484..b93c690 100644 --- a/components/vault/AssetWithName.tsx +++ b/components/vault/AssetWithName.tsx @@ -1,8 +1,6 @@ import NetworkSticker from "@/components/network/NetworkSticker"; import TokenIcon from "@/components/common/TokenIcon"; -import { ChainId } from "@/lib/utils/connectors"; -import { Vault } from "@/lib/vault/getVault"; -import { Token } from "@/lib/types"; +import { VaultData } from "@/lib/types"; const protocolNameToLlamaProtocol: { [key: string]: string } = { "Aave": "aave", @@ -17,26 +15,30 @@ const protocolNameToLlamaProtocol: { [key: string]: string } = { "Origin": "origin-defi", "Stargate": "stargate", "Yearn": "yearn-finance", + "Pirex": "pirex", + "Sommelier": "sommelier" } -export default function AssetWithName({ vault }: { vault: Vault }) { +export default function AssetWithName({ vault }: { vault: VaultData }) { const protocolName = vault.metadata.optionalMetadata?.protocol?.name const protocolIcon = protocolName ? protocolNameToLlamaProtocol[protocolName] : "popcorn" - return
-
- - + return ( +
+
+ + +
+

+ {vault.metadata.vaultName || vault.asset.name} +

+
+ +

{protocolName}

+
-

- {vault.metadata.vaultName || vault.asset.name} -

-
- -

{protocolName}

-
-
+ ) } \ No newline at end of file diff --git a/components/vault/SmartVault.tsx b/components/vault/SmartVault.tsx index a66423e..84ae8c0 100644 --- a/components/vault/SmartVault.tsx +++ b/components/vault/SmartVault.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { Address, useAccount, } from "wagmi"; +import { Address, useAccount, usePublicClient, } from "wagmi"; import { getAddress } from "viem"; import { useAtom } from "jotai"; import { yieldOptionsAtom } from "@/lib/atoms/sdk"; @@ -11,41 +11,40 @@ import Accordion from "@/components/common/Accordion"; import TokenIcon from "@/components/common/TokenIcon"; import Title from "@/components/common/Title"; import { Token, VaultData } from "@/lib/types"; +import calculateAPR from "@/lib/gauges/calculateGaugeAPR"; +import { MutateTokenBalanceProps } from "pages/vaults"; -function getBaseToken(vaultData: VaultData): Token[] { - const baseToken = [vaultData.vault, vaultData.asset] - if (!!vaultData.gauge) baseToken.push(vaultData.gauge) - return baseToken; +function getTokenOptions(vaultData: VaultData, zapAssets?: Token[]): Token[] { + const tokenOptions = [vaultData.vault, vaultData.asset] + if (!!vaultData.gauge) tokenOptions.push(vaultData.gauge) + if (zapAssets) tokenOptions.push(...zapAssets.filter(asset => getAddress(asset.address) !== getAddress(vaultData.asset.address))) + return tokenOptions; +} + +interface SmartVaultsProps { + vaultData: VaultData; + searchString: string; + mutateTokenBalance: (props: MutateTokenBalanceProps) => void; + zapAssets?: Token[]; + deployer?: Address; } export default function SmartVault({ vaultData, searchString, + mutateTokenBalance, + zapAssets, deployer, -}: { - vaultData: VaultData, - searchString: string, - deployer?: Address -}) { - const [yieldOptions] = useAtom(yieldOptionsAtom); +}: SmartVaultsProps) { const { address: account } = useAccount(); const vault = vaultData.vault; const asset = vaultData.asset; const gauge = vaultData.gauge; - const baseToken = getBaseToken(vaultData); - - const [apy, setApy] = useState(0); - - useEffect(() => { - if (!apy) { - // @ts-ignore - yieldOptions?.getApy(vaultData.chainId, vaultData.metadata.optionalMetadata.resolver, vaultData.asset.address).then(res => setApy(!!res ? res.total : 0)) - } - }, [apy]) + const tokenOptions = getTokenOptions(vaultData, zapAssets); // Is loading / error - if (!vaultData || baseToken.length === 0) return <> + if (!vaultData || tokenOptions.length === 0) return <> // Dont show if we filter by deployer if (!!deployer && getAddress(deployer) !== getAddress(vaultData?.metadata?.creator)) return <> // Vault is not in search term @@ -57,10 +56,15 @@ export default function SmartVault({ header={
-
+
+ +
+

{zapAssets && zapAssets?.length > 0 && "⚡ Zap available"}

+
+

Your Wallet

@@ -76,7 +80,7 @@ export default function SmartVault({

{account ? (!!gauge ? - formatAndRoundNumber(gauge?.balance || 0, vault.decimals) : + formatAndRoundNumber(gauge?.balance || 0, gauge.decimals) : formatAndRoundNumber(vault.balance, vault.decimals) ) : "-"} @@ -87,17 +91,26 @@ export default function SmartVault({

vAPY

- {apy ? `${NumberFormatter.format(apy)} %` : "0 %"} + {vaultData.apy ? `${NumberFormatter.format(vaultData.apy)} %` : "0 %"} + {!!vaultData.gaugeMinApy && !!vaultData.gaugeMaxApy && + + {`+ (${formatNumber(vaultData.gaugeMinApy)} % - ${formatNumber(vaultData.gaugeMaxApy)} %)`} + + }

TVL

- $ {NumberFormatter.format(vaultData.tvl)} + $ {vaultData.tvl < 1 ? "0" : NumberFormatter.format(vaultData.tvl)}
+
+

{zapAssets && zapAssets?.length > 0 && "⚡ Zap available"}

+
+
} > @@ -109,8 +122,9 @@ export default function SmartVault({ vault={vault} asset={asset} gauge={gauge} - tokenOptions={[vaultData.vault, vaultData.asset]} + tokenOptions={tokenOptions} chainId={vaultData.chainId} + mutateTokenBalance={mutateTokenBalance} />
@@ -131,9 +145,6 @@ export default function SmartVault({
- {/*
- -
*/}
diff --git a/components/vault/VaultInputs.tsx b/components/vault/VaultInputs.tsx index aefe5e2..5e639b5 100644 --- a/components/vault/VaultInputs.tsx +++ b/components/vault/VaultInputs.tsx @@ -1,184 +1,237 @@ -import { ArrowDownIcon } from "@heroicons/react/24/outline"; +import { ArrowDownIcon, Cog6ToothIcon } from "@heroicons/react/24/outline"; import InputTokenWithError from "@/components/input/InputTokenWithError"; import MainActionButton from "@/components/button/MainActionButton"; import { useEffect, useState } from "react"; import { Address, useAccount, useNetwork, usePublicClient, useSwitchNetwork, useWalletClient } from "wagmi"; import TabSelector from "@/components/common/TabSelector"; -import { Token } from "@/lib/types"; -import { handleAllowance } from "@/lib/approve"; -import { WalletClient } from "viem"; -import { vaultDeposit, vaultDepositAndStake, vaultRedeem, vaultUnstakeAndWithdraw } from "@/lib/vault/interactions"; -import { ADDRESS_ZERO } from "@/lib/constants"; - -const { VaultRouter: VAULT_ROUTER } = { VaultRouter: ADDRESS_ZERO as Address } +import { ActionType, Token } from "@/lib/types"; +import { validateInput } from "@/lib/utils/helpers"; +import Modal from "../modal/Modal"; +import InputNumber from "../input/InputNumber"; +import { MutateTokenBalanceProps } from "pages/vaults"; +import { safeRound } from "@/lib/utils/formatBigNumber"; +import { formatUnits, parseUnits } from "viem"; +import handleVaultInteraction from "@/lib/vault/handleVaultInteraction"; +import getActionSteps, { ActionStep } from "@/lib/vault/getActionSteps"; +import { useConnectModal } from "@rainbow-me/rainbowkit"; +import ActionSteps from "./ActionSteps"; interface VaultInputsProps { vault: Token; asset: Token; gauge?: Token; tokenOptions: Token[]; - chainId: number + chainId: number; + mutateTokenBalance: (props: MutateTokenBalanceProps) => void; } -export default function VaultInputs({ vault, asset, gauge, tokenOptions, chainId }: VaultInputsProps): JSX.Element { - const publicClient = usePublicClient(); +export default function VaultInputs({ vault, asset, gauge, tokenOptions, chainId, mutateTokenBalance }: VaultInputsProps): JSX.Element { + const publicClient = usePublicClient({ chainId }); const { data: walletClient } = useWalletClient() const { address: account } = useAccount(); const { chain } = useNetwork(); const { switchNetwork } = useSwitchNetwork(); + const { openConnectModal } = useConnectModal(); const [inputToken, setInputToken] = useState() const [outputToken, setOutputToken] = useState() - const [inputBalance, setInputBalance] = useState(0); + const [stepCounter, setStepCounter] = useState(0) + const [steps, setSteps] = useState([]) + const [action, setAction] = useState(ActionType.Deposit) + + const [inputBalance, setInputBalance] = useState("0"); const [isDeposit, setIsDeposit] = useState(true); + // Zap Settings + const [showModal, setShowModal] = useState(false) + const [tradeTimeout, setTradeTimeout] = useState(300); // number of seconds a cow order is valid for + const [slippage, setSlippage] = useState(100); // In BPS 0 - 10_000 + useEffect(() => { // set default input/output tokens setInputToken(asset) setOutputToken(!!gauge ? gauge : vault) + const actionType = !!gauge ? ActionType.DepositAndStake : ActionType.Deposit + setAction(actionType) + setSteps(getActionSteps(actionType)) }, []) - function handleChangeInput(e: any) { - setInputBalance(Number(e.currentTarget.value)); - } + const value = e.currentTarget.value + setInputBalance(validateInput(value).isValid ? value : "0"); + }; function switchTokens() { + setStepCounter(0) if (isDeposit) { // Switch to Withdraw setInputToken(!!gauge ? gauge : vault); setOutputToken(asset) setIsDeposit(false) + const newAction = !!gauge ? ActionType.UnstakeAndWithdraw : ActionType.Withdrawal + setAction(newAction) + setSteps(getActionSteps(newAction)) } else { // Switch to Deposit setInputToken(asset); setOutputToken(!!gauge ? gauge : vault) setIsDeposit(true) + const newAction = !!gauge ? ActionType.DepositAndStake : ActionType.Deposit + setAction(newAction) + setSteps(getActionSteps(newAction)) } } + function handleTokenSelect(input: Token, output: Token): void { + setInputToken(input); + setOutputToken(output) - async function handleMainAction() { - if (inputBalance === 0) return; - - if (chain?.id !== Number(chainId)) switchNetwork?.(Number(chainId)); - - switch (inputToken?.address) { + switch (input.address) { case asset.address: - console.log("in asset") - if (outputToken?.address === vault.address) { - console.log("out vault") - await handleAllowance({ - token: inputToken, - inputAmount: (inputBalance * (10 ** inputToken?.decimals)), - account: account as Address, - spender: vault.address, - publicClient, - walletClient: walletClient as WalletClient - }) - vaultDeposit({ - address: vault.address, - account: account as Address, - amount: (inputBalance * (10 ** inputToken?.decimals)), - publicClient, - walletClient: walletClient as WalletClient - }) - } - else if (outputToken?.address === gauge?.address) { - console.log("out gauge") - await handleAllowance({ - token: inputToken, - inputAmount: (inputBalance * (10 ** inputToken?.decimals)), - account: account as Address, - spender: VAULT_ROUTER, - publicClient, - walletClient: walletClient as WalletClient - }) - vaultDepositAndStake({ - address: VAULT_ROUTER, - account: account as Address, - amount: (inputBalance * (10 ** inputToken?.decimals)), - vault: vault?.address as Address, - gauge: gauge?.address as Address, - publicClient, - walletClient: walletClient as WalletClient - }) + switch (output.address) { + case asset.address: + // error + return + case vault.address: + setAction(ActionType.Deposit) + setSteps(getActionSteps(ActionType.Deposit)) + return + case gauge?.address: + setAction(ActionType.DepositAndStake) + setSteps(getActionSteps(ActionType.DepositAndStake)) + return + default: + // error + return } - else { - console.log("out error") - // wrong output token - return - } - break; case vault.address: - console.log("in vault") - if (outputToken?.address === asset.address) { - console.log("out asset") - vaultRedeem({ - address: vault.address, - account: account as Address, - amount: (inputBalance * (10 ** inputToken?.decimals)), - publicClient, - walletClient: walletClient as WalletClient - }) - } - else if (outputToken?.address === gauge?.address) { - console.log("out gauge") - await handleAllowance({ - token: vault, - inputAmount: (inputBalance * (10 ** vault?.decimals)), - account: account as Address, - spender: gauge?.address as Address, - publicClient, - walletClient: walletClient as WalletClient - }) - //gaugeDeposit() + switch (output.address) { + case asset.address: + setAction(ActionType.Withdrawal) + setSteps(getActionSteps(ActionType.Withdrawal)) + return + case vault.address: + // error + return + case gauge?.address: + setAction(ActionType.Stake) + setSteps(getActionSteps(ActionType.Stake)) + return + default: + setAction(ActionType.ZapWithdrawal) + setSteps(getActionSteps(ActionType.ZapWithdrawal)) + return } - else { - console.log("out error") - // wrong output token - return - } - break; case gauge?.address: - console.log("in gauge") - if (outputToken?.address === asset.address) { - console.log("out asset") - await handleAllowance({ - token: inputToken, - inputAmount: (inputBalance * (10 ** vault?.decimals)), - account: account as Address, - spender: VAULT_ROUTER, - publicClient, - walletClient: walletClient as WalletClient - }) - vaultUnstakeAndWithdraw({ - address: VAULT_ROUTER, - account: account as Address, - amount: (inputBalance * (10 ** inputToken?.decimals)), - vault: vault?.address as Address, - gauge: gauge?.address as Address, - publicClient, - walletClient: walletClient as WalletClient - }) - } - else if (outputToken?.address === vault.address) { - console.log("out vault") - //gaugeWithdraw() + switch (output.address) { + case asset.address: + setAction(ActionType.UnstakeAndWithdraw) + setSteps(getActionSteps(ActionType.UnstakeAndWithdraw)) + return + case vault.address: + setAction(ActionType.Unstake) + setSteps(getActionSteps(ActionType.Unstake)) + return + case gauge?.address: + // error + return + default: + setAction(ActionType.ZapUnstakeAndWithdraw) + setSteps(getActionSteps(ActionType.ZapUnstakeAndWithdraw)) + return } - else { - console.log("out error") - // wrong output token - return + default: + switch (output.address) { + case asset.address: + // error + return + case vault.address: + setAction(ActionType.ZapDeposit) + setSteps(getActionSteps(ActionType.ZapDeposit)) + return + case gauge?.address: + setAction(ActionType.ZapDepositAndStake) + setSteps(getActionSteps(ActionType.ZapDepositAndStake)) + return + default: + // error + return } - break; } } + async function handleMainAction() { + const val = Number(inputBalance) + if (val === 0 || !inputToken || !outputToken || !account || !walletClient) return; + + if (chain?.id !== Number(chainId)) switchNetwork?.(Number(chainId)); + + const stepsCopy = [...steps] + const currentStep = stepsCopy[stepCounter] + currentStep.loading = true + setSteps(stepsCopy) + + const vaultInteraction = await handleVaultInteraction({ + action, + stepCounter, + chainId, + amount: (val * (10 ** inputToken.decimals)), + inputToken, + outputToken, + asset, + vault, + gauge, + account, + slippage, + tradeTimeout, + clients: { publicClient, walletClient } + }) + const success = await vaultInteraction() + + currentStep.loading = false + currentStep.success = success; + currentStep.error = !success; + const newStepCounter = stepCounter + 1 + setSteps(stepsCopy) + setStepCounter(newStepCounter) + + if (newStepCounter === steps.length) { + mutateTokenBalance({ inputToken: inputToken.address, outputToken: outputToken.address, vault: vault.address, chainId, account }) + // Reset to start + setSteps(getActionSteps(action)) + setStepCounter(0) + } + } + + function resetActions() { + setSteps(getActionSteps(action)) + setStepCounter(0) + } + if (!inputToken || !outputToken) return <> return <> + +
+

Slippage (in BPS)

+
+ setSlippage(Number(e.currentTarget.value))} + /> +
+
+
+

Timeout (in seconds)

+
+ setTradeTimeout(Number(e.currentTarget.value))} + /> +
+
+
setInputToken(option)} - onMaxClick={() => handleChangeInput({ currentTarget: { value: inputToken.balance / (10 ** inputToken.decimals) } })} + onSelectToken={option => handleTokenSelect(option, !!gauge ? gauge : vault)} + onMaxClick={() => handleChangeInput( + { + currentTarget: { + value: formatUnits(safeRound( + BigInt(inputToken.balance.toLocaleString("fullwide", { useGrouping: false })), + inputToken.decimals), inputToken.decimals) + } + })} chainId={chainId} value={inputBalance} onChange={handleChangeInput} selectedToken={inputToken} errorMessage={""} - tokenList={[]} - allowSelection={false} + tokenList={tokenOptions.filter(token => + gauge?.address + ? token.address !== gauge?.address + : token.address !== vault.address + )} + allowSelection={isDeposit} allowInput />
@@ -214,19 +278,42 @@ export default function VaultInputs({ vault, asset, gauge, tokenOptions, chainId
setOutputToken(option)} + onSelectToken={option => handleTokenSelect(!!gauge ? gauge : vault, option)} onMaxClick={() => { }} chainId={chainId} - value={(inputBalance * (Number(inputToken?.price)) / Number(outputToken?.price)) || 0} + value={(Number(inputBalance) * (Number(inputToken?.price)) / Number(outputToken?.price)) || 0} onChange={() => { }} selectedToken={outputToken} errorMessage={""} - tokenList={[]} - allowSelection={false} + tokenList={tokenOptions.filter(token => + gauge?.address + ? token.address !== gauge?.address + : token.address !== vault.address + )} + allowSelection={!isDeposit} allowInput={false} /> -
- + {((isDeposit && ![asset.address, vault.address].includes(inputToken.address)) || + (!isDeposit && ![asset.address, vault.address].includes(outputToken.address))) && +
setShowModal(true)}> +
+ } +
+ +
+
+ {account ? ( + <> + {(stepCounter === steps.length || steps.some(step => !step.loading && step.error)) ? + : + + } + + ) + : < MainActionButton label={"Connect Wallet"} handleClick={openConnectModal} /> + }
} \ No newline at end of file diff --git a/components/vault/VaultsSorting.tsx b/components/vault/VaultsSorting.tsx new file mode 100644 index 0000000..87511b1 --- /dev/null +++ b/components/vault/VaultsSorting.tsx @@ -0,0 +1,159 @@ +import PseudoRadioButton from "@/components/button/PseudoRadioButton"; +import { useMemo, useRef, useState } from "react"; +import PopUpModal from "@/components/modal/PopUpModal"; +import SwitchIcon from "@/components/svg/SwitchIcon"; + +export enum VAULT_SORTING_TYPE { + none = 'none', + mostTvl = 'most-tvl', + lessTvl = 'less-tvl', + mostvAPR = 'most-apr', + lessvAPR = 'less-apr' +} + +interface VaultSortingProps { + className?: string, + currentSortingType: VAULT_SORTING_TYPE, + sortByMostTvl: () => void, + sortByLessTvl: () => void + sortByMostApy: () => void, + sortByLessApy: () => void +} + +export default function VaultsSorting( + { + className, + currentSortingType, + sortByMostTvl, + sortByLessTvl, + sortByMostApy, + sortByLessApy, + }: VaultSortingProps): JSX.Element { + const [openFilter, setOpenSorting] = useState(false); + + const dropdownRef = useRef(null); + + const isLessThenMdScreenSize = useMemo(() => window.innerWidth < 1024, [window.innerWidth]) + + const sortingLessTvl = () => { + sortByLessTvl() + toggleDropdown() + } + + const sortingMostTvl = () => { + sortByMostTvl() + toggleDropdown() + } + + const sortingLessApy = () => { + sortByLessApy() + toggleDropdown() + } + + const sortingMostApy = () => { + sortByMostApy() + toggleDropdown() + } + + const toggleDropdown = () => { + setOpenSorting(prevState => !prevState) + } + + return ( +
+ + {openFilter && !isLessThenMdScreenSize && ( +
+ + + + +
+ )} + {isLessThenMdScreenSize && ( +
+ setOpenSorting(false)}> + <> +

Select a sorting type

+
+ + + + +
+ +
+
+ )} +
+ ); +} diff --git a/components/vepop/Gauge.tsx b/components/vepop/Gauge.tsx new file mode 100644 index 0000000..72f806a --- /dev/null +++ b/components/vepop/Gauge.tsx @@ -0,0 +1,122 @@ +import { useState } from "react"; +import { Address, useAccount } from "wagmi"; +import Slider from "rc-slider"; +import AssetWithName from "@/components/vault/AssetWithName"; +import { VaultData } from "@/lib/types"; +import Accordion from "@/components/common/Accordion"; +import Title from "@/components/common/Title"; +import useGaugeWeights from "@/lib/gauges/useGaugeWeights"; + +export default function Gauge({ vault, index, votes, handleVotes, canVote }: { vault: VaultData, index: number, votes: number[], handleVotes: Function, canVote: boolean }): JSX.Element { + const { address: account } = useAccount() + + const { data: weights } = useGaugeWeights({ address: vault.gauge?.address as Address, account: account as Address, chainId: vault.chainId }) + + const [amount, setAmount] = useState(0); + + function onChange(value: number) { + const currentVoteForThisGauge = votes[index]; + const potentialNewTotalVotes = votes.reduce((a, b) => a + b, 0) - currentVoteForThisGauge + Number(value); + + if (potentialNewTotalVotes <= 10000) { + handleVotes(value, index); + setAmount(value); + } + } + + return ( + +
+ +
+ +
+ +
+

Current Weight

+

+ + {(Number(weights?.[0]) / 1e16).toFixed() || 0} % + +

+
+ +
+

Upcoming Weight

+

+ + {(Number(weights?.[1]) / 1e16).toFixed() || 0} % + +

+
+ +
+

My Votes

+

+ + {(Number(weights?.[2].power) / 100).toFixed()} % + +

+
+ +
+

Vote

+
+
+ + {(votes[index] / 100).toFixed() || 0} % + +
+
+ onChange(Number(val)) : () => { }} + max={10000} + /> +
+
+
+ +
+
+
+
+
+
+ + + } + > + {/* Accordion Content */} +
+
+ +

Gauge address:

+

+ {vault.gauge?.address} +

+
+
+
+ +

Vault address:

+

+ {vault.address} +

+
+
+
+ + ); +} \ No newline at end of file diff --git a/components/vepop/OPopInterface.tsx b/components/vepop/OPopInterface.tsx new file mode 100644 index 0000000..d91da5d --- /dev/null +++ b/components/vepop/OPopInterface.tsx @@ -0,0 +1,83 @@ +import getGaugeRewards, { GaugeRewards } from "@/lib/gauges/getGaugeRewards" +import getGauges from "@/lib/gauges/getGauges"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { NumberFormatter } from "@/lib/utils/formatBigNumber"; +import { Dispatch, SetStateAction, useEffect, useState } from "react" +import { Address, useAccount, useBalance, usePublicClient, useWalletClient } from "wagmi" +import MainActionButton from "../button/MainActionButton"; +import SecondaryActionButton from "../button/SecondaryActionButton"; +import { claimOPop } from "@/lib/oPop/interactions"; +import { WalletClient } from "viem"; +import { Token } from "@/lib/types"; + +const { + oVCX: OVCX, + VCX, + WETH +} = getVeAddresses(); + +interface OPopInterfaceProps { + gauges: Token[]; + setShowOPopModal: Dispatch>; +} + +export default function OPopInterface({ gauges, setShowOPopModal }: OPopInterfaceProps): JSX.Element { + const { address: account } = useAccount() + const publicClient = usePublicClient(); + const { data: walletClient } = useWalletClient() + + const [gaugeRewards, setGaugeRewards] = useState() + const { data: vcxBal } = useBalance({ chainId: 1, address: account, token: VCX, watch: true }) + const { data: oBal } = useBalance({ chainId: 1, address: account, token: OVCX, watch: true }) + const { data: wethBal } = useBalance({ chainId: 1, address: account, token: WETH, watch: true }) + + const [initalLoad, setInitalLoad] = useState(false); + + useEffect(() => { + async function getValues() { + setInitalLoad(true) + const rewards = await getGaugeRewards({ + gauges: gauges.map(gauge => gauge.address) as Address[], + account: account as Address, + publicClient + }) + setGaugeRewards(rewards) + } + if (account && gauges.length > 0 && !initalLoad) getValues() + }, [gauges, account]) + + return ( +
+

oVCX

+ +

Claimable oVCX

+

{`${gaugeRewards ? NumberFormatter.format(Number(gaugeRewards?.total) / 1e18) : "0"}`}

+
+ +

My VCX

+

{`${vcxBal ? NumberFormatter.format(Number(vcxBal?.value) / 1e18) : "0"}`}

+
+ +

My oVCX

+

{`${oBal ? NumberFormatter.format(Number(oBal?.value) / 1e18) : "0"}`}

+
+ +

My WETH

+

{`${oBal ? NumberFormatter.format(Number(wethBal?.value) / 1e18) : "0"}`}

+
+
+ + claimOPop({ + gauges: gaugeRewards?.amounts?.filter(gauge => Number(gauge.amount) > 0).map(gauge => gauge.address) as Address[], + account: account as Address, + clients: { publicClient, walletClient: walletClient as WalletClient } + })} + disabled={gaugeRewards ? Number(gaugeRewards?.total) === 0 : true} + /> + setShowOPopModal(true)} disabled={oBal ? Number(oBal?.value) === 0 : true} /> +
+
+ ) +} \ No newline at end of file diff --git a/components/vepop/StakingInterface.tsx b/components/vepop/StakingInterface.tsx new file mode 100644 index 0000000..a3a19f4 --- /dev/null +++ b/components/vepop/StakingInterface.tsx @@ -0,0 +1,74 @@ +import { intervalToDuration } from "date-fns"; +import { Dispatch, SetStateAction } from "react"; +import { Address, useAccount, useBalance } from "wagmi"; +import { getVotePeriodEndTime } from "@/lib/gauges/utils"; +import MainActionButton from "@/components/button/MainActionButton"; +import SecondaryActionButton from "@/components//button/SecondaryActionButton"; +import useLockedBalanceOf from "@/lib/gauges/useLockedBalanceOf"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { NumberFormatter } from "@/lib/utils/formatBigNumber"; +import { formatEther } from "viem"; +import { ZERO } from "@/lib/constants"; + +function votingPeriodEnd(): number[] { + const periodEnd = getVotePeriodEndTime(); + const interval = { start: new Date(), end: periodEnd }; + const timeUntilEnd = intervalToDuration(interval); + const formattedTime = [ + (timeUntilEnd.days || 0) % 7, + timeUntilEnd.hours || 0, + timeUntilEnd.minutes || 0, + timeUntilEnd.seconds || 0, + ]; + return formattedTime; +} + +const { + WETH_VCX_LP, + VotingEscrow: VOTING_ESCROW, +} = getVeAddresses(); + +interface StakingInterfaceProps { + setShowLockModal: Dispatch>; + setShowMangementModal: Dispatch>; +} + +export default function StakingInterface({ setShowLockModal, setShowMangementModal }: StakingInterfaceProps): JSX.Element { + const { address: account } = useAccount() + + const { data: lockedBal } = useLockedBalanceOf({ chainId: 1, address: VOTING_ESCROW, account: account as Address }) + const { data: veBal } = useBalance({ chainId: 1, address: account, token: VOTING_ESCROW, watch: true }) + const { data: lpBal } = useBalance({ chainId: 1, address: account, token: WETH_VCX_LP, watch: true }) + + return ( + <> +
+

veVCX

+ +

My VCX LP

+

{NumberFormatter.format(Number(formatEther(lpBal?.value || ZERO))) || "0"}

+
+ +

My Locked VCX LP

+

{lockedBal ? NumberFormatter.format(Number(formatEther(lockedBal?.amount))) : "0"}

+
+ +

Locked Until

+

{lockedBal && lockedBal?.end.toString() !== "0" ? new Date(Number(lockedBal?.end) * 1000).toLocaleDateString() : "-"}

+
+ +

My veVCX

+

{NumberFormatter.format(Number(formatEther(veBal?.value || ZERO))) || "0"}

+
+ +

Voting period ends

+

{votingPeriodEnd()[0]}d : {votingPeriodEnd()[1]}h: {votingPeriodEnd()[2]}m

+
+
+ setShowLockModal(true)} disabled={Number(veBal?.value) > 0} /> + setShowMangementModal(true)} disabled={Number(veBal?.value) === 0} /> +
+
+ + ) +} \ No newline at end of file diff --git a/components/vepop/VeRewards.tsx b/components/vepop/VeRewards.tsx new file mode 100644 index 0000000..7698431 --- /dev/null +++ b/components/vepop/VeRewards.tsx @@ -0,0 +1,61 @@ +import { useEffect, useState } from "react"; +import { Address, formatEther } from "viem"; +import { goerli } from "viem/chains"; +import { useAccount } from "wagmi"; +import MainActionButton from "@/components/button/MainActionButton"; +import getClaimableVeReward from "@/lib/feeDistributor/getClaimableVeReward"; +import getVeApy from "@/lib/feeDistributor/getVeApy"; +import { useClaimTokens } from "@/lib/feeDistributor/useClaimToken"; +import { getVeAddresses } from "@/lib/utils/addresses"; + +function noOp() { } + +const { + WETH: WETH, + FeeDistributor: FEE_DISTRIBUTOR +} = getVeAddresses(); + +export default function VeRewards(): JSX.Element { + const { address: account } = useAccount() + const { write: claimTokens = noOp } = useClaimTokens(FEE_DISTRIBUTOR, account as Address, [WETH]); + + const [apy, setApy] = useState(0); + + useEffect(() => { + if (apy === 0) { + getVeApy({ chain: goerli, address: FEE_DISTRIBUTOR, token: "0x2D9B33e9918Dce388d1Cb8Bf09D4E827b899e9d9" }).then(res => setApy(res)) + } + }, [apy]) + + const [initalLoad, setInitalLoad] = useState(false); + const [accountLoad, setAccountLoad] = useState(false); + + const [claimableVeReward, setClaimableVeReward] = useState(BigInt(0)); + + useEffect(() => { + async function getClaimableReward() { + setInitalLoad(true) + if (account) setAccountLoad(true) + getClaimableVeReward({ chain: goerli, address: FEE_DISTRIBUTOR, user: account as Address, token: WETH }).then(res => setClaimableVeReward(res)) + } + if (!account && !initalLoad) getClaimableReward(); + if (account && !accountLoad) getClaimableReward() + }, [account]) + + return ( +
+

Total veVCX Rewards

+ +

APR

+

{apy} %

+
+ +

Claimable WETH

+

{parseFloat(formatEther(claimableVeReward)).toFixed(3)} wETH

+
+
+ claimTokens()} disabled={Number(claimableVeReward) === 0} /> +
+
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/lock/LockModal.tsx b/components/vepop/modals/lock/LockModal.tsx new file mode 100644 index 0000000..2d22889 --- /dev/null +++ b/components/vepop/modals/lock/LockModal.tsx @@ -0,0 +1,83 @@ +import { Address, useAccount, useNetwork, usePublicClient, useSwitchNetwork, useWalletClient } from "wagmi"; +import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import { WalletClient } from "viem"; +import Modal from "@/components/modal/Modal"; +import MainActionButton from "@/components/button/MainActionButton"; +import SecondaryActionButton from "@/components/button/SecondaryActionButton"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import LockPopInfo from "@/components/vepop/modals/lock/LockPopInfo"; +import LockPopInterface from "@/components/vepop/modals/lock/LockPopInterface"; +import LockPreview from "@/components/vepop/modals/lock/LockPreview"; +import VotingPowerInfo from "@/components/vepop/modals/lock/VotingPowerInfo"; +import { handleAllowance } from "@/lib/approve"; +import { Token } from "@/lib/types"; +import { createLock } from "@/lib/gauges/interactions"; + +const { + BalancerPool: VCX_LP, + VotingEscrow: VOTING_ESCROW +} = getVeAddresses() + +export default function LockModal({ show }: { show: [boolean, Dispatch>] }): JSX.Element { + const { address: account } = useAccount(); + const { chain } = useNetwork(); + const { switchNetwork } = useSwitchNetwork(); + + const publicClient = usePublicClient(); + const { data: walletClient } = useWalletClient() + + const [step, setStep] = useState(0); + const [showModal, setShowModal] = show; + + const [amount, setAmount] = useState("0"); + const [days, setDays] = useState(7); + + useEffect(() => { + if (!showModal) setStep(0) + }, + [showModal] + ) + + async function handleLock() { + const val = Number(amount) + + if ((val || 0) == 0) return; + // Early exit if value is ZERO + + + if (chain?.id as number !== Number(1)) switchNetwork?.(Number(1)); + + await handleAllowance({ + token: VCX_LP, + amount: (val * (10 ** 18) || 0), + account: account as Address, + spender: VOTING_ESCROW, + clients: { + publicClient, + walletClient: walletClient as WalletClient + } + }) + // When approved continue to deposit + createLock(({ amount: (val || 0), days, account: account as Address, clients: { publicClient, walletClient: walletClient as WalletClient } })); + setShowModal(false); + } + + + return ( + + <> + {step === 0 && } + {step === 1 && } + {step === 2 && } + {step === 3 && } + +
+ {step < 3 && setStep(step + 1)} />} + {step === 3 && } + {step === 0 && setStep(2)} />} + {step === 1 || step === 3 && setStep(step - 1)} />} +
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/lock/LockPopInfo.tsx b/components/vepop/modals/lock/LockPopInfo.tsx new file mode 100644 index 0000000..4987b89 --- /dev/null +++ b/components/vepop/modals/lock/LockPopInfo.tsx @@ -0,0 +1,26 @@ +export default function LockPopInfo(): JSX.Element { + return ( +
+ + + + + +
+

Locking VCX

+

+ Lock your VCX LP to receive vote-escrowed veVCX. + veVCX has many purposes. + It allows you to boost your vault yield by earning VCX call options (oVCX). + You can use veVCX to vote on vault gauge incentives, + participate in governance and earn protocol fees. + Unlocking VCX early results in a penalty of up to 75% of your VCX. +

+
+
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/lock/LockPopInterface.tsx b/components/vepop/modals/lock/LockPopInterface.tsx new file mode 100644 index 0000000..4f8d5f6 --- /dev/null +++ b/components/vepop/modals/lock/LockPopInterface.tsx @@ -0,0 +1,123 @@ +import { Dispatch, FormEventHandler, SetStateAction, useMemo } from "react"; +import { useAccount, useBalance, useToken } from "wagmi"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import InputTokenWithError from "@/components/input/InputTokenWithError"; +import InputNumber from "@/components/input/InputNumber"; +import { calcUnlockTime, calculateVeOut } from "@/lib/gauges/utils"; +import { ZERO } from "@/lib/constants"; +import { safeRound } from "@/lib/utils/formatBigNumber"; +import { validateInput } from "@/lib/utils/helpers"; +import { formatEther } from "viem"; + +const { BalancerPool: VCX_LP } = getVeAddresses(); + +function LockTimeButton({ label, isActive, handleClick }: { label: string, isActive: boolean, handleClick: Function }): JSX.Element { + return ( + + ) +} + +interface LockPopInterfaceProps { + amountState: [string, Dispatch>]; + daysState: [number, Dispatch>]; +} + +export default function LockPopInterface({ amountState, daysState }: LockPopInterfaceProps): JSX.Element { + const { address: account } = useAccount() + const { data: lpToken } = useToken({ chainId: 1, address: VCX_LP }); + const { data: lpBal } = useBalance({ chainId: 1, address: account, token: VCX_LP }) + + const [amount, setAmount] = amountState + const [days, setDays] = daysState + + const errorMessage = useMemo(() => { + return (Number(amount) || 0) > Number(lpBal?.formatted) ? "* Balance not available" : ""; + }, [amount, lpBal?.formatted]); + + const handleMaxClick = () => setAmount(formatEther(safeRound(lpBal?.value || ZERO, 18))); + + const handleChangeInput: FormEventHandler = ({ currentTarget: { value } }) => { + setAmount(validateInput(value).isValid ? value : "0"); + }; + + const handleSetDays: FormEventHandler = ({ currentTarget: { value } }) => { + setDays(Number(value)); + }; + + return ( +
+ +

Lock your VCX

+ +
+

Amount VCX

+ { }} + onMaxClick={handleMaxClick} + chainId={1} + value={String(amount)} + onChange={handleChangeInput} + selectedToken={ + { + ...lpToken, + balance: Number(lpBal?.value || 0), + } as any + } + errorMessage={errorMessage} + allowInput + tokenList={[]} + getTokenUrl="https://app.balancer.fi/#/ethereum/pool/0x577a7f7ee659aa14dc16fd384b3f8078e23f1920000200000000000000000633 " + /> +
+ +
+
+

Lockup Time

+

Custom Time

+
+
+ setDays(7)} /> + setDays(30)} /> + setDays(90)} /> + setDays(180)} /> + setDays(365)} /> + setDays(730)} /> + setDays(1460)} /> +
+ +
+
+
+

Unlocks at:

+

{new Date(calcUnlockTime(days)).toLocaleDateString()}

+
+
+ +
+

Voting Power

+
+ +

{Number(amount) > 0 ? calculateVeOut(Number(amount), days).toFixed(2) : "Enter the amount to view your voting power"}

+
+
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/lock/LockPreview.tsx b/components/vepop/modals/lock/LockPreview.tsx new file mode 100644 index 0000000..b8d6d28 --- /dev/null +++ b/components/vepop/modals/lock/LockPreview.tsx @@ -0,0 +1,31 @@ +import { calcUnlockTime, calculateVeOut } from "@/lib/gauges/utils"; + +export default function LockPreview({ amount, days }: { amount: string, days: number }): JSX.Element { + const val = Number(amount); + return ( +
+ +

Preview Lock

+ +
+
+

Lock Amount

+

{val > 0 ? val.toFixed(2) : "0"} VCX

+
+
+

Unlock Date

+

{new Date(calcUnlockTime(days)).toLocaleDateString()}

+
+
+

Initial Voting Power

+

{val > 0 ? calculateVeOut(val, days).toFixed(2) : "0"}

+
+
+ +
+

Important: veVCX is not transferrable and unlocking VCX LP early results in a penalty of up to 75% of your VCX LP

+
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/lock/VotingPowerInfo.tsx b/components/vepop/modals/lock/VotingPowerInfo.tsx new file mode 100644 index 0000000..8c33b3c --- /dev/null +++ b/components/vepop/modals/lock/VotingPowerInfo.tsx @@ -0,0 +1,23 @@ +export default function VotingPowerInfo(): JSX.Element { + return ( +
+ + + + + + +
+

Voting Power

+

+ Lock your VCX LP longer for more veVCX. + Your veVCX balance represents your voting power which decreases linearly until expiry. +

+
+
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/manage/IncreaseStakeInterface.tsx b/components/vepop/modals/manage/IncreaseStakeInterface.tsx new file mode 100644 index 0000000..908dbf2 --- /dev/null +++ b/components/vepop/modals/manage/IncreaseStakeInterface.tsx @@ -0,0 +1,86 @@ +import { Dispatch, FormEventHandler, SetStateAction, useMemo } from "react"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { Address, useAccount, useBalance, useToken } from "wagmi"; +import { formatAndRoundBigNumber, safeRound } from "@/lib/utils/formatBigNumber"; +import { ZERO } from "@/lib/constants"; +import InputTokenWithError from "@/components/input/InputTokenWithError"; +import { calcDaysToUnlock, calculateVeOut } from "@/lib/gauges/utils"; +import { validateInput } from "@/lib/utils/helpers"; +import { formatEther } from "viem"; + +const {WETH_VCX_LP } = getVeAddresses(); + +interface IncreaseStakeInterfaceProps { + amountState: [string, Dispatch>]; + lockedBal: { amount: bigint, end: bigint } +} + +export default function IncreaseStakeInterface({ amountState, lockedBal }: IncreaseStakeInterfaceProps): JSX.Element { + const { address: account } = useAccount() + const { data: lpToken } = useToken({ chainId: 1, address: WETH_VCX_LP as Address }); + const { data: lpBal } = useBalance({ chainId: 1, address: account, token: WETH_VCX_LP }) + + const [amount, setAmount] = amountState + + const errorMessage = useMemo(() => { + return (Number(amount) || 0) > Number(lpBal?.formatted) ? "* Balance not available" : ""; + }, [amount, lpBal?.formatted]); + + const handleMaxClick = () => setAmount(formatEther(safeRound(lpBal?.value || ZERO, 18))); + + const handleChangeInput: FormEventHandler = ({ currentTarget: { value } }) => { + setAmount(validateInput(value).isValid ? value : "0"); + }; + + return ( +
+ +

Lock your VCX

+ +
+

Amount VCX

+ { }} + onMaxClick={handleMaxClick} + chainId={1} + value={String(amount)} + onChange={handleChangeInput} + selectedToken={ + { + ...lpToken, + balance: Number(lpBal?.value || 0) || 0, + } as any + } + errorMessage={errorMessage} + allowInput + tokenList={[]} + getTokenUrl="https://app.balancer.fi/#/ethereum/pool/0x577a7f7ee659aa14dc16fd384b3f8078e23f1920000200000000000000000633 " + /> +
+ +
+
+

Current Lock Amount

+

{lockedBal ? formatAndRoundBigNumber(lockedBal?.amount, 18) : ""} VCX

+
+
+

Unlock Date

+

{lockedBal && lockedBal?.end.toString() !== "0" ? new Date(Number(lockedBal?.end) * 1000).toLocaleDateString() : "-"}

+
+
+ +
+

New Voting Power

+
+

+ {Number(amount) > 0 ? + calculateVeOut(Number(amount) + (Number(lockedBal?.amount) / 1e18), calcDaysToUnlock(Number(lockedBal?.end))).toFixed(2) + : "Enter the amount to view your voting power"} +

+
+
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/manage/IncreaseStakePreview.tsx b/components/vepop/modals/manage/IncreaseStakePreview.tsx new file mode 100644 index 0000000..4b278a0 --- /dev/null +++ b/components/vepop/modals/manage/IncreaseStakePreview.tsx @@ -0,0 +1,37 @@ +import { calcDaysToUnlock, calculateVeOut } from "@/lib/gauges/utils" + +export default function IncreaseStakePreview({ amount, lockedBal }: { amount: string, lockedBal: { amount: bigint, end: bigint } }): JSX.Element { + const val = Number(amount); + const totalLocked = (Number(lockedBal?.amount) / 1e18) + val + + return ( +
+ +

Preview Lock

+ +
+
+

Lock Amount

+

{val > 0 ? val.toFixed(2) : "0"} VCX LP

+
+
+

Total Locked

+

{lockedBal ? totalLocked.toFixed(2) : ""} VCX LP

+
+
+

Unlock Date

+

{lockedBal && lockedBal?.end.toString() !== "0" ? new Date(Number(lockedBal?.end) * 1000).toLocaleDateString() : "-"}

+
+
+

New Voting Power

+

{val > 0 ? calculateVeOut((Number(lockedBal?.amount) / 1e18) + val, calcDaysToUnlock(Number(lockedBal?.end))).toFixed(2) : "0"} veVCX

+
+
+ +
+

Important: veVCX is not transferrable and unlocking VCX LP early results in a penalty of up to 75% of your VCX LP

+
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/manage/IncreaseTimeInterface.tsx b/components/vepop/modals/manage/IncreaseTimeInterface.tsx new file mode 100644 index 0000000..4f02404 --- /dev/null +++ b/components/vepop/modals/manage/IncreaseTimeInterface.tsx @@ -0,0 +1,75 @@ +import { Dispatch, FormEventHandler, SetStateAction } from "react"; +import InputNumber from "@/components/input/InputNumber"; +import { calcDaysToUnlock, calcUnlockTime, calculateVeOut } from "@/lib/gauges/utils"; + + +function LockTimeButton({ label, isActive, handleClick }: { label: string, isActive: boolean, handleClick: Function }): JSX.Element { + return ( + + ) +} + +export default function IncreaseTimeInterface({ daysState, lockedBal }: + { daysState: [number, Dispatch>], lockedBal: { amount: bigint, end: bigint } }): JSX.Element { + const [days, setDays] = daysState + + const handleSetDays: FormEventHandler = ({ currentTarget: { value } }) => { + setDays(Number(value)); + }; + + const totalDays = calcDaysToUnlock(Number(lockedBal?.end)) + days + + return ( +
+ +

Increase lock time

+ +
+
+

Lockup Time

+

Custom Time

+
+
+ setDays(7)} /> + setDays(30)} /> + setDays(90)} /> + setDays(180)} /> + setDays(365)} /> + setDays(730)} /> + setDays(1460)} /> +
+ +
+
+
+

Unlocks at:

+

{new Date(calcUnlockTime(totalDays)).toLocaleDateString()}

+
+
+ +
+

New Voting Power

+
+

{Number(lockedBal?.amount) > 0 ? calculateVeOut(Number(lockedBal?.amount) / 1e18, totalDays).toFixed(2) : "0"}

+
+
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/manage/IncreaseTimePreview.tsx b/components/vepop/modals/manage/IncreaseTimePreview.tsx new file mode 100644 index 0000000..85fc7a4 --- /dev/null +++ b/components/vepop/modals/manage/IncreaseTimePreview.tsx @@ -0,0 +1,37 @@ +import { calcDaysToUnlock, calcUnlockTime, calculateVeOut } from "@/lib/gauges/utils" + +export default function IncreaseTimePreview({ days, lockedBal }: { days: number, lockedBal: { amount: bigint, end: bigint } }): JSX.Element { + const totalDays = calcDaysToUnlock(Number(lockedBal?.end)) + days + const amount = Number(lockedBal?.amount) / 1e18 + + return ( +
+ +

Preview Lock

+ +
+
+

Lock Time

+

{days} Days

+
+
+

Unlock Date

+

{new Date(calcUnlockTime(totalDays)).toLocaleDateString()}

+
+
+

Lock Amount

+

{lockedBal && amount.toFixed(2)}

+
+
+

New Voting Power

+

{amount > 0 ? calculateVeOut(amount, totalDays).toFixed(2) : "0"} veVCX

+
+
+ +
+

Important: veVCX is not transferrable and unlocking VCX LP early results in a penalty of up to 75% of your VCX LP

+
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/manage/ManageLockModal.tsx b/components/vepop/modals/manage/ManageLockModal.tsx new file mode 100644 index 0000000..754ddcc --- /dev/null +++ b/components/vepop/modals/manage/ManageLockModal.tsx @@ -0,0 +1,136 @@ +import { Address, useAccount, useBalance, useNetwork, usePublicClient, useSwitchNetwork, useWalletClient } from "wagmi"; +import { WalletClient } from "viem"; +import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import { getVeAddresses } from "lib/utils/addresses"; +import useLockedBalanceOf from "@/lib/gauges/useLockedBalanceOf"; +import Modal from "@/components/modal/Modal"; +import MainActionButton from "@/components/button/MainActionButton"; +import SecondaryActionButton from "@/components/button/SecondaryActionButton"; +import { showErrorToast } from "@/lib/toasts"; +import { handleAllowance } from "@/lib/approve"; +import { Token } from "@/lib/types"; +import { increaseLockAmount, increaseLockTime, withdrawLock } from "@/lib/gauges/interactions"; +import SelectManagementOption from "./SelectManagementOption"; +import IncreaseStakeInterface from "./IncreaseStakeInterface"; +import IncreaseStakePreview from "./IncreaseStakePreview"; +import IncreaseTimeInterface from "./IncreaseTimeInterface"; +import IncreaseTimePreview from "./IncreaseTimePreview"; +import UnstakePreview from "./UnstakePreview"; + +const { + BalancerPool: VCX_LP, + VotingEscrow: VOTING_ESCROW, +} = getVeAddresses(); + +export enum ManagementOption { + IncreaseLock, + IncreaseTime, + Unlock +} + +export default function ManageLockModal({ show }: { show: [boolean, Dispatch>] }): JSX.Element { + const { chain } = useNetwork(); + const { switchNetwork } = useSwitchNetwork(); + const { address: account } = useAccount(); + + const publicClient = usePublicClient(); + const { data: walletClient } = useWalletClient() + + const [showModal, setShowModal] = show; + const [step, setStep] = useState(0); + const [mangementOption, setMangementOption] = useState(); + + const { data: veBal } = useBalance({ chainId: 1, address: account, token: VOTING_ESCROW }) + const { data: lockedBal } = useLockedBalanceOf({ chainId: 1, address: VOTING_ESCROW, account: account as Address }) as { data: { amount: bigint, end: bigint } } + + const [amount, setAmount] = useState("0"); + const [days, setDays] = useState(7); + const isIncreaseLockValid = ((Number(lockedBal?.end) - Math.floor(Date.now() / 1000)) / (604800)) < 207 + + useEffect(() => { + if (!showModal) { + setStep(0); + // @ts-ignore + setMangementOption(null) + } + }, + [showModal] + ) + + async function handleMainAction() { + if (chain?.id as number !== Number(1)) switchNetwork?.(Number(1)); + const val = Number(amount) + + const clients = { publicClient, walletClient: walletClient as WalletClient } + + if (mangementOption === ManagementOption.IncreaseLock) { + if ((val || 0) == 0) return; + await handleAllowance({ + token: VCX_LP, + amount: (val * (10 ** 18) || 0), + account: account as Address, + spender: VOTING_ESCROW, + clients:{publicClient, + walletClient: walletClient as WalletClient} + }) + increaseLockAmount({ amount: val, account: account as Address, clients }) + } + + if (mangementOption === ManagementOption.IncreaseTime) increaseLockTime({ unlockTime: Number(lockedBal?.end || 0) + (days * 86400), account: account as Address, clients }) + if (mangementOption === ManagementOption.Unlock) withdrawLock({ account: account as Address, clients }) + + setShowModal(false); + } + + return ( + + <> + {step === 0 && } + + {mangementOption === ManagementOption.IncreaseLock && + <> + {step === 1 && + <> + + setStep(step + 1)} /> + + } + {step === 2 && + <> + + + + } + + } + {mangementOption === ManagementOption.IncreaseTime && + <> + {step === 1 && + <> + + { + isIncreaseLockValid + ? setStep(step + 1)} /> + : showErrorToast("You've already locked your stake for the maximum time allowed")} + /> + } + + } + {step === 2 && + <> + + + + } + + } + {mangementOption === ManagementOption.Unlock && + <> + + + + } + + + ) +} \ No newline at end of file diff --git a/components/vepop/modals/manage/SelectManagementOption.tsx b/components/vepop/modals/manage/SelectManagementOption.tsx new file mode 100644 index 0000000..ae57eb0 --- /dev/null +++ b/components/vepop/modals/manage/SelectManagementOption.tsx @@ -0,0 +1,50 @@ +import TertiaryActionButton from "@/components/button/TertiaryActionButton"; +import { ManagementOption } from "@/components/vepop/modals/manage/ManageLockModal"; + +export default function SelectManagementOption({ setStep, setManagementOption }: { setStep: Function, setManagementOption: Function }): JSX.Element { + return ( +
+ + + + + +
+

Update your Lock

+

+ Increase your veVCX by locking more VCX LP or increasing the lock time for your locked VCX LP balance. + Alternatively Unlock your locked VCX LP. +

+
+
+
+ { + setManagementOption(ManagementOption.IncreaseLock); + setStep(1) + }} + /> +
+
+ { + setManagementOption(ManagementOption.IncreaseTime); + setStep(1) + }} + /> +
+
+ { + setManagementOption(ManagementOption.Unlock); + setStep(1) + }} + /> +
+
+
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/manage/UnstakePreview.tsx b/components/vepop/modals/manage/UnstakePreview.tsx new file mode 100644 index 0000000..0514fa4 --- /dev/null +++ b/components/vepop/modals/manage/UnstakePreview.tsx @@ -0,0 +1,32 @@ +export default function UnstakePreview({ amount }: { amount: number }): JSX.Element { + return ( +
+ +

Preview Unlock

+ +
+
+

Unlock Amount

+

{amount > 0 ? amount.toFixed(2) : "0"} VCX LP

+
+
+

Unlock Penalty

+

25%

+
+
+

Returned Amount

+

{amount > 0 ? (amount * 0.75).toFixed(2) : "0"} VCX LP

+
+
+

New Voting Power

+

0

+
+
+ +
+

Important: Unlocking your VCX LP early will results in a penalty of {(amount * 0.25).toFixed(2)} VCX LP

+
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/oPop/ExerciseOPopInterface.tsx b/components/vepop/modals/oPop/ExerciseOPopInterface.tsx new file mode 100644 index 0000000..592fec5 --- /dev/null +++ b/components/vepop/modals/oPop/ExerciseOPopInterface.tsx @@ -0,0 +1,200 @@ +import { Dispatch, FormEventHandler, SetStateAction, useEffect, useState } from "react"; +import { useAccount, useBalance, usePublicClient, useToken } from "wagmi"; +import { PlusIcon } from "@heroicons/react/24/outline"; +import TokenIcon from "@/components/common/TokenIcon"; +import InputTokenWithError from "@/components/input/InputTokenWithError"; +import { BalancerOracleAbi, ZERO } from "@/lib/constants"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { formatAndRoundBigNumber, safeRound } from "@/lib/utils/formatBigNumber"; +import { validateInput } from "@/lib/utils/helpers"; +import { Token } from "@/lib/types"; +import { llama } from "@/lib/resolver/price/resolver"; +import { useEthToUsd } from "@/lib/oPop/ethToUsd"; +import { formatEther } from "viem"; + +const { + VCX, + oVCX:OVCX, + BalancerOracle: OVCX_ORACLE, + WETH: WETH +} = getVeAddresses(); + +const SLIPPAGE = 0.01 // @dev adding some slippage to the call -- TODO -> we should later allow users to change that + +interface ExerciseOPopInterfaceProps { + amountState: [string, Dispatch>]; + maxPaymentAmountState: [string, Dispatch>]; +} + +export default function ExerciseOPopInterface({ amountState, maxPaymentAmountState }: ExerciseOPopInterfaceProps): JSX.Element { + const { address: account } = useAccount(); + const publicClient = usePublicClient(); + + const [amount, setAmount] = amountState; + const [maxPaymentAmount, setMaxPaymentAmount] = maxPaymentAmountState; + + const { data: oVcxBal } = useBalance({ chainId: 1, address: account, token: OVCX }) + const { data: wethBal } = useBalance({ chainId: 1, address: account, token: WETH }) + + const { data: oVcx } = useToken({ chainId: 1, address: OVCX }); + const { data: vcx } = useToken({ chainId: 1, address: VCX }); + const { data: weth } = useToken({ chainId: 1, address: WETH }); + + const [oVcxPrice, setOVcxPrice] = useState(ZERO); // oVCX price in ETH (needs to be multiplied with the eth price to arrive at USD prices) + const [oVcxDiscount, setOVcxDiscount] = useState(0); + const [vcxPrice, setVCXPrice] = useState(0); + const [wethPrice, setWethPrice] = useState(0); + + const [initialLoad, setInitialLoad] = useState(false) + + useEffect(() => { + function setUpPrices() { + setInitialLoad(true) + + //llama({ address: "0x6F0fecBC276de8fC69257065fE47C5a03d986394", chainId: 10 }).then(res => setVCXPrice(res)) + // TODO -- actually fetch VCX price + setVCXPrice(0.0001) + + llama({ address: WETH, chainId: 1 }).then(res => setWethPrice(res)) + publicClient.readContract({ + address: OVCX_ORACLE, + abi: BalancerOracleAbi, + functionName: 'getPrice', + }).then(res => setOVcxPrice(res)) + publicClient.readContract({ + address: OVCX_ORACLE, + abi: BalancerOracleAbi, + functionName: 'multiplier', + }).then(res => setOVcxDiscount(res)) + } + if (!initialLoad) setUpPrices() + }, [initialLoad]) + + function handleMaxWeth() { + const maxEth = formatEther(safeRound(wethBal?.value || ZERO, 18)); + + setMaxPaymentAmount(maxEth); + setAmount(getOPopAmount(Number(maxEth))) + }; + + function handleMaxOPop() { + const maxOPop = formatEther(safeRound(oVcxBal?.value || ZERO, 18)); + + setMaxPaymentAmount(getMaxPaymentAmount(Number(maxOPop))); + setAmount(maxOPop) + }; + + function getMaxPaymentAmount(oVcxAmount: number) { + const oVcxValue = oVcxAmount * ((Number(oVcxPrice) / 1e18) * wethPrice); + + return String((oVcxValue / wethPrice) * (1 + SLIPPAGE)); + } + + function getOPopAmount(paymentAmount: number) { + const ethValue = paymentAmount * wethPrice; + + return String(ethValue / (((Number(oVcxPrice) / 1e18) * wethPrice) * (1 - SLIPPAGE))); + } + + const handleOPopInput: FormEventHandler = ({ currentTarget: { value } }) => { + const amount = validateInput(value).isValid ? value : "0" + setAmount(amount); + setMaxPaymentAmount(getMaxPaymentAmount(Number(amount))); + }; + + const handleEthInput: FormEventHandler = ({ currentTarget: { value } }) => { + const amount = validateInput(value).isValid ? value : "0" + setMaxPaymentAmount(amount); + setAmount(getOPopAmount(Number(amount))); + }; + + return ( +
+

Exercise oVCX

+

+ Strike Price: $ {formatAndRoundBigNumber(useEthToUsd(oVcxPrice) || ZERO, 18)} + | VCX Price: $ {vcxPrice} + | Discount: {(Number(oVcxDiscount) / 100).toFixed(2)} %

+
+ { }} + onMaxClick={handleMaxOPop} + chainId={1} + value={amount} + onChange={handleOPopInput} + allowInput={true} + selectedToken={ + { + ...oVcx, + logoURI: "/images/tokens/oVcx.svg", + balance: oVcxBal?.value || ZERO, + } as any + } + errorMessage={Number(amount) > (Number(oVcxBal?.value) / 1e18) ? "Insufficient Balance" : ""} + tokenList={[]} + /> +
+ +
+ + { }} + onMaxClick={handleMaxWeth} + chainId={1} + value={maxPaymentAmount} + onChange={handleEthInput} + allowInput={true} + selectedToken={ + { + ...weth, + decimals: 18, + logoURI: "https://etherscan.io/token/images/weth_28.png", + balance: wethBal?.value || ZERO, + } as any + } + tokenList={[]} + errorMessage={Number(maxPaymentAmount) > (Number(wethBal?.value) / 1e18) ? "Insufficient Balance" : ""} + /> +
+ +
+ + +
+

Received VCX

+
+

{amount}

+ +
+ +
+

+ {vcx?.symbol} +

+
+
+ +
+
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/oPop/OPopModal.tsx b/components/vepop/modals/oPop/OPopModal.tsx new file mode 100644 index 0000000..637484f --- /dev/null +++ b/components/vepop/modals/oPop/OPopModal.tsx @@ -0,0 +1,76 @@ +import Modal from "@/components/modal/Modal"; +import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import { Address, WalletClient, useAccount, useNetwork, usePublicClient, useSwitchNetwork, useWalletClient } from "wagmi"; +import OptionInfo from "@/components/vepop/modals/oPop/OptionInfo"; +import ExerciseOPopInterface from "@/components/vepop/modals/oPop/ExerciseOPopInterface"; +import MainActionButton from "@/components/button/MainActionButton"; +import SecondaryActionButton from "@/components/button/SecondaryActionButton"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { handleAllowance } from "@/lib/approve"; +import { parseEther } from "viem"; +import { exerciseOPop } from "@/lib/oPop/interactions"; + +const { WETH, oVCX } = getVeAddresses(); + +export default function OPopModal({ show }: { show: [boolean, Dispatch>] }): JSX.Element { + const { chain } = useNetwork(); + const { switchNetwork } = useSwitchNetwork(); + const { address: account } = useAccount(); + const publicClient = usePublicClient(); + const { data: walletClient } = useWalletClient() + + const [step, setStep] = useState(0); + const [showModal, setShowModal] = show; + + const [amount, setAmount] = useState("0"); + const [maxPaymentAmount, setMaxPaymentAmount] = useState("0"); + + useEffect(() => { + if (!showModal) setStep(0) + setAmount("0"); + setMaxPaymentAmount("0"); + }, + [showModal] + ) + + async function handleExerciseOPop() { + if ((Number(amount) || 0) == 0) return; + // Early exit if value is ZERO + + if (chain?.id as number !== Number(1)) switchNetwork?.(Number(1)); + + await handleAllowance({ + token: WETH, + amount: (Number(amount) * (10 ** 18) || 0), + account: account as Address, + spender: oVCX, + clients: { + publicClient, + walletClient: walletClient as WalletClient + } + }) + + exerciseOPop({ + account: account as Address, + amount: parseEther(Number(amount).toLocaleString("fullwide", { useGrouping: false })), + maxPaymentAmount: parseEther(maxPaymentAmount), + clients: { publicClient, walletClient: walletClient as WalletClient } + }); + setShowModal(false); + } + + return ( + + <> + {step === 0 && } + {step === 1 && } + +
+ {step === 0 && setStep(step + 1)} />} + {step === 1 && } + {step === 1 && setStep(step - 1)} />} +
+ +
+ ) +} \ No newline at end of file diff --git a/components/vepop/modals/oPop/OptionInfo.tsx b/components/vepop/modals/oPop/OptionInfo.tsx new file mode 100644 index 0000000..2743a6b --- /dev/null +++ b/components/vepop/modals/oPop/OptionInfo.tsx @@ -0,0 +1,18 @@ +export default function OptionInfo(): JSX.Element { + return ( +
+ + + + + +
+

Exercise oVCX

+

+ Exercise your oVCX to buy discounted VCX. + You need to burn oVCX and pay with WETH to get cheap VCX directly from the DAO. +

+
+
+ ) +} \ No newline at end of file diff --git a/lib/approve.ts b/lib/approve.ts index f5333b9..72fbe51 100644 --- a/lib/approve.ts +++ b/lib/approve.ts @@ -1,15 +1,15 @@ -import { Address, PublicClient, WalletClient } from "viem" +import { Address, PublicClient, WalletClient, getAddress } from "viem" import { ERC20Abi } from "@/lib/constants" import { showErrorToast, showLoadingToast, showSuccessToast } from "@/lib/toasts" -import { SimulationResponse, Token } from "@/lib/types"; +import { Clients, SimulationResponse, Token } from "@/lib/types"; +import { UsdtAbi } from "./constants/abi/USDT"; interface HandleAllowanceProps { - token: Token; - inputAmount: number; + token: Address; + amount: number; account: Address; spender: Address; - publicClient: PublicClient; - walletClient: WalletClient; + clients: Clients; } interface SimulateApproveProps { @@ -19,25 +19,25 @@ interface SimulateApproveProps { publicClient: PublicClient; } -interface ApprovePops extends SimulateApproveProps { +interface ApproveProps extends SimulateApproveProps { walletClient: WalletClient; } -export async function handleAllowance({ token, inputAmount, account, spender, publicClient, walletClient }: HandleAllowanceProps): Promise { - const allowance = await publicClient.readContract({ - address: token.address, +export async function handleAllowance({ token, amount, account, spender, clients }: HandleAllowanceProps): Promise { + const allowance = await clients.publicClient.readContract({ + address: token, abi: ERC20Abi, functionName: "allowance", args: [account, spender] }) - if (Number(allowance) === 0 || Number(allowance) < inputAmount) { - return approve({ address: token.address, account, spender, publicClient, walletClient }) + if (Number(allowance) === 0 || Number(allowance) < amount) { + return approve({ address: token, account, spender, publicClient: clients.publicClient, walletClient: clients.walletClient }) } return true } -export default async function approve({ address, account, spender, publicClient, walletClient }: ApprovePops): Promise { +export default async function approve({ address, account, spender, publicClient, walletClient }: ApproveProps): Promise { showLoadingToast("Approving assets for deposit...") const { request, success, error: simulationError } = await simulateApprove({ address, account, spender, publicClient }) @@ -62,7 +62,8 @@ async function simulateApprove({ address, account, spender, publicClient }: Simu const { request } = await publicClient.simulateContract({ account, address, - abi: ERC20Abi, + // @ts-ignore -- for some reason viem is not happy when the two abis are slightly different + abi: address === "0xdAC17F958D2ee523a2206206994597C13D831ec7" ? UsdtAbi : ERC20Abi, // USDT doesnt return a bool on approval functionName: 'approve', args: [spender, BigInt("115792089237316195423570985008687907853269984665640")] }) diff --git a/lib/atoms/vaults.ts b/lib/atoms/vaults.ts new file mode 100644 index 0000000..ccf5554 --- /dev/null +++ b/lib/atoms/vaults.ts @@ -0,0 +1,5 @@ +import { atom } from "jotai"; +import { VaultData } from "@/lib/types"; + + +export const vaultsAtom = atom([]); diff --git a/lib/constants/abi/BalancerOracle.ts b/lib/constants/abi/BalancerOracle.ts new file mode 100644 index 0000000..c453027 --- /dev/null +++ b/lib/constants/abi/BalancerOracle.ts @@ -0,0 +1 @@ +export const BalancerOracleAbi = [{ "inputs": [{ "internalType": "contract IBalancerTwapOracle", "name": "balancerTwapOracle_", "type": "address" }, { "internalType": "address", "name": "owner_", "type": "address" }, { "internalType": "uint16", "name": "multiplier_", "type": "uint16" }, { "internalType": "uint56", "name": "secs_", "type": "uint56" }, { "internalType": "uint56", "name": "ago_", "type": "uint56" }, { "internalType": "uint128", "name": "minPrice_", "type": "uint128" }], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [], "name": "BalancerOracle__TWAPOracleNotReady", "type": "error" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "user", "type": "address" }, { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" }], "name": "OwnershipTransferred", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": false, "internalType": "uint16", "name": "multiplier", "type": "uint16" }, { "indexed": false, "internalType": "uint56", "name": "secs", "type": "uint56" }, { "indexed": false, "internalType": "uint56", "name": "ago", "type": "uint56" }, { "indexed": false, "internalType": "uint128", "name": "minPrice", "type": "uint128" }], "name": "SetParams", "type": "event" }, { "inputs": [], "name": "ago", "outputs": [{ "internalType": "uint56", "name": "", "type": "uint56" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "balancerTwapOracle", "outputs": [{ "internalType": "contract IBalancerTwapOracle", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getPrice", "outputs": [{ "internalType": "uint256", "name": "price", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "minPrice", "outputs": [{ "internalType": "uint128", "name": "", "type": "uint128" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "multiplier", "outputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "secs", "outputs": [{ "internalType": "uint56", "name": "", "type": "uint56" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint16", "name": "multiplier_", "type": "uint16" }, { "internalType": "uint56", "name": "secs_", "type": "uint56" }, { "internalType": "uint56", "name": "ago_", "type": "uint56" }, { "internalType": "uint128", "name": "minPrice_", "type": "uint128" }], "name": "setParams", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }] as const \ No newline at end of file diff --git a/lib/constants/abi/Gauge.ts b/lib/constants/abi/Gauge.ts new file mode 100644 index 0000000..e19da76 --- /dev/null +++ b/lib/constants/abi/Gauge.ts @@ -0,0 +1 @@ +export const GaugeAbi = [{ "name": "Deposit", "inputs": [{ "name": "provider", "type": "address", "indexed": true }, { "name": "value", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "Withdraw", "inputs": [{ "name": "provider", "type": "address", "indexed": true }, { "name": "value", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "UpdateLiquidityLimit", "inputs": [{ "name": "user", "type": "address", "indexed": true }, { "name": "original_balance", "type": "uint256", "indexed": false }, { "name": "original_supply", "type": "uint256", "indexed": false }, { "name": "working_balance", "type": "uint256", "indexed": false }, { "name": "working_supply", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "Transfer", "inputs": [{ "name": "_from", "type": "address", "indexed": true }, { "name": "_to", "type": "address", "indexed": true }, { "name": "_value", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "Approval", "inputs": [{ "name": "_owner", "type": "address", "indexed": true }, { "name": "_spender", "type": "address", "indexed": true }, { "name": "_value", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "RewardDistributorUpdated", "inputs": [{ "name": "reward_token", "type": "address", "indexed": true }, { "name": "distributor", "type": "address", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "RelativeWeightCapChanged", "inputs": [{ "name": "new_relative_weight_cap", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewPendingAdmin", "inputs": [{ "name": "new_pending_admin", "type": "address", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewAdmin", "inputs": [{ "name": "new_admin", "type": "address", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewTokenlessProduction", "inputs": [{ "name": "new_tokenless_production", "type": "uint8", "indexed": false }], "anonymous": false, "type": "event" }, { "stateMutability": "nonpayable", "type": "constructor", "inputs": [{ "name": "minter", "type": "address" }, { "name": "delegation_proxy", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "deposit", "inputs": [{ "name": "_value", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "deposit", "inputs": [{ "name": "_value", "type": "uint256" }, { "name": "_addr", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "deposit", "inputs": [{ "name": "_value", "type": "uint256" }, { "name": "_addr", "type": "address" }, { "name": "_claim_rewards", "type": "bool" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "withdraw", "inputs": [{ "name": "_value", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "withdraw", "inputs": [{ "name": "_value", "type": "uint256" }, { "name": "_claim_rewards", "type": "bool" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "claim_rewards", "inputs": [], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "claim_rewards", "inputs": [{ "name": "_addr", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "claim_rewards", "inputs": [{ "name": "_addr", "type": "address" }, { "name": "_receiver", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "transferFrom", "inputs": [{ "name": "_from", "type": "address" }, { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" }], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "transfer", "inputs": [{ "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" }], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "approve", "inputs": [{ "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" }], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "permit", "inputs": [{ "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" }, { "name": "_deadline", "type": "uint256" }, { "name": "_v", "type": "uint8" }, { "name": "_r", "type": "bytes32" }, { "name": "_s", "type": "bytes32" }], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "increaseAllowance", "inputs": [{ "name": "_spender", "type": "address" }, { "name": "_added_value", "type": "uint256" }], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "decreaseAllowance", "inputs": [{ "name": "_spender", "type": "address" }, { "name": "_subtracted_value", "type": "uint256" }], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "user_checkpoint", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "set_rewards_receiver", "inputs": [{ "name": "_receiver", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "kick", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "deposit_reward_token", "inputs": [{ "name": "_reward_token", "type": "address" }, { "name": "_amount", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "add_reward", "inputs": [{ "name": "_reward_token", "type": "address" }, { "name": "_distributor", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "set_reward_distributor", "inputs": [{ "name": "_reward_token", "type": "address" }, { "name": "_distributor", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "killGauge", "inputs": [], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "unkillGauge", "inputs": [], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "change_pending_admin", "inputs": [{ "name": "new_pending_admin", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "claim_admin", "inputs": [], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "set_tokenless_production", "inputs": [{ "name": "new_tokenless_production", "type": "uint8" }], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "claimed_reward", "inputs": [{ "name": "_addr", "type": "address" }, { "name": "_token", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "claimable_reward", "inputs": [{ "name": "_user", "type": "address" }, { "name": "_reward_token", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "claimable_tokens", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "integrate_checkpoint", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "future_epoch_time", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "inflation_rate", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "version", "inputs": [], "outputs": [{ "name": "", "type": "string" }] }, { "stateMutability": "view", "type": "function", "name": "allowance", "inputs": [{ "name": "owner", "type": "address" }, { "name": "spender", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "is_killed", "inputs": [], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "initialize", "inputs": [{ "name": "_lp_token", "type": "address" }, { "name": "relative_weight_cap", "type": "uint256" }, { "name": "_admin", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "setRelativeWeightCap", "inputs": [{ "name": "relative_weight_cap", "type": "uint256" }], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "getRelativeWeightCap", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "getCappedRelativeWeight", "inputs": [{ "name": "time", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "pure", "type": "function", "name": "getMaxRelativeWeightCap", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "tokenless_production", "inputs": [], "outputs": [{ "name": "", "type": "uint8" }] }, { "stateMutability": "view", "type": "function", "name": "pending_admin", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "admin", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "balanceOf", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "totalSupply", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "name", "inputs": [], "outputs": [{ "name": "", "type": "string" }] }, { "stateMutability": "view", "type": "function", "name": "symbol", "inputs": [], "outputs": [{ "name": "", "type": "string" }] }, { "stateMutability": "view", "type": "function", "name": "DOMAIN_SEPARATOR", "inputs": [], "outputs": [{ "name": "", "type": "bytes32" }] }, { "stateMutability": "view", "type": "function", "name": "nonces", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "lp_token", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "gauge_state", "inputs": [], "outputs": [{ "name": "", "type": "uint8" }] }, { "stateMutability": "view", "type": "function", "name": "decimals", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "reward_count", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "reward_data", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "tuple", "components": [{ "name": "token", "type": "address" }, { "name": "distributor", "type": "address" }, { "name": "period_finish", "type": "uint256" }, { "name": "rate", "type": "uint256" }, { "name": "last_update", "type": "uint256" }, { "name": "integral", "type": "uint256" }] }] }, { "stateMutability": "view", "type": "function", "name": "rewards_receiver", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "reward_integral_for", "inputs": [{ "name": "arg0", "type": "address" }, { "name": "arg1", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "working_balances", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "working_supply", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "integrate_inv_supply_of", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "integrate_checkpoint_of", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "integrate_fraction", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "period", "inputs": [], "outputs": [{ "name": "", "type": "int128" }] }, { "stateMutability": "view", "type": "function", "name": "reward_tokens", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "period_timestamp", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "integrate_inv_supply", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }] as const; \ No newline at end of file diff --git a/lib/constants/abi/GaugeController.ts b/lib/constants/abi/GaugeController.ts new file mode 100644 index 0000000..587ee6b --- /dev/null +++ b/lib/constants/abi/GaugeController.ts @@ -0,0 +1 @@ +export const GaugeControllerAbi = [{ "name": "AddType", "inputs": [{ "name": "name", "type": "string", "indexed": false }, { "name": "type_id", "type": "int128", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewTypeWeight", "inputs": [{ "name": "type_id", "type": "int128", "indexed": false }, { "name": "time", "type": "uint256", "indexed": false }, { "name": "weight", "type": "uint256", "indexed": false }, { "name": "total_weight", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewGaugeWeight", "inputs": [{ "name": "gauge_address", "type": "address", "indexed": false }, { "name": "time", "type": "uint256", "indexed": false }, { "name": "weight", "type": "uint256", "indexed": false }, { "name": "total_weight", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "VoteForGauge", "inputs": [{ "name": "time", "type": "uint256", "indexed": false }, { "name": "user", "type": "address", "indexed": false }, { "name": "gauge_addr", "type": "address", "indexed": false }, { "name": "weight", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewGauge", "inputs": [{ "name": "addr", "type": "address", "indexed": false }, { "name": "gauge_type", "type": "int128", "indexed": false }, { "name": "weight", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewPendingAdmin", "inputs": [{ "name": "new_pending_admin", "type": "address", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewAdmin", "inputs": [{ "name": "new_admin", "type": "address", "indexed": false }], "anonymous": false, "type": "event" }, { "stateMutability": "nonpayable", "type": "constructor", "inputs": [{ "name": "_voting_escrow", "type": "address" }, { "name": "_admin", "type": "address" }], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "token", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "voting_escrow", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "gauge_exists", "inputs": [{ "name": "_addr", "type": "address" }], "outputs": [{ "name": "", "type": "bool" }] }, { "stateMutability": "view", "type": "function", "name": "gauge_types", "inputs": [{ "name": "_addr", "type": "address" }], "outputs": [{ "name": "", "type": "int128" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "add_gauge", "inputs": [{ "name": "addr", "type": "address" }, { "name": "gauge_type", "type": "int128" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "add_gauge", "inputs": [{ "name": "addr", "type": "address" }, { "name": "gauge_type", "type": "int128" }, { "name": "weight", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "checkpoint", "inputs": [], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "checkpoint_gauge", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "gauge_relative_weight", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "gauge_relative_weight", "inputs": [{ "name": "addr", "type": "address" }, { "name": "time", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "gauge_relative_weight_write", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "gauge_relative_weight_write", "inputs": [{ "name": "addr", "type": "address" }, { "name": "time", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "add_type", "inputs": [{ "name": "_name", "type": "string" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "add_type", "inputs": [{ "name": "_name", "type": "string" }, { "name": "weight", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "change_type_weight", "inputs": [{ "name": "type_id", "type": "int128" }, { "name": "weight", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "change_gauge_weight", "inputs": [{ "name": "addr", "type": "address" }, { "name": "weight", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "vote_for_many_gauge_weights", "inputs": [{ "name": "_gauge_addrs", "type": "address[8]" }, { "name": "_user_weight", "type": "uint256[8]" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "vote_for_gauge_weights", "inputs": [{ "name": "_gauge_addr", "type": "address" }, { "name": "_user_weight", "type": "uint256" }], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "get_gauge_weight", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "get_type_weight", "inputs": [{ "name": "type_id", "type": "int128" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "get_total_weight", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "get_weights_sum_per_type", "inputs": [{ "name": "type_id", "type": "int128" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "change_pending_admin", "inputs": [{ "name": "new_pending_admin", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "claim_admin", "inputs": [], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "pending_admin", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "admin", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "n_gauge_types", "inputs": [], "outputs": [{ "name": "", "type": "int128" }] }, { "stateMutability": "view", "type": "function", "name": "n_gauges", "inputs": [], "outputs": [{ "name": "", "type": "int128" }] }, { "stateMutability": "view", "type": "function", "name": "gauge_type_names", "inputs": [{ "name": "arg0", "type": "int128" }], "outputs": [{ "name": "", "type": "string" }] }, { "stateMutability": "view", "type": "function", "name": "gauges", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "vote_user_slopes", "inputs": [{ "name": "arg0", "type": "address" }, { "name": "arg1", "type": "address" }], "outputs": [{ "name": "", "type": "tuple", "components": [{ "name": "slope", "type": "uint256" }, { "name": "power", "type": "uint256" }, { "name": "end", "type": "uint256" }] }] }, { "stateMutability": "view", "type": "function", "name": "vote_user_power", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "last_user_vote", "inputs": [{ "name": "arg0", "type": "address" }, { "name": "arg1", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "points_weight", "inputs": [{ "name": "arg0", "type": "address" }, { "name": "arg1", "type": "uint256" }], "outputs": [{ "name": "", "type": "tuple", "components": [{ "name": "bias", "type": "uint256" }, { "name": "slope", "type": "uint256" }] }] }, { "stateMutability": "view", "type": "function", "name": "time_weight", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "points_sum", "inputs": [{ "name": "arg0", "type": "int128" }, { "name": "arg1", "type": "uint256" }], "outputs": [{ "name": "", "type": "tuple", "components": [{ "name": "bias", "type": "uint256" }, { "name": "slope", "type": "uint256" }] }] }, { "stateMutability": "view", "type": "function", "name": "time_sum", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "points_total", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "time_total", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "points_type_weight", "inputs": [{ "name": "arg0", "type": "int128" }, { "name": "arg1", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "time_type_weight", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }] as const; \ No newline at end of file diff --git a/lib/constants/abi/Minter.ts b/lib/constants/abi/Minter.ts new file mode 100644 index 0000000..92dd3d0 --- /dev/null +++ b/lib/constants/abi/Minter.ts @@ -0,0 +1 @@ +export const MinterAbi = [{ "inputs": [{ "internalType": "contract ITokenAdmin", "name": "tokenAdmin", "type": "address" }, { "internalType": "contract IGaugeController", "name": "gaugeController", "type": "address" }], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "recipient", "type": "address" }, { "indexed": false, "internalType": "address", "name": "gauge", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "minted", "type": "uint256" }], "name": "Minted", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "user", "type": "address" }, { "indexed": true, "internalType": "address", "name": "minter", "type": "address" }, { "indexed": false, "internalType": "bool", "name": "approval", "type": "bool" }], "name": "MinterApprovalSet", "type": "event" }, { "inputs": [{ "internalType": "address", "name": "minter", "type": "address" }, { "internalType": "address", "name": "user", "type": "address" }], "name": "allowed_to_mint_for", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getGaugeController", "outputs": [{ "internalType": "contract IGaugeController", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "minter", "type": "address" }, { "internalType": "address", "name": "user", "type": "address" }], "name": "getMinterApproval", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getToken", "outputs": [{ "internalType": "contract IERC20", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getTokenAdmin", "outputs": [{ "internalType": "contract ITokenAdmin", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "gauge", "type": "address" }], "name": "mint", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "gauge", "type": "address" }, { "internalType": "address", "name": "user", "type": "address" }], "name": "mintFor", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address[]", "name": "gauges", "type": "address[]" }], "name": "mintMany", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address[]", "name": "gauges", "type": "address[]" }, { "internalType": "address", "name": "user", "type": "address" }], "name": "mintManyFor", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "gauge", "type": "address" }, { "internalType": "address", "name": "user", "type": "address" }], "name": "mint_for", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address[8]", "name": "gauges", "type": "address[8]" }], "name": "mint_many", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "user", "type": "address" }, { "internalType": "address", "name": "gauge", "type": "address" }], "name": "minted", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "minter", "type": "address" }, { "internalType": "bool", "name": "approval", "type": "bool" }], "name": "setMinterApproval", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "minter", "type": "address" }], "name": "toggle_approve_mint", "outputs": [], "stateMutability": "nonpayable", "type": "function" }] as const \ No newline at end of file diff --git a/lib/constants/abi/OPop.ts b/lib/constants/abi/OPop.ts new file mode 100644 index 0000000..e62cc36 --- /dev/null +++ b/lib/constants/abi/OPop.ts @@ -0,0 +1 @@ +export const OPopAbi = [{ "inputs": [{ "internalType": "string", "name": "name_", "type": "string" }, { "internalType": "string", "name": "symbol_", "type": "string" }, { "internalType": "address", "name": "owner_", "type": "address" }, { "internalType": "address", "name": "tokenAdmin_", "type": "address" }, { "internalType": "contract ERC20", "name": "paymentToken_", "type": "address" }, { "internalType": "contract ERC20", "name": "underlyingToken_", "type": "address" }, { "internalType": "contract IOracle", "name": "oracle_", "type": "address" }, { "internalType": "address", "name": "treasury_", "type": "address" }], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [], "name": "OptionsToken__NotTokenAdmin", "type": "error" }, { "inputs": [], "name": "OptionsToken__PastDeadline", "type": "error" }, { "inputs": [], "name": "OptionsToken__SlippageTooHigh", "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": "amount", "type": "uint256" }], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, { "indexed": true, "internalType": "address", "name": "recipient", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "paymentAmount", "type": "uint256" }], "name": "Exercise", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "user", "type": "address" }, { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" }], "name": "OwnershipTransferred", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "contract IOracle", "name": "newOracle", "type": "address" }], "name": "SetOracle", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "newTreasury", "type": "address" }], "name": "SetTreasury", "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": "amount", "type": "uint256" }], "name": "Transfer", "type": "event" }, { "inputs": [], "name": "DOMAIN_SEPARATOR", "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "", "type": "address" }, { "internalType": "address", "name": "", "type": "address" }], "name": "allowance", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }], "name": "approve", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "", "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": "uint256", "name": "amount", "type": "uint256" }, { "internalType": "uint256", "name": "maxPaymentAmount", "type": "uint256" }, { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }], "name": "exercise", "outputs": [{ "internalType": "uint256", "name": "paymentAmount", "type": "uint256" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "amount", "type": "uint256" }, { "internalType": "uint256", "name": "maxPaymentAmount", "type": "uint256" }, { "internalType": "address", "name": "recipient", "type": "address" }], "name": "exercise", "outputs": [{ "internalType": "uint256", "name": "paymentAmount", "type": "uint256" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }], "name": "mint", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "name", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "", "type": "address" }], "name": "nonces", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "oracle", "outputs": [{ "internalType": "contract IOracle", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "paymentToken", "outputs": [{ "internalType": "contract ERC20", "name": "", "type": "address" }], "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": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "contract IOracle", "name": "oracle_", "type": "address" }], "name": "setOracle", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "treasury_", "type": "address" }], "name": "setTreasury", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "symbol", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "tokenAdmin", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "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": "amount", "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": "amount", "type": "uint256" }], "name": "transferFrom", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "treasury", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "underlyingToken", "outputs": [{ "internalType": "contract ERC20", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }] as const; \ No newline at end of file diff --git a/lib/constants/abi/USDT.ts b/lib/constants/abi/USDT.ts new file mode 100644 index 0000000..f5faf25 --- /dev/null +++ b/lib/constants/abi/USDT.ts @@ -0,0 +1,282 @@ +export const UsdtAbi = [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": [ + { + "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": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "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": "subtractedValue", + "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": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "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": "amount", + "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": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] as const \ No newline at end of file diff --git a/lib/constants/abi/VCX.ts b/lib/constants/abi/VCX.ts new file mode 100644 index 0000000..4b3d28b --- /dev/null +++ b/lib/constants/abi/VCX.ts @@ -0,0 +1,448 @@ +export const VCXAbi = [ + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "popAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vcxAmount", + "type": "uint256" + } + ], + "name": "Migrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "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": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTs", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTs", + "type": "uint256" + } + ], + "name": "UpdatedEndOfMigrationTs", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "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": [], + "name": "endOfMigrationTs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ts", + "type": "uint256" + } + ], + "name": "setEndOfMigrationTs", + "outputs": [], + "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": "amount", + "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": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] as const \ No newline at end of file diff --git a/lib/constants/abi/VotingEscrow.ts b/lib/constants/abi/VotingEscrow.ts new file mode 100644 index 0000000..21ebab8 --- /dev/null +++ b/lib/constants/abi/VotingEscrow.ts @@ -0,0 +1 @@ +export const VotingEscrowAbi = [{ "name": "Deposit", "inputs": [{ "name": "provider", "type": "address", "indexed": true }, { "name": "value", "type": "uint256", "indexed": false }, { "name": "locktime", "type": "uint256", "indexed": true }, { "name": "type", "type": "int128", "indexed": false }, { "name": "ts", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "Withdraw", "inputs": [{ "name": "provider", "type": "address", "indexed": true }, { "name": "value", "type": "uint256", "indexed": false }, { "name": "ts", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "Penalty", "inputs": [{ "name": "provider", "type": "address", "indexed": true }, { "name": "value", "type": "uint256", "indexed": false }, { "name": "ts", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "Supply", "inputs": [{ "name": "prevSupply", "type": "uint256", "indexed": false }, { "name": "supply", "type": "uint256", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewPendingAdmin", "inputs": [{ "name": "new_pending_admin", "type": "address", "indexed": false }], "anonymous": false, "type": "event" }, { "name": "NewAdmin", "inputs": [{ "name": "new_admin", "type": "address", "indexed": false }], "anonymous": false, "type": "event" }, { "stateMutability": "nonpayable", "type": "constructor", "inputs": [{ "name": "token_addr", "type": "address" }, { "name": "_name", "type": "string" }, { "name": "_symbol", "type": "string" }, { "name": "_admin", "type": "address" }], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "token", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "name", "inputs": [], "outputs": [{ "name": "", "type": "string" }] }, { "stateMutability": "view", "type": "function", "name": "symbol", "inputs": [], "outputs": [{ "name": "", "type": "string" }] }, { "stateMutability": "view", "type": "function", "name": "decimals", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "commit_smart_wallet_checker", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "apply_smart_wallet_checker", "inputs": [], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "get_last_user_slope", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [{ "name": "", "type": "int128" }] }, { "stateMutability": "view", "type": "function", "name": "user_point_history__ts", "inputs": [{ "name": "_addr", "type": "address" }, { "name": "_idx", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "locked__end", "inputs": [{ "name": "_addr", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "checkpoint", "inputs": [], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "deposit_for", "inputs": [{ "name": "_addr", "type": "address" }, { "name": "_value", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "create_lock", "inputs": [{ "name": "_value", "type": "uint256" }, { "name": "_unlock_time", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "increase_amount", "inputs": [{ "name": "_value", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "increase_unlock_time", "inputs": [{ "name": "_unlock_time", "type": "uint256" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "withdraw", "inputs": [], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "balanceOf", "inputs": [{ "name": "addr", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "balanceOf", "inputs": [{ "name": "addr", "type": "address" }, { "name": "_t", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "balanceOfAt", "inputs": [{ "name": "addr", "type": "address" }, { "name": "_block", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "totalSupply", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "totalSupply", "inputs": [{ "name": "t", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "totalSupplyAt", "inputs": [{ "name": "_block", "type": "uint256" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "nonpayable", "type": "function", "name": "change_pending_admin", "inputs": [{ "name": "new_pending_admin", "type": "address" }], "outputs": [] }, { "stateMutability": "nonpayable", "type": "function", "name": "claim_admin", "inputs": [], "outputs": [] }, { "stateMutability": "view", "type": "function", "name": "pending_admin", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "admin", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "supply", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "locked", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "tuple", "components": [{ "name": "amount", "type": "int128" }, { "name": "end", "type": "uint256" }] }] }, { "stateMutability": "view", "type": "function", "name": "epoch", "inputs": [], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "point_history", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "tuple", "components": [{ "name": "bias", "type": "int128" }, { "name": "slope", "type": "int128" }, { "name": "ts", "type": "uint256" }, { "name": "blk", "type": "uint256" }] }] }, { "stateMutability": "view", "type": "function", "name": "user_point_history", "inputs": [{ "name": "arg0", "type": "address" }, { "name": "arg1", "type": "uint256" }], "outputs": [{ "name": "", "type": "tuple", "components": [{ "name": "bias", "type": "int128" }, { "name": "slope", "type": "int128" }, { "name": "ts", "type": "uint256" }, { "name": "blk", "type": "uint256" }] }] }, { "stateMutability": "view", "type": "function", "name": "user_point_epoch", "inputs": [{ "name": "arg0", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "stateMutability": "view", "type": "function", "name": "slope_changes", "inputs": [{ "name": "arg0", "type": "uint256" }], "outputs": [{ "name": "", "type": "int128" }] }, { "stateMutability": "view", "type": "function", "name": "future_smart_wallet_checker", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }, { "stateMutability": "view", "type": "function", "name": "smart_wallet_checker", "inputs": [], "outputs": [{ "name": "", "type": "address" }] }] as const; \ No newline at end of file diff --git a/lib/constants/abi/index.ts b/lib/constants/abi/index.ts index 34c65c3..5c4d900 100644 --- a/lib/constants/abi/index.ts +++ b/lib/constants/abi/index.ts @@ -1,3 +1,10 @@ export * from "./ERC20"; export * from "./Vault"; -export * from "./VaultRegistry"; \ No newline at end of file +export * from "./VaultRegistry"; +export * from "./GaugeController"; +export * from "./Gauge"; +export * from "./VotingEscrow"; +export * from "./BalancerOracle"; +export * from "./OPop"; +export * from "./Minter"; +export * from "./VCX"; \ No newline at end of file diff --git a/lib/constants/assets.ts b/lib/constants/assets.ts index 079d65d..75c94f7 100644 --- a/lib/constants/assets.ts +++ b/lib/constants/assets.ts @@ -1,11 +1,12 @@ -import { TokenConstant } from "../types"; +import { Asset } from "@/lib/types"; -const assets: TokenConstant[] = [ +const assets: Asset[] = [ { - "chains": [1, 1337, 42161], + "chains": [1, 1337, 10, 42161], "address": { "1": "0x6B175474E89094C44Da98b954EedeAC495271d0F", "1337": "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "10": "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", "42161": "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1" }, "name": "Dai Stablecoin", @@ -14,11 +15,12 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/DAI.png" }, { - "chains": [1, 1337, 42161, 137], + "chains": [1, 1337, 10, 42161, 137], "address": { "1": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "1337": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "42161": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", + "10": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", "137": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" }, "name": "USD Coin", @@ -27,10 +29,21 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/USDC.png" }, { - "chains": [1, 1337, 42161], + "chains": [10], + "address": { + "10": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", + }, + "name": "USD Coin Bridged", + "symbol": "USDC.e", + "decimals": 6, + "logoURI": "https://cdn.furucombo.app/assets/img/token/USDC.png" + }, + { + "chains": [1, 1337, 10, 42161], "address": { "1": "0xdAC17F958D2ee523a2206206994597C13D831ec7", "1337": "0xdAC17F958D2ee523a2206206994597C13D831ec7", + "10": "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58", "42161": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8" }, "name": "Tether USD", @@ -51,19 +64,20 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/FRAX.png" }, { - "chains": [1, 1337, 42161], + "chains": [1, 1337, 10, 42161], "address": { "1": "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0", "1337": "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0", + "10": "0xc40F949F8a4e094D1b49a23ea9241D289B7b2819", "42161": "0x93b346b6BC2548dA6A1E7d98E9a421B42541425b" }, - "name": "LUSD Stablecoin", + "name": "LUSD", "symbol": "LUSD", "decimals": 18, "logoURI": "https://cdn.furucombo.app/assets/img/token/LUSD.png" }, { - "chains": [1], + "chains": [], "address": { "1": "0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3", "1337": "0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3", @@ -75,21 +89,11 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/MIM.png" }, { - "chains": [1, 1337], - "address": { - "1": "0x57Ab1ec28D129707052df4dF418D58a2D46d5f51", - "1337": "0x57Ab1ec28D129707052df4dF418D58a2D46d5f51" - }, - "name": "Synth USD", - "symbol": "sUSD", - "decimals": 18, - "logoURI": "https://etherscan.io/token/images/SynthetixsUSD_32.png" - }, - { - "chains": [1, 1337, 42161], + "chains": [1, 1337, 10, 42161], "address": { "1": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", "1337": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + "10": "0x68f180fcCe6836688e9084f035309E29Bf0A2095", "42161": "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f" }, "name": "Wrapped BTC", @@ -98,10 +102,11 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/WBTC.png" }, { - "chains": [1, 1337, 42161], + "chains": [1, 1337, 10, 42161], "address": { "1": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "1337": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "10": "0x4200000000000000000000000000000000000006", "42161": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" }, "name": "Wrapped Ether", @@ -110,18 +115,18 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/WETH.svg" }, { - "chains": [1, 1337], + "chains": [], "address": { - "1": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", - "1337": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84" + "1": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", + "1337": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0" }, - "name": "Staked Ether", - "symbol": "stETH", + "name": "Matic Token", + "symbol": "MATIC", "decimals": 18, - "logoURI": "https://cdn.furucombo.app/assets/img/token/stETH.svg" + "logoURI": "https://cdn.furucombo.app/assets/img/token/MATIC.png" }, { - "chains": [1], + "chains": [], "address": { "1": "0x383518188C0C6d7730D91b2c03a03C837814a899", "1337": "0x383518188C0C6d7730D91b2c03a03C837814a899" @@ -131,50 +136,6 @@ const assets: TokenConstant[] = [ "decimals": 9, "logoURI": "https://cdn.furucombo.app/assets/img/token/OHM.png" }, - { - "chains": [1, 1337], - "address": { - "1": "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86", - "1337": "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86" - }, - "name": "Origin Dollar", - "symbol": "oUSD", - "decimals": 18, - "logoURI": "https://icons.llamao.fi/icons/protocols/origin-dollar" - }, - { - "chains": [1, 1337], - "address": { - "1": "0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3", - "1337": "0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3" - }, - "name": "Origin Ether", - "symbol": "oETH", - "decimals": 18, - "logoURI": "https://icons.llamao.fi/icons/protocols/origin-ether" - }, - { - "chains": [1, 1337], - "address": { - "1": "0xD533a949740bb3306d119CC777fa900bA034cd52", - "1337": "0xD533a949740bb3306d119CC777fa900bA034cd52" - }, - "name": "Curve", - "symbol": "CRV", - "decimals": 18, - "logoURI": "https://etherscan.io/token/images/Curvefi_32.png" - }, - { - "chains": [1, 1337], - "address": { - "1": "0xba100000625a3754423978a60c9317c58a424e3D", - "1337": "0xba100000625a3754423978a60c9317c58a424e3D" - }, - "name": "Balancer", - "symbol": "BAL", - "decimals": 18, - "logoURI": "https://etherscan.io/token/images/Balancer_32.png" - }, { "chains": [1, 1337], "address": { @@ -211,7 +172,7 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/USDT.png" }, { - "chains": [1], + "chains": [], "address": { "1": "0xfA0F307783AC21C39E939ACFF795e27b650F6e68", "1337": "0xfA0F307783AC21C39E939ACFF795e27b650F6e68", @@ -223,7 +184,7 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/FRAX.png" }, { - "chains": [1], + "chains": [], "address": { "1": "0xE8F55368C82D38bbbbDb5533e7F56AfC2E978CC2", "1337": "0xE8F55368C82D38bbbbDb5533e7F56AfC2E978CC2", @@ -235,7 +196,7 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/LUSD.png" }, { - "chains": [], + "chains": [42161], "address": { "42161": "0x68f5d998F00bB2460511021741D098c05721d8fF" }, @@ -245,7 +206,7 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/DAI.png" }, { - "chains": [], + "chains": [42161], "address": { "42161": "0xB67c014FA700E69681a673876eb8BAFAA36BFf71" }, @@ -276,15 +237,58 @@ const assets: TokenConstant[] = [ "logoURI": "https://cdn.furucombo.app/assets/img/token/WETH.svg" }, { - "chains": [], + "chains": [1, 1337], + "address": { + "1": "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86", + "1337": "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86" + }, + "name": "Origin Dollar", + "symbol": "oUSD", + "decimals": 18, + "logoURI": "https://icons.llamao.fi/icons/protocols/origin-dollar" + }, + { + "chains": [1, 1337], "address": { - "1": "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0", - "1337": "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0" + "1": "0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3", + "1337": "0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3" }, - "name": "Matic", + "name": "Origin Ether", "symbol": "oETH", "decimals": 18, - "logoURI": "https://icons.llamao.fi/icons/chains/rsz_polygon" + "logoURI": "/images/tokens/oEth.png" + }, + { + "chains": [1, 1337], + "address": { + "1": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", + "1337": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84" + }, + "name": "Staked Ether", + "symbol": "stETH", + "decimals": 18, + "logoURI": "https://cdn.furucombo.app/assets/img/token/stETH.svg" + }, + { + "chains": [1, 1337], + "address": { + "1": "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", + "1337": "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0" + }, + "name": "Wrapped Staked Ether", + "symbol": "wstETH", + "decimals": 18, + "logoURI": "https://cdn.furucombo.app/assets/img/token/stETH.svg" + }, + { + "chains": [1], + "address": { + "1": "0x514910771AF9Ca656af840dff83E8264EcF986CA" + }, + "name": "Chainlink", + "symbol": "LINK", + "decimals": 18, + "logoURI": "https://etherscan.io/token/images/chainlinktoken_32.png?v=6" }, { "chains": [1, 1337], @@ -292,10 +296,328 @@ const assets: TokenConstant[] = [ "1": "0x76FCf0e8C7Ff37A47a799FA2cd4c13cDe0D981C9", "1337": "0x76FCf0e8C7Ff37A47a799FA2cd4c13cDe0D981C9" }, - "name": "OHM / DAI LP ", + "name": "OHM / DAI LP", "symbol": "b-ohm-dai-lp", "decimals": 18, "logoURI": "https://cdn.furucombo.app/assets/img/token/OHM.png" + }, + { + "chains": [1, 1337], + "address": { + "1": "0xFCc5c47bE19d06BF83eB04298b026F81069ff65b", + "1337": "0xFCc5c47bE19d06BF83eB04298b026F81069ff65b" + }, + "name": "yCRV", + "symbol": "yCRV", + "decimals": 18, + "logoURI": "https://etherscan.io/token/images/yearncrvnew_32.png" + }, + { + "chains": [1], + "address": { + "1": "0x3175df0976dfa876431c2e9ee6bc45b65d3473cc" + }, + "name": "FRAX / USDC LP", + "symbol": "crvFRAX", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, { + "chains": [1], + "address": { + "1": "0x06325440d014e39736583c165c2963ba99faf14e" + }, + "name": "ETH / stETH LP", + "symbol": "steCRV", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, { + "chains": [1], + "address": { + "1": "0x6c3f90f043a72fa612cbac8115ee7e52bde6e490" + }, + "name": "3Pool", + "symbol": "3CRV", + "decimals": 18, + "logoURI": "https://etherscan.io/token/images/3pool_32.png" + }, { + "chains": [1], + "address": { + "1": "0xf43211935c781d5ca1a41d2041f397b8a7366c7a" + }, + "name": "ETH / frxETH LP ", + "symbol": "crvFrxETH", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0xc4ad29ba4b3c580e6d59105fff484999997675ff" + }, + "name": "TryCripto2", + "symbol": "crv3crypto", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x94b17476a93b3262d87b9a326965d1e91f9c13e7" + }, + "name": "ETH / OETH LP", + "symbol": "crvOETH", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x21e27a5e5513d6e65c4f830167390997aa84843a" + }, + "name": "stETH-ng", + "symbol": "crvStETH-ng", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0xb30da2376f63de30b42dc055c93fa474f31330a5" + }, + "name": "alUSDFRAXBP", + "symbol": "alUSD FRAX USDC", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x4dece678ceceb27446b35c672dc7d61f30bad69e" + }, + "name": "crvUSD/USDC", + "symbol": "USDC crvUSD", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x390f3595bca2df7d23783dfd126427cceb997bf4" + }, + "name": "crvUSD/USDT", + "symbol": "USDT crvUSD", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0xf5f5b97624542d72a9e06f04804bf81baa15e2b4" + }, + "name": "TricryptoUSDT", + "symbol": "USDT WBTC ETH", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x7f86bf177dd4f3494b841a37e810a34dd56c829b" + }, + "name": "TricryptoUSDC", + "symbol": "USDC WBTC ETH", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x971add32ea87f10bd192671630be3be8a11b8623" + }, + "name": "cvxCrv/Crv", + "symbol": "CRV cvxCRV", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x4704ab1fb693ce163f7c9d3a31b3ff4eaf797714" + }, + "name": "FPI2Pool", + "symbol": "FRAX FPI", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x5a6a4d54456819380173272a5e8e9b9904bdf41b" + }, + "name": "mim", + "symbol": "MIM DAI USDC USDT", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0xc9c32cd16bf7efb85ff14e0c8603cc90f6f2ee49" + }, + "name": "Bean", + "symbol": "BEAN DAI USDC USDT", + "decimals": 18, + "logoURI": "https://etherscan.io/token/images/bean3crv_32.png" + }, + { + "chains": [1], + "address": { + "1": "0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca" + }, + "name": "lusd", + "symbol": "LUSD DAI USDC USDT", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0xc25a3a3b969415c80451098fa907ec722572917f" + }, + "name": "susd", + "symbol": "DAI USDC USDT sUSD", + "decimals": 18, + "logoURI": "https://etherscan.io/token/images/Curvefi_sCrv_32.png" + }, + { + "chains": [1], + "address": { + "1": "0xfd2a8fa60abd58efe3eee34dd494cd491dc14900" + }, + "name": "aave", + "symbol": "DAI USDC USDT", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0xe57180685e3348589e9521aa53af0bcd497e884d" + }, + "name": "DOLA/FRAXBP", + "symbol": "DOLA FRAX USDC", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x43b4fdfd4ff969587185cdb6f0bd875c5fc83f8c" + }, + "name": "alusd", + "symbol": "alUSD DAI USDC USDT", + "decimals": 18, + "logoURI": "/images/tokens/curve-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x5c6Ee304399DBdB9C8Ef030aB642B10820DB8F56" + }, + "name": "Bal 80 Eth 20", + "symbol": "BAL WETH", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x1E19CF2D73a72Ef1332C882F20534B6519Be0276" + }, + "name": "rETH wETH", + "symbol": "rETH WETH", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x20a61B948E33879ce7F23e535CC7BAA3BC66c5a9" + }, + "name": "R DAI", + "symbol": "R DAI", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x42ED016F826165C2e5976fe5bC3df540C5aD0Af7" + }, + "name": "wstETH sfrxETH rETH", + "symbol": "wstETH sfrxETH rETH", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x1ee442b5326009Bb18F2F472d3e0061513d1A0fF" + }, + "name": "BADGER 50 rETH 50", + "symbol": "BADGER rETH", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x87a867f5D240a782d43D90b6B06DEa470F3f8F22" + }, + "name": "wstETH 50 COMP 50", + "symbol": "wstETH COMP", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x3ff3a210e57cFe679D9AD1e9bA6453A716C56a2e" + }, + "name": "USDC 50 STG 50", + "symbol": "USDC STG", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x3dd0843A028C86e0b760b1A76929d1C5Ef93a2dd" + }, + "name": "AuraBAL Stable Pool", + "symbol": "B-80BAL-20WETH auraBAL", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0xE7e2c68d3b13d905BBb636709cF4DfD21076b9D2" + }, + "name": "WETH swETH", + "symbol": "WETH swETH", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" + }, + { + "chains": [1], + "address": { + "1": "0x32296969Ef14EB0c6d29669C550D4a0449130230" + }, + "name": "wstETH WETH", + "symbol": "wstETH WETH", + "decimals": 18, + "logoURI": "/images/tokens/balancer-lp.png" } ] export default assets; \ No newline at end of file diff --git a/lib/constants/index.ts b/lib/constants/index.ts index 684db0c..575e6f3 100644 --- a/lib/constants/index.ts +++ b/lib/constants/index.ts @@ -1,7 +1,7 @@ export * from "./abi"; import assets from "@/lib/constants/assets"; import { Token } from "../types"; -import { Address } from "viem"; +import { Address, maxInt256, maxUint256, zeroAddress } from "viem"; export function getAssetsByChain(chainId: number): Token[] { return assets.filter((asset) => asset.chains.includes(chainId)).map((asset) => { @@ -11,6 +11,8 @@ export function getAssetsByChain(chainId: number): Token[] { symbol: asset.symbol, decimals: asset.decimals, logoURI: asset.logoURI, + balance: 0, + price: 0 } }); } @@ -32,8 +34,9 @@ export const PopStakingByChain: { [key: number]: Address } = { 10: "0x3Fcc4eA703054453D8697b58C5CB2585F8883C05" } -export const ADDRESS_ZERO: Address = "0x0000000000000000000000000000000000000000" -export const MAX_INT256 = BigInt(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) -export const MAX_UINT256 = BigInt(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +export const ADDRESS_ZERO = zeroAddress +export const MAX_INT256 = maxInt256 +export const MAX_UINT256 = maxUint256 export const MINUS_ONE = BigInt(-0x01) -export const ZERO = BigInt(0) \ No newline at end of file +export const ZERO = BigInt(0) +export const ROUNDING_VALUE = 10_000; \ No newline at end of file diff --git a/lib/feeDistributor/getClaimableVeReward.ts b/lib/feeDistributor/getClaimableVeReward.ts new file mode 100644 index 0000000..8dd1854 --- /dev/null +++ b/lib/feeDistributor/getClaimableVeReward.ts @@ -0,0 +1,108 @@ +import { Chain, createPublicClient, http } from 'viem'; +import { thisPeriodTimestamp } from '@/lib/gauges/utils'; +import { ZERO } from '@/lib/constants'; +import { RPC_URLS } from '@/lib/utils/connectors'; + +interface GetVeRewardsProps { + chain: Chain; + address: `0x${string}`; + user: `0x${string}`; + token: `0x${string}`; +}; + +export default async function getClaimableVeReward({ chain, address, user, token }: GetVeRewardsProps): Promise { + const timestamp = BigInt(String(thisPeriodTimestamp())); + + const client = createPublicClient({ chain, transport: http(RPC_URLS[chain.id]) }) + const data = await client.multicall({ + contracts: [ + { + address, + abi: abiFeeDistributor, + functionName: "getTotalSupplyAtTimestamp", + args: [timestamp] + }, + { + address, + abi: abiFeeDistributor, + functionName: "getUserBalanceAtTimestamp", + args: [user, timestamp] + }, + { + address, + abi: abiFeeDistributor, + functionName: "getTokensDistributedInWeek", + args: [token, timestamp] + }, + ], + allowFailure: false + }) + + if (Number(data[1]) && Number(data[2]) > 0 && Number(data[0]) > 0) { + return (data[1] * data[2]) / data[0]; + } + + return ZERO; +} + +const abiFeeDistributor = [ + { + "stateMutability": "view", + "type": "function", + "name": "getTokensDistributedInWeek", + "inputs": [ + { + "name": "token", + "type": "address" + }, + { + "name": "timestamp", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "getTotalSupplyAtTimestamp", + "inputs": [ + { + "name": "timestamp", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "getUserBalanceAtTimestamp", + "inputs": [ + { + "name": "user", + "type": "address" + }, + { + "name": "timestamp", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, +] as const \ No newline at end of file diff --git a/lib/feeDistributor/getVeApy.ts b/lib/feeDistributor/getVeApy.ts new file mode 100644 index 0000000..99a6a96 --- /dev/null +++ b/lib/feeDistributor/getVeApy.ts @@ -0,0 +1,107 @@ +import { Chain, createPublicClient, http } from "viem"; +import { llama } from "@/lib/resolver/price/resolver"; +import { thisPeriodTimestamp } from "@/lib/gauges/utils"; +import { RPC_URLS } from "@/lib/utils/connectors"; + +interface ClaimableTokensArgs { + chain: Chain; + address: `0x${string}`; + token: `0x${string}`; +} + +export default async function getVeApy({ chain, address, token }: ClaimableTokensArgs): Promise { + const popPriceUSD = await llama({ address: "0x6F0fecBC276de8fC69257065fE47C5a03d986394", chainId: 10 }) + const wethPriceUSD = await llama({ address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", chainId: 1 }) + const timestamp = BigInt(String(thisPeriodTimestamp() - 604800)); + + const client = createPublicClient({ chain, transport: http(RPC_URLS[chain.id]) }) + const data = await client.multicall({ + contracts: [ + { + address, + abi: abiFeeDistributor, + functionName: "getTotalSupplyAtTimestamp", + args: [timestamp] + }, + { + address, + abi: abiFeeDistributor, + functionName: "getTokensDistributedInWeek", + args: [token, timestamp] + }, + ], + allowFailure: false + }) + + if (Number(data[1]) > 0 && Number(data[0]) > 0) { + const rewardValue = Number(data[1]) * wethPriceUSD + const supplyValue = Number(data[0]) * popPriceUSD; + const apy = (rewardValue / supplyValue) * 52; + return apy; + } + + return 0; +}; + + +const abiFeeDistributor = [ + { + "stateMutability": "view", + "type": "function", + "name": "getTokensDistributedInWeek", + "inputs": [ + { + "name": "token", + "type": "address" + }, + { + "name": "timestamp", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "getTotalSupplyAtTimestamp", + "inputs": [ + { + "name": "timestamp", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "getUserBalanceAtTimestamp", + "inputs": [ + { + "name": "user", + "type": "address" + }, + { + "name": "timestamp", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, +] as const \ No newline at end of file diff --git a/lib/feeDistributor/useClaimToken.ts b/lib/feeDistributor/useClaimToken.ts new file mode 100644 index 0000000..68dfcc0 --- /dev/null +++ b/lib/feeDistributor/useClaimToken.ts @@ -0,0 +1,22 @@ +import { showErrorToast, showSuccessToast } from "lib/toasts"; +import { useContractWrite, usePrepareContractWrite } from "wagmi"; + +export function useClaimTokens(address: `0x${string}`, user: `0x${string}`, tokens: string[]) { + const { config } = usePrepareContractWrite({ + address, + abi: ["function claimTokens(address user, address[] calldata tokens) external"], + functionName: "claimTokens", + args: [user, tokens], + chainId: Number(5), + }); + + return useContractWrite({ + ...config, + onSuccess: () => { + showSuccessToast("wETH Succesfully Claimed!"); + }, + onError: (error) => { + showErrorToast(error); + } + }); +} \ No newline at end of file diff --git a/lib/gauges/calculateGaugeAPR.ts b/lib/gauges/calculateGaugeAPR.ts new file mode 100644 index 0000000..86bbc5b --- /dev/null +++ b/lib/gauges/calculateGaugeAPR.ts @@ -0,0 +1,91 @@ +import { thisPeriodTimestamp } from "@/lib/gauges/utils"; +import { Address, PublicClient, formatEther } from "viem"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { llama } from "@/lib/resolver/price/resolver"; +import { GaugeAbi, GaugeControllerAbi } from "@/lib/constants"; + +const { GaugeController: GAUGE_CONTROLLER } = getVeAddresses() + + +async function getGaugeData(gauge: Address, publicClient: PublicClient): Promise<[boolean, number, number, number, number]> { + const gaugeContract = { + address: gauge, + abi: GaugeAbi + } + + const data = await publicClient.multicall({ + contracts: [ + { + ...gaugeContract, + functionName: 'is_killed', + }, + { + ...gaugeContract, + functionName: 'inflation_rate', + }, + { + ...gaugeContract, + functionName: 'getCappedRelativeWeight', + args: [BigInt(thisPeriodTimestamp())] + }, + { + ...gaugeContract, + functionName: 'tokenless_production', + }, + { + ...gaugeContract, + functionName: 'working_supply', + }, + ], + allowFailure: false + }) + + return [data[0], Number(formatEther(data[1])), Number(formatEther(data[2])), Number(data[3]), Number(formatEther(data[4]))]; +} + +interface CalculateAPRProps { + vaultPrice: number; + gauge: Address; + publicClient: PublicClient; +} + +export default async function calculateAPR({ vaultPrice, gauge, publicClient }: CalculateAPRProps): Promise { + /// fetch the price of token0, token1 and LIT in USD + const popPriceUSD = await llama({ address: "0x6F0fecBC276de8fC69257065fE47C5a03d986394", chainId: 10 }) + + /// calculate the lowerAPR and upperAPR + let lowerAPR = 0; + let upperAPR = 0; + + if (gauge) { + const [is_killed, inflation_rate, relative_weight, tokenless_production, working_supply] = await getGaugeData(gauge, publicClient); + const gauge_exists = await publicClient.readContract({ + address: GAUGE_CONTROLLER, + abi: GaugeControllerAbi, + functionName: 'gauge_exists', + args: [gauge] + }) + + /// @dev the price of oVCX is determined by applying the discount factor to the VCX price. + /// as of this writing, the discount factor of 50% but is subject to change. Additional dev + /// work is needed to programmatically apply the discount factor at any given point in time. + const oVcxPriceUSD = popPriceUSD * 0.5; + + if (gauge_exists == true && is_killed == false) { + const relative_inflation = inflation_rate * relative_weight; + if (relative_inflation > 0) { + const annualRewardUSD = relative_inflation * 86400 * 365 * oVcxPriceUSD; + const effectiveSupply = working_supply > 0 ? working_supply : 1; + const workingSupplyUSD = effectiveSupply * vaultPrice; + + lowerAPR = (((annualRewardUSD * tokenless_production) / 100) / workingSupplyUSD) * 100; + upperAPR = (annualRewardUSD / workingSupplyUSD) * 100; + } + } + } else { + console.log('~~~~~ No Gauge Found ~~~~~'); + return []; + } + + return [lowerAPR, upperAPR]; +} \ No newline at end of file diff --git a/lib/gauges/getGaugeRewards.ts b/lib/gauges/getGaugeRewards.ts new file mode 100644 index 0000000..e502dd1 --- /dev/null +++ b/lib/gauges/getGaugeRewards.ts @@ -0,0 +1,32 @@ +import { Address } from "wagmi"; +import { GaugeAbi, ZERO } from "@/lib/constants"; +import { PublicClient } from "viem"; + +interface GetGaugeRewardsProps { + gauges: Address[]; + account: Address; + publicClient: PublicClient; +} + +export type GaugeRewards = { + total: bigint, + amounts: { amount: bigint, address: Address }[] +} + +export default async function getGaugeRewards({ gauges, account, publicClient }: GetGaugeRewardsProps): Promise { + const data = await publicClient.multicall({ + contracts: gauges.map((address) => { + return { + address, + abi: GaugeAbi, + functionName: 'claimable_tokens', + args: [account] + } + }), + allowFailure: false + }) + + const total = data?.reduce((acc: bigint, curr: bigint) => acc + (curr || ZERO), ZERO); + const amounts = data?.map((amount, i) => { return { amount: amount, address: gauges[i] } }); + return { total, amounts } +} \ No newline at end of file diff --git a/lib/gauges/getGauges.ts b/lib/gauges/getGauges.ts new file mode 100644 index 0000000..c0aa4cf --- /dev/null +++ b/lib/gauges/getGauges.ts @@ -0,0 +1,83 @@ +import { Address, PublicClient, getAddress } from "viem"; +import { ADDRESS_ZERO, GaugeAbi, GaugeControllerAbi } from "@/lib/constants"; + +export interface Gauge { + address: Address; + lpToken: Address; + decimals: number; + balance: number; + chainId: number; +} + +export default async function getGauges({ address, account = ADDRESS_ZERO, publicClient }: { address: Address, account?: Address, publicClient: PublicClient }): Promise { + const nGauges = await publicClient.readContract({ + address: address, + abi: GaugeControllerAbi, + functionName: 'n_gauges', + }) + + const gaugeController = { + address: address, + abi: GaugeControllerAbi + } as const + + let gauges = await publicClient.multicall({ + contracts: Array(Number(nGauges)).fill(undefined).map((item, idx) => { + return { + ...gaugeController, + functionName: "gauges", + args: [idx] + } + }), + allowFailure: false + }) as Address[] + // @dev Deployment script ran out of gas and somehow added a random address into the gauges which now breaks these calls + gauges = gauges.filter(gauge => gauge !== "0x38098e3600665168eBE4d827D24D0416efC24799"); + + const areGaugesKilled = await publicClient.multicall({ + contracts: gauges.map((gauge: Address) => { + return { + address: gauge, + abi: GaugeAbi, + functionName: "is_killed", + } + }), + allowFailure: false + }) + + const aliveGauges = gauges?.filter((gauge: any, idx: number) => !areGaugesKilled[idx]) + + const lpTokens = await publicClient.multicall({ + contracts: aliveGauges.map((gauge: Address) => { + const gaugeContract = { + address: gauge, + abi: GaugeAbi, + } + return [{ + ...gaugeContract, + functionName: "lp_token", + }, + { + ...gaugeContract, + functionName: "decimals", + }, + { + ...gaugeContract, + functionName: 'balanceOf', + args: [account] + }] + }).flat(), + allowFailure: false + }) + + return aliveGauges.map((gauge: Address, i: number) => { + if (i > 0) i = i * 3 + return { + address: getAddress(gauge), + lpToken: getAddress(lpTokens[i + 0] as Address), + decimals: Number(lpTokens[i + 1]), + balance: account === ADDRESS_ZERO ? 0 : Number(lpTokens[i + 2]), + chainId: publicClient.chain?.id as number + } + }) +} \ No newline at end of file diff --git a/lib/gauges/hasAlreadyVoted.ts b/lib/gauges/hasAlreadyVoted.ts new file mode 100644 index 0000000..2b0067a --- /dev/null +++ b/lib/gauges/hasAlreadyVoted.ts @@ -0,0 +1,26 @@ +import { PublicClient, zeroAddress } from 'viem'; +import { Address } from 'wagmi'; +import { getVeAddresses } from '@/lib/utils/addresses'; +import { GaugeControllerAbi } from '@/lib/constants'; + +const DAYS = 24 * 60 * 60; + +const { GaugeController: GAUGE_CONTROLLER } = getVeAddresses() + +export async function hasAlreadyVoted({ addresses, publicClient, account = zeroAddress }: { addresses: Address[], publicClient: PublicClient, account?: Address }): Promise { + const data = await publicClient.multicall({ + contracts: addresses.map((address) => { + return { + address: GAUGE_CONTROLLER, + abi: GaugeControllerAbi, + functionName: "last_user_vote", + args: [account, address] + } + }), + allowFailure: false + }) + + const limitTimestamp = BigInt(Math.floor(Date.now() / 1000) - (DAYS * 10)); + + return data?.some((voteTimestamp: bigint) => voteTimestamp > limitTimestamp); +} \ No newline at end of file diff --git a/lib/gauges/interactions.ts b/lib/gauges/interactions.ts new file mode 100644 index 0000000..e3e9b7d --- /dev/null +++ b/lib/gauges/interactions.ts @@ -0,0 +1,231 @@ +import { Abi, Address, PublicClient, WalletClient, parseEther, zeroAddress } from "viem"; +import { VaultData } from "@/lib/types"; +import { showErrorToast, showLoadingToast, showSuccessToast } from "@/lib/toasts"; +import { SimulationResponse } from "@/lib/types"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { GaugeAbi, GaugeControllerAbi, VotingEscrowAbi } from "@/lib/constants"; +import { handleCallResult } from "../utils/helpers"; + +type SimulationContract = { + address: Address; + abi: Abi; +} + +interface SimulateProps { + account: Address; + contract: SimulationContract; + functionName: string; + publicClient: PublicClient; + args?: any[] +} + +const { GaugeController: GAUGE_CONTROLLER, VotingEscrow: VOTING_ESCROW } = getVeAddresses() + +async function simulateCall({ account, contract, functionName, publicClient, args }: SimulateProps): Promise { + try { + const { request } = await publicClient.simulateContract({ + account, + address: contract.address, + abi: contract.abi, + // @ts-ignore + functionName, + args + }) + return { request: request, success: true, error: null } + } catch (error: any) { + return { request: null, success: false, error: error.shortMessage } + } +} + +type Clients = { + publicClient: PublicClient; + walletClient: WalletClient; +} + +interface SendVotesProps { + vaults: VaultData[]; + votes: number[]; + account: Address; + clients: Clients; +} + +export async function sendVotes({ vaults, votes, account, clients }: SendVotesProps): Promise { + showLoadingToast("Sending votes...") + + let addr = new Array(8); + let v = new Array(8); + + for (let i = 0; i < Math.ceil(vaults.length / 8); i++) { + addr = []; + v = []; + + for (let n = 0; n < 8; n++) { + const l = i * 8; + v[n] = votes[n + l] === undefined ? 0 : votes[n + l]; + addr[n] = vaults[n + l] === undefined || votes[n + l] === 0 ? zeroAddress : vaults[n + l].gauge?.address as Address; + + } + + const success = await handleCallResult({ + successMessage: "Voted for gauges!", + simulationResponse: await simulateCall({ + account, + contract: { + address: GAUGE_CONTROLLER, + abi: GaugeControllerAbi, + }, + functionName: "vote_for_many_gauge_weights", + publicClient: clients.publicClient, + args: [addr, v] + }), + clients + }) + if (!success) return false + } + return true +} + +interface CreateLockProps { + amount: number | string; + days: number; + account: Address; + clients: Clients; +} + +export async function createLock({ amount, days, account, clients }: CreateLockProps): Promise { + showLoadingToast("Creating lock...") + + return handleCallResult({ + successMessage: "Lock created successfully!", + simulationResponse: await simulateCall({ + account, + contract: { + address: VOTING_ESCROW, + abi: VotingEscrowAbi, + }, + functionName: "create_lock", + publicClient: clients.publicClient, + args: [parseEther(Number(amount).toLocaleString("fullwide", { useGrouping: false })), BigInt(Math.floor(Date.now() / 1000) + (86400 * days))] + }), + clients + }) +} + +interface IncreaseLockAmountProps { + amount: number | string; + account: Address; + clients: Clients; +} + +export async function increaseLockAmount({ amount, account, clients }: IncreaseLockAmountProps): Promise { + showLoadingToast("Increasing lock amount...") + + return handleCallResult({ + successMessage: "Lock amount increased successfully!", + simulationResponse: await simulateCall({ + account, + contract: { + address: VOTING_ESCROW, + abi: VotingEscrowAbi, + }, + functionName: "increase_amount", + publicClient: clients.publicClient, + args: [parseEther(Number(amount).toLocaleString("fullwide", { useGrouping: false }))] + }), + clients + }) +} + +interface IncreaseLockTimeProps { + unlockTime: number; + account: Address; + clients: Clients; +} + +export async function increaseLockTime({ unlockTime, account, clients }: IncreaseLockTimeProps): Promise { + showLoadingToast("Increasing lock time...") + + return handleCallResult({ + successMessage: "Lock amount increased successfully!", + simulationResponse: await simulateCall({ + account, + contract: { + address: VOTING_ESCROW, + abi: VotingEscrowAbi, + }, + functionName: "increase_unlock_time", + publicClient: clients.publicClient, + args: [BigInt(unlockTime)] + }), + clients + }) +} + +interface WithdrawLockProps { + account: Address; + clients: Clients; +} + +export async function withdrawLock({ account, clients }: WithdrawLockProps): Promise { + showLoadingToast("Withdrawing lock...") + + return handleCallResult({ + successMessage: "Withdrawal successful!", + simulationResponse: await simulateCall({ + account, + contract: { + address: VOTING_ESCROW, + abi: VotingEscrowAbi, + }, + functionName: "withdraw", + publicClient: clients.publicClient, + }), + clients + }) +} + +interface GaugeInteractionProps { + chainId: number; + address: Address; + amount: number; + account: Address; + clients: Clients; +} + +export async function gaugeDeposit({ chainId, address, amount, account, clients }: GaugeInteractionProps): Promise { + showLoadingToast("Staking into Gauge...") + + return handleCallResult({ + successMessage: "Staked into Gauge successful!", + simulationResponse: await simulateCall({ + account, + contract: { + address, + abi: GaugeAbi, + }, + functionName: "deposit", + publicClient: clients.publicClient, + args: [amount] + }), + clients + }) +} + +export async function gaugeWithdraw({ chainId, address, amount, account, clients }: GaugeInteractionProps): Promise { + showLoadingToast("Unstaking from Gauge...") + + return handleCallResult({ + successMessage: "Unstaked from Gauge successful!", + simulationResponse: await simulateCall({ + account, + contract: { + address, + abi: GaugeAbi, + }, + functionName: "withdraw", + publicClient: clients.publicClient, + args: [amount] + }), + clients + }) +} \ No newline at end of file diff --git a/lib/gauges/useGaugeWeights.ts b/lib/gauges/useGaugeWeights.ts new file mode 100644 index 0000000..9e6d55e --- /dev/null +++ b/lib/gauges/useGaugeWeights.ts @@ -0,0 +1,38 @@ +import { Address, zeroAddress } from "viem"; +import { useContractReads } from "wagmi"; +import { getVotePeriodEndTime } from "@/lib/gauges/utils"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { GaugeControllerAbi } from "@/lib/constants"; + +const { GaugeController: GAUGE_CONTROLLER } = getVeAddresses(); + + +export default function useGaugeWeights({ address, account, chainId }: { address: Address, account: Address, chainId: number }) { + const contract = { + address: GAUGE_CONTROLLER, + chainId: Number(chainId), + abi: GaugeControllerAbi + } + + return useContractReads({ + contracts: [ + { + ...contract, + functionName: "gauge_relative_weight", + args: [address] + }, + { + ...contract, + functionName: "gauge_relative_weight", + args: [address, BigInt(getVotePeriodEndTime() / 1000)] + }, + { + ...contract, + functionName: "vote_user_slopes", + args: [account || zeroAddress, address] + } + ], + enabled: !!address && !!chainId, + allowFailure: false, + }) +} \ No newline at end of file diff --git a/lib/gauges/useLockedBalanceOf.ts b/lib/gauges/useLockedBalanceOf.ts new file mode 100644 index 0000000..f8aaa50 --- /dev/null +++ b/lib/gauges/useLockedBalanceOf.ts @@ -0,0 +1,20 @@ +import { Address, useContractRead } from "wagmi"; +import { VotingEscrowAbi } from "@/lib/constants"; + +export interface LockedBalance { + amount: bigint; + end: bigint; +} + +export default function useLockedBalanceOf({ chainId, address, account }: { chainId: number, address: Address, account: Address }) { + return useContractRead({ + address, + chainId: Number(chainId), + abi: VotingEscrowAbi, + functionName: "locked", + args: (!!account && [account]) || [], + scopeKey: `lockedBalanceOf:${chainId}:${address}:${account}`, + enabled: !!(chainId && address && account), + watch: true + }) +} \ No newline at end of file diff --git a/lib/gauges/utils.ts b/lib/gauges/utils.ts new file mode 100644 index 0000000..d47ad4e --- /dev/null +++ b/lib/gauges/utils.ts @@ -0,0 +1,40 @@ +import { nextThursday } from "date-fns" + +export function calcUnlockTime(days: number, start = Date.now()): number { + const week = 86400 * 7; + const now = start / 1000; + const unlockTime = now + (86400 * days); + + return Math.floor(unlockTime / week) * week * 1000; +} + +export function calcDaysToUnlock(unlockTime: number): number { + const day = 86400; + const now = Math.floor(Date.now() / 1000) + return Math.floor((unlockTime - now) / day) +} + +export function calculateVeOut(amount: number | string, days: number) { + const week = 7; + const maxTime = 52 * 4; // 4 years in weeks + const lockTime = Math.floor(days / week); + return Number(amount) * lockTime / maxTime; +} + +export function getVotePeriodEndTime(): number { + const n = nextThursday(new Date()); + const epochEndTime = Date.UTC( + n.getFullYear(), + n.getMonth(), + n.getDate(), + 0, + 0, + 0 + ); + return epochEndTime; +} + +export function thisPeriodTimestamp(): number { + const week = 604800 * 1000; + return (Math.floor(Date.now() / week) * week) / 1000; +}; \ No newline at end of file diff --git a/lib/getNetworth.ts b/lib/getNetworth.ts index 37ab5f0..0d5d9e7 100644 --- a/lib/getNetworth.ts +++ b/lib/getNetworth.ts @@ -3,9 +3,8 @@ import { Chain, arbitrum, optimism, polygon } from "viem/chains"; import { Address, mainnet } from "wagmi"; import { ChainId, RPC_URLS } from "@/lib/utils/connectors"; import { ERC20Abi, PopByChain, PopStakingByChain } from "@/lib/constants"; -import getVaultAddresses from "@/lib/vault/getVaultAddresses"; import { resolvePrice } from "@/lib/resolver/price/price"; -import { getVaultNetworthByChain } from "@/lib/vault/getVaultNetworth"; +import { VaultData } from "./types"; const BaseAddressesByChain: { [key: number]: Address[] } = { 1: [PopByChain[ChainId.Ethereum], PopStakingByChain[ChainId.Ethereum]], @@ -26,6 +25,14 @@ export type Networth = { total: number } +export function getVaultNetworthByChain({ vaults, chainId }: { vaults: VaultData[], chainId: number }): number { + const vaultValue = vaults.filter(vaultData => vaultData.chainId === chainId).map(vaultData => (vaultData.vault.balance * vaultData.vault.price) / (10 ** vaultData.vault.decimals)).reduce((a, b) => a + b, 0) + const gaugeValue = vaults.filter( + vaultData => vaultData.chainId === chainId && !!vaultData.gauge?.address) + .map(vaultData => ((vaultData.gauge?.balance || 0) * (vaultData.gauge?.price || 0)) / (10 ** (vaultData.gauge?.decimals || 0))).reduce((a, b) => a + b, 0) + return vaultValue + gaugeValue +} + async function getBalancesByChain({ account, client, addresses }: { account: Address, client: PublicClient, addresses: Address[] }) : Promise<{ address: Address, balance: number, decimals: number }[]> { let res = await client.multicall({ @@ -58,22 +65,16 @@ export async function getNetworthByChain({ account, chain }: { account: Address, chain, transport: http(RPC_URLS[chain.id]) }) - // Get addresses - const vaultAddresses = await getVaultAddresses({ client }) - const addresses = [...BaseAddressesByChain[client.chain?.id as number], ...vaultAddresses] // Get balances - const balances = await getBalancesByChain({ account, client, addresses }) + const balances = await getBalancesByChain({ account, client, addresses: BaseAddressesByChain[client.chain?.id as number] }) - // Get value of POP holdings + // Get value of VCX holdings const popPrice = await resolvePrice({ address: PopByChain[10], chainId: 10, client: undefined, resolver: 'llama' }) const popNetworth = ((balances.find(entry => entry.address === PopByChain[chain.id])?.balance || 0) * popPrice) / (1e18); const stakeNetworth = ((balances.find(entry => entry.address === PopStakingByChain[chain.id])?.balance || 0) * popPrice) / (1e18); - // Get value of vault holdings - const vaultNetworth = await getVaultNetworthByChain({ account, chain }) - - return { pop: popNetworth, stake: stakeNetworth, vault: vaultNetworth, total: popNetworth + stakeNetworth + vaultNetworth } + return { pop: popNetworth, stake: stakeNetworth, vault: 0, total: popNetworth + stakeNetworth } } export async function getTotalNetworth({ account }: { account: Address }): Promise { @@ -90,7 +91,7 @@ export async function getTotalNetworth({ account }: { account: Address }): Promi total: { pop: ethereumNetworth.pop + polygonNetworth.pop + optimismNetworth.pop + arbitrumNetworth.pop, stake: ethereumNetworth.stake + polygonNetworth.stake + optimismNetworth.stake + arbitrumNetworth.stake, - vault: ethereumNetworth.vault + polygonNetworth.vault + optimismNetworth.vault + arbitrumNetworth.vault, + vault: 0, total: ethereumNetworth.total + polygonNetworth.total + optimismNetworth.total + arbitrumNetworth.total } } diff --git a/lib/oPop/ethToUsd.ts b/lib/oPop/ethToUsd.ts new file mode 100644 index 0000000..98454b6 --- /dev/null +++ b/lib/oPop/ethToUsd.ts @@ -0,0 +1,38 @@ +import { useState, useEffect } from 'react'; +import axios from 'axios'; +import { formatEther, parseEther, parseUnits } from 'viem'; + +async function getEthToUsdPrice(): Promise { + try { + const response = await axios.get('https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd'); + return response.data.ethereum.usd; + } catch (error) { + throw new Error('Failed to fetch ETH price from CoinGecko'); + } +} + +async function convertEthToUsd(ethAmount: bigint): Promise { + const ethToUsdPrice = await getEthToUsdPrice(); + const ethAmountFloat = parseFloat(formatEther(ethAmount)); + const usdValue = ethAmountFloat * ethToUsdPrice; + return parseEther(usdValue.toString()); +} + +export function useEthToUsd(ethAmount: bigint) { + const [usdValue, setUsdValue] = useState(null); + + useEffect(() => { + async function fetchUsdValue() { + try { + const value = await convertEthToUsd(ethAmount); + setUsdValue(value); + } catch (error) { + console.error(error); + } + } + + fetchUsdValue(); + }, [ethAmount]); + + return usdValue; +} \ No newline at end of file diff --git a/lib/oPop/interactions.ts b/lib/oPop/interactions.ts new file mode 100644 index 0000000..cd2f0b9 --- /dev/null +++ b/lib/oPop/interactions.ts @@ -0,0 +1,105 @@ +import { Abi, Address, PublicClient, WalletClient, parseEther } from "viem"; +import { showErrorToast, showSuccessToast } from "@/lib/toasts"; +import { MinterAbi, OPopAbi } from "@/lib/constants"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { SimulationResponse } from "@/lib/types"; + +type SimulationContract = { + address: Address; + abi: Abi; +} + +interface SimulateProps { + account: Address; + contract: SimulationContract; + functionName: string; + publicClient: PublicClient; + args?: any[] +} + +const { oVCX, Minter: OVCX_MINTER } = getVeAddresses() + +async function simulateCall({ account, contract, functionName, publicClient, args }: SimulateProps): Promise { + try { + const { request } = await publicClient.simulateContract({ + account, + address: contract.address, + abi: contract.abi, + // @ts-ignore + functionName, + args + }) + return { request: request, success: true, error: null } + } catch (error: any) { + return { request: null, success: false, error: error.shortMessage } + } +} + +type Clients = { + publicClient: PublicClient; + walletClient: WalletClient; +} + +interface ExerciseOPopProps { + amount: bigint; + maxPaymentAmount: bigint; + account: Address; + clients: Clients +} + +export async function exerciseOPop({ amount, maxPaymentAmount, account, clients }: ExerciseOPopProps) { + const { request, success, error: simulationError } = await simulateCall({ + account, + contract: { + address: oVCX, + abi: OPopAbi, + }, + functionName: "exercise", + publicClient: clients.publicClient, + args: [amount, maxPaymentAmount, account] + }) + + if (success) { + try { + const hash = await clients.walletClient.writeContract(request) + const receipt = await clients.publicClient.waitForTransactionReceipt({ hash }) + showSuccessToast("oVCX exercised successfully!") + } catch (error: any) { + showErrorToast(error.shortMessage) + } + } else { + showErrorToast(simulationError) + } +} + + +interface ClaimOPopProps { + gauges: Address[]; + account: Address; + clients: Clients +} + +export async function claimOPop({ gauges, account, clients }: ClaimOPopProps) { + const { request, success, error: simulationError } = await simulateCall({ + account, + contract: { + address: OVCX_MINTER, + abi: MinterAbi, + }, + functionName: "mintMany", + publicClient: clients.publicClient, + args: [gauges] + }) + + if (success) { + try { + const hash = await clients.walletClient.writeContract(request) + const receipt = await clients.publicClient.waitForTransactionReceipt({ hash }) + showSuccessToast("oVCX Succesfully Claimed!") + } catch (error: any) { + showErrorToast(error.shortMessage) + } + } else { + showErrorToast(simulationError) + } +} \ No newline at end of file diff --git a/lib/resolver/price/index.ts b/lib/resolver/price/index.ts index b9adab0..214ed33 100644 --- a/lib/resolver/price/index.ts +++ b/lib/resolver/price/index.ts @@ -1,7 +1,7 @@ import { Address } from "viem"; import { PublicClient } from "wagmi"; -import { llama, vault } from "./resolver" +import { llama } from "./resolver" export type PriceResolverParams = { address: Address, @@ -13,7 +13,6 @@ export type PriceResolvers = typeof PriceResolvers; export const PriceResolvers: { [key: string]: ({ address, chainId, client }: PriceResolverParams) => Promise } = { llama, - vault, default: llama }; diff --git a/lib/resolver/price/resolver/index.ts b/lib/resolver/price/resolver/index.ts index f653d71..91258b0 100644 --- a/lib/resolver/price/resolver/index.ts +++ b/lib/resolver/price/resolver/index.ts @@ -1,2 +1 @@ -export * from "./llama"; -export * from "./vault"; \ No newline at end of file +export * from "./llama"; \ No newline at end of file diff --git a/lib/resolver/price/resolver/vault.ts b/lib/resolver/price/resolver/vault.ts deleted file mode 100644 index 382c315..0000000 --- a/lib/resolver/price/resolver/vault.ts +++ /dev/null @@ -1,12 +0,0 @@ -import getAssetAndValueByVault from "@/lib/vault/getAssetAndAssetsPerShare"; -import { PriceResolverParams } from ".."; -import { resolvePrice } from "../price"; - -export async function vault({ address, chainId, client }: PriceResolverParams): Promise { - if (!client) return 0; - - const { asset, assetsPerShare } = await getAssetAndValueByVault({ address, client }); - const price = await resolvePrice({ chainId: chainId, client: client, address: asset, resolver: 'llama' }) - - return Number(assetsPerShare) * price -} diff --git a/lib/types.ts b/lib/types.ts index d84f176..b25aceb 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -1,5 +1,5 @@ import { ProtocolName } from "vaultcraft-sdk"; -import { Address } from "viem"; +import { Address, PublicClient, WalletClient } from "viem"; export type Token = { address: Address; @@ -11,6 +11,38 @@ export type Token = { price: number; }; +export type veAddresses = { + VCX: Address; + WETH_VCX_LP:Address; + VE_VCX:Address; + POP: Address; + WETH: Address; + BalancerPool: Address; + BalancerOracle: Address; + oVCX: Address; + VaultRegistry: Address; + BoostV2:Address; + Minter: Address; + TokenAdmin: Address; + VotingEscrow: Address; + GaugeController: Address; + GaugeFactory: Address; + SmartWalletChecker: Address; + VotingEscrowDelegation: Address; + VaultRouter: Address; + FeeDistributor: Address; +}; + +export type Asset = { + chains: number[]; + address: { [key: string]: Address }; + name: string; + symbol: string; + decimals: number; + logoURI: string; + apy?: number; +}; + export type TokenConstant = { chains: number[]; address: { [key: string]: Address }; @@ -41,6 +73,10 @@ export type VaultData = { depositLimit: number; metadata: VaultMetadata; chainId: number; + apy: number; + gaugeMinApy?: number; + gaugeMaxApy?: number; + totalApy:number; } export type VaultMetadata = { @@ -77,4 +113,22 @@ export interface IconProps { color: string; size: string; className?: string; +} + +export interface Clients { + publicClient: PublicClient; + walletClient: WalletClient; +} + +export enum ActionType { + Deposit, + Withdrawal, + Stake, + Unstake, + DepositAndStake, + UnstakeAndWithdraw, + ZapDeposit, + ZapWithdrawal, + ZapDepositAndStake, + ZapUnstakeAndWithdraw } \ No newline at end of file diff --git a/lib/utils/addresses/index.ts b/lib/utils/addresses/index.ts new file mode 100644 index 0000000..2387d7d --- /dev/null +++ b/lib/utils/addresses/index.ts @@ -0,0 +1,26 @@ +import { veAddresses } from "lib/types"; + +const VeAddresses = { + VCX: "0xcE246eEa10988C495B4A90a905Ee9237a0f91543", + WETH_VCX_LP: "0x577A7f7EE659Aa14Dc16FD384B3F8078E23F1920", + VE_VCX:"0x0aB4bC35Ef33089B9082Ca7BB8657D7c4E819a1A", + oVCX: "0xaFa52E3860b4371ab9d8F08E801E9EA1027C0CA2", + POP: "0xD0Cd466b34A24fcB2f87676278AF2005Ca8A78c4", + WETH: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + BalancerPool: "0x577A7f7EE659Aa14Dc16FD384B3F8078E23F1920", // Same as WETH_VCX_LP + BalancerOracle: "0xe2871224b413F55c5a2Fd21E49bD63A52e339b03", + VaultRegistry: "0x007318Dc89B314b47609C684260CfbfbcD412864", + BoostV2: "0xa2E88993a0f0dc6e6020431477f3A70c86109bBf", + Minter: "0x49f095B38eE6d8541758af51c509332e7793D4b0", + TokenAdmin: "0x03d103c547B43b5a76df7e652BD0Bb61bE0BD70d", + VotingEscrow: "0x0aB4bC35Ef33089B9082Ca7BB8657D7c4E819a1A", // Same as VE_VCX + GaugeController: "0xD57d8EEC36F0Ba7D8Fd693B9D97e02D8353EB1F4", + GaugeFactory: "0x3bd6418e90653945f781e3717D8F9404565444F6", + SmartWalletChecker: "0x8427155770f7e6b973249E2f9D140a495aBE4f90", + VotingEscrowDelegation: "0xafE32869CAf311585647ADcD79050B83DbCF94C8", + VaultRouter: "0x8aed8Ea73044910760E8957B6c5b28Ac51f8f809" +}; + +export function getVeAddresses(): veAddresses { + return VeAddresses as veAddresses; +} diff --git a/lib/utils/connectors.ts b/lib/utils/connectors.ts index 458fa13..87c973e 100644 --- a/lib/utils/connectors.ts +++ b/lib/utils/connectors.ts @@ -81,10 +81,10 @@ export const networkLogos: { [key: number]: string } = { [ChainId.RemoteFork]: "/images/networks/testNets.png", }; export const RPC_URLS: { [key: number]: string } = { - [ChainId.Ethereum]: `https://eth-mainnet.alchemyapi.io/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`, - [ChainId.Arbitrum]: `https://arb-mainnet.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`, - [ChainId.Polygon]: `https://polygon-mainnet.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`, - [ChainId.Optimism]: `https://opt-mainnet.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`, + [ChainId.Ethereum]: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_API_KEY}`, + [ChainId.Arbitrum]: `https://arb-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`, + [ChainId.Polygon]: `https://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`, + [ChainId.Optimism]: `https://opt-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`, [ChainId.Goerli]: "https://goerli.blockpi.network/v1/rpc/public", [ChainId.BNB]: `https://bsc-dataseed1.binance.org`, [ChainId.Localhost]: `http://localhost:8545`, diff --git a/lib/utils/formatBigNumber.ts b/lib/utils/formatBigNumber.ts index 58b07b5..e84910c 100644 --- a/lib/utils/formatBigNumber.ts +++ b/lib/utils/formatBigNumber.ts @@ -1,5 +1,5 @@ import { formatUnits, parseUnits } from "viem"; -import { ZERO } from "./helpers"; +import { ZERO } from "@/lib/constants"; const MILLION = 1e6; const THOUSAND = 1e3; @@ -66,4 +66,20 @@ export function numberToBigNumber(value: number | string, decimals: number): Big export const NumberFormatter = Intl.NumberFormat("en", { //@ts-ignore notation: "compact", -}); \ No newline at end of file + maximumSignificantDigits: 3 +}); + +export function safeRound(bn: bigint, decimals = 18): bigint { + let roundingDecimals = 1; + if (decimals < 2) { + roundingDecimals = 1; + } else if (decimals <= 8) { + roundingDecimals = 2; + } else if (decimals <= 18) { + roundingDecimals = 10 + } else if (decimals === 27) { + roundingDecimals = 20 + } + const roundingValue = parseUnits("1", roundingDecimals) + return (bn / roundingValue) * roundingValue +} \ No newline at end of file diff --git a/lib/utils/getZapAssets.ts b/lib/utils/getZapAssets.ts new file mode 100644 index 0000000..4da6351 --- /dev/null +++ b/lib/utils/getZapAssets.ts @@ -0,0 +1,54 @@ +import { Token } from "@/lib/types"; +import assets from "@/lib/constants/assets"; +import { Address, Chain, createPublicClient, getAddress, http } from "viem"; +import axios from "axios"; +import { RPC_URLS, networkMap } from "@/lib/utils/connectors"; +import { ERC20Abi } from "@/lib/constants"; + +const symbolsToSelect = ["DAI", "USDC", "USDC.e", "USDT", "LUSD", "WETH", "WBTC"] + +export default async function getZapAssets({ chain, account }: { chain: Chain, account?: Address }): Promise { + const selected = assets.filter(asset => asset.chains.includes(chain.id)).filter(asset => symbolsToSelect.includes(asset.symbol)) + if (selected.length === 0) return [] + // Add prices + const { data } = await axios.get(`https://coins.llama.fi/prices/current/${String(selected.map(asset => `${networkMap[chain.id].toLowerCase()}:${asset.address[String(chain.id)]}`))}`) + + let balances: bigint[]; + if (account) { + const client = createPublicClient({ chain, transport: http(RPC_URLS[chain.id]) }) + balances = await client.multicall({ + contracts: selected.map(asset => { + return { + address: asset.address[String(chain.id)], + abi: ERC20Abi, + functionName: 'balanceOf', + args: [account] + } + }), + allowFailure: false + }) + } + + return selected.map((asset, i) => { + const address = asset.address[String(chain.id)] + const key = `${networkMap[chain.id].toLowerCase()}:${address}` + const price = Number(data.coins[key]?.price || 0) + return { + address, + name: asset.name, + symbol: asset.symbol, + decimals: asset.decimals, + logoURI: asset.logoURI, + balance: account ? Number(balances[i]) : 0, + price + } + }) +} + +export async function getAvailableZapAssets(chainId: number) { + const defiTokens = (await axios.get('https://enso-scrape.s3.us-east-2.amazonaws.com/output/backend/defiTokens.json')).data + .filter((entry: any) => entry.chainId === chainId).map((entry: any) => getAddress(entry.tokenAddress)) + const baseTokens = (await axios.get('https://enso-scrape.s3.us-east-2.amazonaws.com/output/backend/baseTokens.json')).data + .filter((entry: any) => entry.chainId === chainId).map((entry: any) => getAddress(entry.address)) + return [...baseTokens, ...defiTokens] +} \ No newline at end of file diff --git a/lib/utils/helpers.ts b/lib/utils/helpers.ts index e69de29..8acad1e 100644 --- a/lib/utils/helpers.ts +++ b/lib/utils/helpers.ts @@ -0,0 +1,69 @@ +import { showErrorToast, showSuccessToast } from "../toasts"; +import { Clients, SimulationResponse, Token } from "../types"; + +export function validateInput(value: string | number): { formatted: string, isValid: boolean } { + const formatted = value === "." ? "0" : (`${value || "0"}`.replace(/\.$/, ".0") as any); + return { + formatted, + isValid: value === "" || isFinite(Number(formatted)), + }; +}; + +interface HandleCallResultProps { + successMessage: string; + simulationResponse: SimulationResponse; + clients: Clients; +} + +export async function handleCallResult({ successMessage, simulationResponse, clients }: HandleCallResultProps): Promise { + if (simulationResponse.success) { + try { + const hash = await clients.walletClient.writeContract(simulationResponse.request) + const receipt = await clients.publicClient.waitForTransactionReceipt({ hash }) + showSuccessToast(successMessage) + return true; + } catch (error: any) { + showErrorToast(error.shortMessage) + return false; + } + } else { + showErrorToast(simulationResponse.error) + return false; + } +} + + +export function cleanTokenName(token: Token): string { + if (token.name.includes("Hop")) { + return token.name.slice(0, token.name.indexOf(" LP Token")) + } + else if (token.name.includes("Curve.fi Factory USD Metapool")) { + return token.name.slice(31) + } + else if (token.name.includes("Curve.fi Factory Pool:")) { + return token.name.slice(23) + } + else if (token.name.includes("StableV")) { + return token.name.slice(15) + } + else if (token.name.includes("VolatileV")) { + return token.name.slice(17) + } + return token.name +} + +export function cleanTokenSymbol(token: Token): string { + if (token.symbol.includes("HOP-LP")) { + const split = token.symbol.split("LP-") + return split[0] + split[1] + } + else if (token.symbol.includes("AMMV2")) { + const split = token.symbol.split("AMMV2-") + return split[0].slice(0, -1) + split[1] + } + else if (token.symbol.includes("AMM")) { + const split = token.symbol.split("AMM-") + return split[0].slice(0, -1) + split[1] + } + return token.symbol +} \ No newline at end of file diff --git a/lib/utils/metadata/protocolMetadata.ts b/lib/utils/metadata/protocolMetadata.ts index de311ba..b3095e5 100644 --- a/lib/utils/metadata/protocolMetadata.ts +++ b/lib/utils/metadata/protocolMetadata.ts @@ -42,6 +42,14 @@ const ProtocolMetadata: { [key: string]: { name: string, description: string } } description: `Idle is a decentralized yield automation protocol that aims to step up DeFi by reimagining how risk and yield are managed. This vault is connected to **[Yield Tranches](https://docs.idle.finance/products/yield-tranches) (YTs)**: an innovative DeFi primitive that segments yields and risks to appeal to a diverse range of users, offering two risk-return profiles, Senior and Junior. **Senior YTs withhold part of their yield in exchange for funds coverage**, given by the Junior class’ liquidity. This way, **Senior holders benefit from built-in protection on deposits**. That yield is routed to the Junior side in exchange for first-loss liquidity to cover Senior funds. --- All Idle strategies feature **automatically compounded interest** and **no lock-up periods**.` + }, + pirex: { + name: "Pirex", + description: "Pirex is a product by Redacted which creates liquid wrappers that allow for auto-compounding and the tokenization of future yield/vote events." + }, + sommelier: { + name: "Sommelier", + description: "Provider of automated vaults that find best-in-class yields while mitigating risk." } } diff --git a/lib/vault/getActionSteps.ts b/lib/vault/getActionSteps.ts new file mode 100644 index 0000000..3b4a9e3 --- /dev/null +++ b/lib/vault/getActionSteps.ts @@ -0,0 +1,144 @@ +import { ActionType } from "../types"; + +export interface ActionStep { + step: number; + label: string; + success: boolean; + error: boolean; + loading: boolean; +} + +const BaseStepInfo = { + success: false, + error: false, + loading: false +} + +export default function getActionSteps(action: ActionType): ActionStep[] { + switch (action) { + case ActionType.Deposit: + return [{ + step: 1, + label: "Handle Allowance", + ...BaseStepInfo + }, + { + step: 2, + label: "Deposit into Vault", + ...BaseStepInfo + }] + case ActionType.Withdrawal: + return [{ + step: 1, + label: "Withdraw from Vault", + ...BaseStepInfo + }] + case ActionType.Stake: + return [{ + step: 1, + label: "Handle Allowance", + ...BaseStepInfo + }, + { + step: 2, + label: "Stake into Gauge", + ...BaseStepInfo + }] + case ActionType.Unstake: + return [{ + step: 1, + label: "Unstake from Gauge", + ...BaseStepInfo + }] + case ActionType.DepositAndStake: + return [{ + step: 1, + label: "Handle Allowance", + ...BaseStepInfo + }, + { + step: 2, + label: "Deposit and Stake", + ...BaseStepInfo + }] + case ActionType.UnstakeAndWithdraw: + return [{ + step: 1, + label: "Handle Allowance", + ...BaseStepInfo + }, + { + step: 2, + label: "Unstake and Withdraw", + ...BaseStepInfo + }] + case ActionType.ZapDeposit: + return [{ + step: 1, + label: "Handle Zap Allowance", + ...BaseStepInfo + }, { + step: 2, + label: "Zap", + ...BaseStepInfo + }, { + step: 3, + label: "Handle Allowance", + ...BaseStepInfo + }, { + step: 4, + label: "Deposit", + ...BaseStepInfo + }] + case ActionType.ZapWithdrawal: + return [{ + step: 1, + label: "Withdraw", + ...BaseStepInfo + }, { + step: 2, + label: "Handle Zap Allowance", + ...BaseStepInfo + }, { + step: 3, + label: "Zap", + ...BaseStepInfo + }] + case ActionType.ZapDepositAndStake: + return [{ + step: 1, + label: "Handle Zap Allowance", + ...BaseStepInfo + }, { + step: 2, + label: "Zap", + ...BaseStepInfo + }, { + step: 3, + label: "Handle Allowance", + ...BaseStepInfo + }, { + step: 4, + label: "Deposit and Stake", + ...BaseStepInfo + }] + case ActionType.ZapUnstakeAndWithdraw: + return [{ + step: 1, + label: "Handle Allowance", + ...BaseStepInfo + }, { + step: 2, + label: "Unstake and Withdraw", + ...BaseStepInfo + }, { + step: 3, + label: "Handle Zap Allowance", + ...BaseStepInfo + }, { + step: 4, + label: "Zap", + ...BaseStepInfo + }] + } +} \ No newline at end of file diff --git a/lib/vault/getAssetIcon.ts b/lib/vault/getAssetIcon.ts index eac6c56..3b4c13f 100644 --- a/lib/vault/getAssetIcon.ts +++ b/lib/vault/getAssetIcon.ts @@ -69,18 +69,17 @@ function getProtocolIcon(asset: Token, adapter: Token, chainId: number): string // TODO fill this with curve lp icon return undefined; } - else if (adapter?.name?.includes("Stargate") || asset?.name?.includes("STG") || asset?.symbol?.includes("STG") || asset?.symbol?.includes("S*")) { + else if (adapter?.name?.includes("Velodrome") || asset?.symbol?.includes("vAMM")) { // TODO fill this with curve lp icon + return "/images/tokens/velodrome-lp.svg"; + } + else if (adapter?.name?.includes("Stargate") || asset?.name?.includes("STG") || asset?.symbol?.includes("STG") || asset?.symbol?.includes("S*")) { return getIconFromTokenListBySymbol(asset?.symbol?.includes("*") ? asset?.symbol?.split("*")[1] : asset?.symbol?.split(" ")[1], chainId); } else if (adapter?.name?.includes("Sushi")) { // TODO fill this with curve lp icon return undefined; } - else if (adapter?.name?.includes("Velodrome")) { - // TODO fill this with curve lp icon - return "/images/tokens/velodrome-lp.svg"; - } else if (adapter?.name?.includes("Yearn")) { // TODO fill this with curve lp icon return undefined; diff --git a/lib/vault/getOptionalMetadata.ts b/lib/vault/getOptionalMetadata.ts index 61727cd..2389b68 100644 --- a/lib/vault/getOptionalMetadata.ts +++ b/lib/vault/getOptionalMetadata.ts @@ -1,9 +1,8 @@ import TokenMetadata, { addLpMetadata } from "@/lib/utils/metadata/tokenMetadata"; import ProtocolMetadata from "@/lib/utils/metadata/protocolMetadata"; import StrategyMetadata, { addGenericStrategyDescription } from "@/lib/utils/metadata/strategyMetadata"; -import { Token } from "../types"; +import { Token, OptionalMetadata } from "../types"; import { Address } from "viem"; -import { OptionalMetadata } from "./getVault"; function getLocalMetadata(address: string): OptionalMetadata | undefined { switch (address) { @@ -370,6 +369,24 @@ function getOriginMetadata(adapter: Token, asset: Token): OptionalMetadata { } } +function getPirexMetadata(adapter: Token, asset: Token): OptionalMetadata { + return { + protocol: ProtocolMetadata.pirex, + token: { name: asset.symbol, description: "None available" }, + strategy: { name: "Pirex Vault", description: addGenericStrategyDescription("automatedAssetStrategy", "Pirex") }, + resolver: "pirex" + } +} + +function getSommelierMetadata(adapter: Token, asset: Token): OptionalMetadata { + return { + protocol: ProtocolMetadata.sommelier, + token: { name: asset.symbol, description: "None available" }, + strategy: { name: "Sommelier Vault", description: addGenericStrategyDescription("automatedAssetStrategy", "Sommelier") }, + resolver: "sommelier" + } +} + function getEmptyMetadata(adapter: Token, asset: Token): OptionalMetadata { return { token: { name: "Token", description: "Not found" }, @@ -404,6 +421,10 @@ function getFactoryMetadata({ adapter, asset }: { adapter: Token, asset: Token } return getIdleMetadata(adapter, asset) } else if (adapter?.name?.includes("Origin")) { return getOriginMetadata(adapter, asset) + } else if (asset?.name?.includes("Pirex")) { + return getPirexMetadata(adapter, asset) + } else if (adapter?.symbol?.includes("WETH")) { + return getSommelierMetadata(adapter, asset) } return getEmptyMetadata(adapter, asset) } @@ -415,4 +436,4 @@ export default function getOptionalMetadata({ vaultAddress, asset, adapter }: { else { return getFactoryMetadata({ adapter, asset }) } -} \ No newline at end of file +} diff --git a/lib/vault/getVault.ts b/lib/vault/getVault.ts index 701f57f..af2e76c 100644 --- a/lib/vault/getVault.ts +++ b/lib/vault/getVault.ts @@ -2,7 +2,6 @@ import { Address, Chain, ReadContractParameters, createPublicClient, getAddress, import { PublicClient } from "wagmi" import axios from "axios" import { VaultAbi } from "@/lib/constants/abi/Vault" -import { resolvePrice } from "@/lib/resolver/price/price" import { Token, VaultData } from "@/lib/types" import { ADDRESS_ZERO, ERC20Abi, VaultRegistryByChain, VaultRegistyAbi } from "@/lib/constants" import { RPC_URLS, networkMap } from "@/lib/utils/connectors"; @@ -10,6 +9,13 @@ import getVaultAddresses from "@/lib/vault/getVaultAddresses" import getAssetIcon from "@/lib/vault/getAssetIcon" import getVaultName from "@/lib/vault/getVaultName" import getOptionalMetadata from "@/lib/vault/getOptionalMetadata" +import { getVeAddresses } from "../utils/addresses" +import getGauges, { Gauge } from "../gauges/getGauges" +import { cleanTokenName, cleanTokenSymbol } from "../utils/helpers" +import { ProtocolName, YieldOptions } from "vaultcraft-sdk" +import calculateAPR from "../gauges/calculateGaugeAPR" + +const { GaugeController: GAUGE_CONTROLLER } = getVeAddresses(); function prepareVaultContract(vault: Address, account: Address): ReadContractParameters[] { const vaultContract = { @@ -97,13 +103,26 @@ function prepareTokenContracts(address: Address, account: Address): ReadContract ] } -export async function getVaultsByChain({ chain, account }: { chain: Chain, account?: Address }): Promise { +interface GetVaultsByChainProps { + chain: Chain; + account?: Address; + yieldOptions: YieldOptions +} + +export async function getVaultsByChain({ chain, account, yieldOptions }: GetVaultsByChainProps): Promise { const client = createPublicClient({ chain, transport: http(RPC_URLS[chain.id]) }) const vaults = await getVaultAddresses({ client }) - return getVaults({ vaults, account, client }) + return getVaults({ vaults, account, client, yieldOptions }) +} + +interface GetVaultsProps { + vaults: Address[]; + account?: Address; + client: PublicClient; + yieldOptions: YieldOptions } -export async function getVaults({ vaults, account = ADDRESS_ZERO, client }: { vaults: Address[], account?: Address, client: PublicClient }): Promise { +export async function getVaults({ vaults, account = ADDRESS_ZERO, client, yieldOptions }: GetVaultsProps): Promise { const hasAccount = account !== ADDRESS_ZERO // Get vault addresses const results = await client.multicall({ @@ -116,16 +135,18 @@ export async function getVaults({ vaults, account = ADDRESS_ZERO, client }: { va if (i > 0) i = i * 10 const assetsPerShare = Number(results[i + 6]) > 0 ? Number(results[i + 5]) / Number(results[i + 6]) : Number(1e-9) const fees = results[i + 7] as [BigInt, BigInt, BigInt, BigInt] + const vaultToken: Token = { + address: getAddress(vault), + name: String(results[i + 0]), + symbol: String(results[i + 1]), + decimals: Number(results[i + 2]), + logoURI: "/images/tokens/pop.svg", + balance: hasAccount ? Number(results[i + 9]) : 0, + price: 0 // @dev will be added in a later step + } return { address: getAddress(vault), - vault: { - address: getAddress(vault), - name: String(results[i + 0]), - symbol: String(results[i + 1]), - decimals: Number(results[i + 2]), - logoURI: "/images/tokens/pop.svg", - balance: hasAccount ? Number(results[i + 9]) : 0 - }, + vault: { ...vaultToken, symbol: cleanTokenSymbol(vaultToken) }, assetAddress: getAddress(results[i + 3] as string), adapterAddress: getAddress(results[i + 4] as string), totalAssets: Number(results[i + 5]), @@ -164,7 +185,7 @@ export async function getVaults({ vaults, account = ADDRESS_ZERO, client }: { va name: String(assetAndAdapterMeta[i + 3]), symbol: String(assetAndAdapterMeta[i + 4]), decimals: entry.vault.decimals, - logoURI: "", // wont be used, just here for consistency + logoURI: "/images/tokens/pop.svg", // wont be used, just here for consistency balance: 0, price: 0, } @@ -172,6 +193,8 @@ export async function getVaults({ vaults, account = ADDRESS_ZERO, client }: { va ...entry, asset: { ...asset, + name: cleanTokenName(asset), + symbol: cleanTokenSymbol(asset), logoURI: getAssetIcon({ asset, adapter, chainId: client.chain.id }) }, adapter @@ -216,80 +239,55 @@ export async function getVaults({ vaults, account = ADDRESS_ZERO, client }: { va } }) - return metadata as unknown as VaultData[] -} - + // Add apy + metadata = await Promise.all(metadata.map(async (entry, i) => { + let apy = 0; + try { + const vaultYield = await yieldOptions.getApy({ + chainId: entry.chainId, + protocol: entry.metadata.optionalMetadata.resolver as ProtocolName, + asset: entry.asset.address + }) + apy = vaultYield.total + } catch (e) { } + return { ...entry, apy, totalApy: apy } + })) -export async function getVault({ vault, account = ADDRESS_ZERO, client }: { vault: Address, account?: Address, client: PublicClient }): Promise { - const hasAccount = account !== ADDRESS_ZERO - const results = await client.multicall({ - contracts: prepareVaultContract(vault, account), - allowFailure: false - }) - const registryMetadata = await client.readContract(prepareRegistryContract(VaultRegistryByChain[client.chain.id], vault)) as unknown as string[] - const vaultName = await getVaultName({ address: getAddress(vault), cid: registryMetadata[3] }) + // Add gauges + if (client.chain.id === 1) { + const gauges = await getGauges({ address: GAUGE_CONTROLLER, account: account, publicClient: client }) + metadata = await Promise.all(metadata.map(async (entry, i) => { + const foundGauge = gauges.find((gauge: Gauge) => gauge.lpToken === entry.address) + const gauge = foundGauge ? { + address: foundGauge.address, + name: `${entry.vault.name}-gauge`, + symbol: `st-${entry.vault.name}`, + decimals: foundGauge.decimals, + logoURI: "/images/tokens/pop.svg", // wont be used, just here for consistency + balance: foundGauge.balance, + price: entry.pricePerShare * 1e9, + } : undefined - const price = await resolvePrice({ chainId: client.chain.id, client: client, address: results[3] as Address, resolver: 'llama' }) - const assetsPerShare = Number(results[6]) > 0 ? Number(results[5]) / Number(results[6]) : Number(1) - const pricePerShare = assetsPerShare * price - const fees = results[7] as [BigInt, BigInt, BigInt, BigInt] + let gaugeMinApy; + let gaugeMaxApy; + let totalApy = entry.totalApy; + if (!!gauge) { + const gaugeApr = await calculateAPR({ vaultPrice: entry.vault.price, gauge: gauge.address, publicClient: client }) + gaugeMinApy = gaugeApr[0]; + gaugeMaxApy = gaugeApr[1]; + totalApy += gaugeApr[1]; + } - // Add token and adapter metadata - const assetAndAdapterMeta = await client.multicall({ - contracts: [...prepareTokenContracts(results[3] as Address, account), ...prepareTokenContracts(results[4] as Address, account)].flat(), - allowFailure: false - }) - const asset = { - address: getAddress(results[3] as string), - name: String(assetAndAdapterMeta[0]), - symbol: String(assetAndAdapterMeta[1]), - decimals: Number(results[2]) - 9, - logoURI: "", - balance: hasAccount ? Number(assetAndAdapterMeta[2]) : 0, - price: price - } - const adapter = { - address: getAddress(results[4] as string), - name: String(assetAndAdapterMeta[3]), - symbol: String(assetAndAdapterMeta[4]), - decimals: Number(results[2]), - logoURI: "", // wont be used, just here for consistency, - balance: 0, // wont be used, just here for consistency, - price: 0, // wont be used, just here for consistency, - } - return { - address: getAddress(vault), - vault: { - address: getAddress(vault), - name: String(results[0]), - symbol: String(results[1]), - decimals: Number(results[2]), - logoURI: "/images/tokens/pop.svg", - balance: hasAccount ? Number(results[9]) : 0, - price: pricePerShare * 1e9, // @dev -- normalize vault price for previews (watch this if errors occur) - }, - asset: { ...asset, logoURI: getAssetIcon({ asset, adapter, chainId: client.chain.id }) }, - adapter, - totalAssets: Number(results[5]), - totalSupply: Number(results[6]), - assetsPerShare: assetsPerShare, - assetPrice: price, - pricePerShare: pricePerShare, - tvl: (Number(results[6]) * pricePerShare) / (10 ** (Number(results[2]) - 9)), - fees: { - deposit: Number(fees[0]), - withdrawal: Number(fees[1]), - management: Number(fees[2]), - performance: Number(fees[3]), - }, - depositLimit: Number(results[8]), - metadata: { - creator: registryMetadata[2] as Address, - cid: registryMetadata[3] as string, - vaultName: vaultName, - optionalMetadata: getOptionalMetadata({ vaultAddress: getAddress(vault), asset: asset, adapter: adapter }) - }, - chainId: client.chain.id + return { + ...entry, + gauge, + gaugeMinApy, + gaugeMaxApy, + totalApy + } + })) } + + return metadata as unknown as VaultData[] } \ No newline at end of file diff --git a/lib/vault/getVaultNetworth.ts b/lib/vault/getVaultNetworth.ts deleted file mode 100644 index 41ed07e..0000000 --- a/lib/vault/getVaultNetworth.ts +++ /dev/null @@ -1,96 +0,0 @@ -import axios from "axios"; -import { Address, PublicClient, mainnet } from "wagmi"; -import { ChainId, RPC_URLS, networkMap } from "@/lib/utils/connectors"; -import { VaultAbi } from "@/lib/constants"; -import getVaultAddresses from "@/lib/vault/getVaultAddresses"; -import { Chain, createPublicClient, http } from "viem"; -import { arbitrum, optimism, polygon } from "viem/chains"; - -function prepareContract(address: Address, account: Address) { - const vaultContract = { - address, - abi: VaultAbi - } - return [{ - ...vaultContract, - functionName: 'asset' - }, - { - ...vaultContract, - functionName: 'totalAssets' - }, - { - ...vaultContract, - functionName: 'totalSupply' - }, - { - ...vaultContract, - functionName: 'balanceOf', - args: [account] - }, - { - ...vaultContract, - functionName: 'decimals' - }] -} - -async function getVaultValues({ addresses, account, client }: { addresses: Address[], account: Address, client: PublicClient }): Promise { - const res = await client.multicall({ contracts: addresses.map(address => prepareContract(address, account)).flat(), allowFailure: false }) - - return addresses.map((address, i) => { - if (i > 0) i = i * 5 - const assetsPerShare = Number(res[i + 1]) === 0 ? 0 : Number(res[i + 1]) / Number(res[i + 2]) - return { - vault: address, - asset: res[i] as Address, - assetsPerShare: assetsPerShare, - totalAssets: Number(res[i + 1]), - totalSupply: Number(res[i + 2]), - balance: Number(res[i + 3]), - decimals: Number(res[i + 4]) - } - }) -} - -export async function getVaultNetworthByChain({ account, chain }: { account: Address, chain: Chain }): Promise { - const client = createPublicClient({ - chain, - transport: http(RPC_URLS[chain.id]) - }) - const addresses = await getVaultAddresses({ client }) - const vaultValues = await getVaultValues({ addresses, account, client }) - const { data } = await axios.get(`https://coins.llama.fi/prices/current/${String(vaultValues.map(entry => `${networkMap[chain.id].toLowerCase()}:${entry.asset}`))}`) - const vaults = vaultValues.map((entry, i) => { - const assetPrice = Number(data.coins[`${networkMap[chain.id].toLowerCase()}:${entry.asset}`]?.price || 0) - return { - ...entry, - price: assetPrice * entry.assetsPerShare, - balanceValue: entry.balance === 0 ? 0 : (entry.balance * assetPrice * entry.assetsPerShare) / (10 ** ((entry.decimals as number) - 9)) - } - }) - - return vaults.reduce((acc, entry) => acc + entry.balanceValue, 0) -} - -type VaultNetworth = { - [ChainId.Ethereum]: number, - [ChainId.Polygon]: number, - [ChainId.Optimism]: number, - [ChainId.Arbitrum]: number, - total: number -} - -export default async function getVaultNetworth({ account }: { account: Address }): Promise { - const ethereumNetworth = await getVaultNetworthByChain({ account, chain: mainnet }) - const polygonNetworth = await getVaultNetworthByChain({ account, chain: polygon }) - const optimismNetworth = await getVaultNetworthByChain({ account, chain: optimism }) - const arbitrumNetworth = await getVaultNetworthByChain({ account, chain: arbitrum }) - - return { - [ChainId.Ethereum]: ethereumNetworth, - [ChainId.Polygon]: polygonNetworth, - [ChainId.Optimism]: optimismNetworth, - [ChainId.Arbitrum]: arbitrumNetworth, - total: ethereumNetworth + polygonNetworth + optimismNetworth + arbitrumNetworth - } -} \ No newline at end of file diff --git a/lib/vault/handleVaultInteraction.ts b/lib/vault/handleVaultInteraction.ts new file mode 100644 index 0000000..42faead --- /dev/null +++ b/lib/vault/handleVaultInteraction.ts @@ -0,0 +1,145 @@ +import axios from "axios" +import { Address, getAddress } from "viem"; +import { handleAllowance } from "../approve"; +import { ActionType, Clients, Token } from "../types"; +import { vaultDeposit, vaultDepositAndStake, vaultRedeem, vaultUnstakeAndWithdraw } from "./interactions"; +import zap from "./zap"; +import { getVeAddresses } from "../utils/addresses"; +import { gaugeDeposit, gaugeWithdraw } from "../gauges/interactions"; +import { erc20ABI } from "wagmi"; + +const { VaultRouter: VAULT_ROUTER } = getVeAddresses() + +interface HandleVaultInteractionProps { + stepCounter: number; + action: ActionType; + chainId: number; + amount: number; + inputToken: Token; + outputToken: Token; + asset: Token, + vault: Token, + gauge?: Token, + account: Address, + slippage: number; + tradeTimeout: number, + clients: Clients, +} + +export default async function handleVaultInteraction({ + action, + stepCounter, + chainId, + amount, + inputToken, + outputToken, + asset, + vault, + gauge, + account, + slippage, + tradeTimeout, + clients, +}: HandleVaultInteractionProps): Promise<() => Promise> { + let postBal = 0; + switch (action) { + case ActionType.Deposit: + switch (stepCounter) { + case 0: + return () => handleAllowance({ token: inputToken.address, amount, account, spender: outputToken.address, clients }) + case 1: + return () => vaultDeposit({ chainId, vault: vault.address, account, amount, clients }) + } + case ActionType.Withdrawal: + return () => vaultRedeem({ chainId, vault: vault.address, account, amount, clients }) + case ActionType.Stake: + switch (stepCounter) { + case 0: + return () => handleAllowance({ token: inputToken.address, amount, account, spender: gauge?.address as Address, clients }) + case 1: + return () => gaugeDeposit({ chainId, address: gauge?.address as Address, account, amount, clients }) + } + case ActionType.Unstake: + return () => gaugeWithdraw({ chainId, address: gauge?.address as Address, account, amount, clients }) + case ActionType.DepositAndStake: + switch (stepCounter) { + case 0: + return () => handleAllowance({ token: inputToken.address, amount, account, spender: VAULT_ROUTER, clients }) + case 1: + return () => vaultDepositAndStake({ chainId, router: VAULT_ROUTER, vault: vault.address, gauge: gauge?.address as Address, account, amount, clients }) + } + case ActionType.UnstakeAndWithdraw: + switch (stepCounter) { + case 0: + return () => handleAllowance({ token: inputToken.address, amount, account, spender: VAULT_ROUTER, clients }) + case 1: + return () => vaultUnstakeAndWithdraw({ chainId, router: VAULT_ROUTER, vault: vault.address, gauge: gauge?.address as Address, account, amount, clients }) + } + case ActionType.ZapDeposit: + switch (stepCounter) { + case 0: + const ensoWallet = (await axios.get( + `https://api.enso.finance/api/v1/wallet?chainId=${chainId}&fromAddress=${account}`, + { headers: { Authorization: `Bearer ${process.env.ENSO_API_KEY}` } }) + ).data + return () => handleAllowance({ token: inputToken.address, amount, account, spender: getAddress(ensoWallet.address), clients }) + case 1: + return () => zap({ chainId, sellToken: inputToken.address, buyToken: asset.address, amount, account, slippage, tradeTimeout, clients }) + case 2: + postBal = Number(await clients.publicClient.readContract({ address: asset.address, abi: erc20ABI, functionName: "balanceOf", args: [account] })) + return () => handleAllowance({ token: asset.address, amount: postBal - asset.balance, account, spender: vault.address, clients }) + case 3: + postBal = Number(await clients.publicClient.readContract({ address: asset.address, abi: erc20ABI, functionName: "balanceOf", args: [account] })) + return () => vaultDeposit({ chainId, vault: vault.address, account, amount: postBal - asset.balance, clients }) + } + case ActionType.ZapWithdrawal: + switch (stepCounter) { + case 0: + return () => vaultRedeem({ chainId, vault: vault.address, account, amount, clients }) + case 1: + const ensoWallet = (await axios.get( + `https://api.enso.finance/api/v1/wallet?chainId=${chainId}&fromAddress=${account}`, + { headers: { Authorization: `Bearer ${process.env.ENSO_API_KEY}` } }) + ).data + return () => handleAllowance({ token: asset.address, amount, account, spender: getAddress(ensoWallet.address), clients }) + case 2: + postBal = Number(await clients.publicClient.readContract({ address: asset.address, abi: erc20ABI, functionName: "balanceOf", args: [account] })) + return () => zap({ chainId, sellToken: asset.address, buyToken: outputToken.address, amount: postBal - asset.balance, account, slippage, tradeTimeout, clients }) + } + case ActionType.ZapDepositAndStake: + switch (stepCounter) { + case 0: + const ensoWallet = (await axios.get( + `https://api.enso.finance/api/v1/wallet?chainId=${chainId}&fromAddress=${account}`, + { headers: { Authorization: `Bearer ${process.env.ENSO_API_KEY}` } }) + ).data + return () => handleAllowance({ token: inputToken.address, amount, account, spender: getAddress(ensoWallet.address), clients }) + case 1: + return () => zap({ chainId, sellToken: inputToken.address, buyToken: asset.address, amount, account, slippage, tradeTimeout, clients }) + case 2: + postBal = Number(await clients.publicClient.readContract({ address: asset.address, abi: erc20ABI, functionName: "balanceOf", args: [account] })) + return () => handleAllowance({ token: asset.address, amount: postBal - asset.balance, account, spender: VAULT_ROUTER, clients }) + case 3: + postBal = Number(await clients.publicClient.readContract({ address: asset.address, abi: erc20ABI, functionName: "balanceOf", args: [account] })) + return () => vaultDepositAndStake({ chainId, router: VAULT_ROUTER, vault: vault.address, gauge: gauge?.address as Address, account, amount: postBal - asset.balance, clients }) + } + case ActionType.ZapUnstakeAndWithdraw: + switch (stepCounter) { + case 0: + return () => handleAllowance({ token: inputToken.address, amount, account, spender: VAULT_ROUTER, clients }) + case 1: + return () => vaultUnstakeAndWithdraw({ chainId, router: VAULT_ROUTER, vault: vault.address, gauge: gauge?.address as Address, account, amount, clients }) + case 2: + const ensoWallet = (await axios.get( + `https://api.enso.finance/api/v1/wallet?chainId=${chainId}&fromAddress=${account}`, + { headers: { Authorization: `Bearer ${process.env.ENSO_API_KEY}` } }) + ).data + return () => handleAllowance({ token: asset.address, amount, account, spender: getAddress(ensoWallet.address), clients }) + case 3: + return () => zap({ chainId, sellToken: asset.address, buyToken: outputToken.address, amount, account, slippage, tradeTimeout, clients }) + } + default: + // We should never reach this code. This is here just to make ts happy + return async () => false + } +} \ No newline at end of file diff --git a/lib/vault/interactions.ts b/lib/vault/interactions.ts index bcc03ce..f1ecaa4 100644 --- a/lib/vault/interactions.ts +++ b/lib/vault/interactions.ts @@ -1,47 +1,35 @@ -import { showSuccessToast, showErrorToast, showLoadingToast } from "@/lib/toasts"; -import { SimulationResponse } from "@/lib/types"; +import { showLoadingToast } from "@/lib/toasts"; +import { Clients, SimulationResponse } from "@/lib/types"; import { VaultAbi } from "@/lib/constants"; -import { Address, PublicClient, WalletClient } from "viem"; +import { Address, PublicClient } from "viem"; import { VaultRouterAbi } from "@/lib/constants/abi/VaultRouter"; +import { handleCallResult } from "../utils/helpers"; interface VaultWriteProps { - address: Address; + chainId: number; + vault: Address; account: Address; amount: number; - publicClient: PublicClient; - walletClient: WalletClient; + clients: Clients; } -interface VaultSimulateProps { - address: Address; - account: Address; - amount: number; - functionName: string; - publicClient: PublicClient; +interface VaultRouterWriteProps extends VaultWriteProps { + router: Address; + gauge: Address; } -interface VaultRouterWriteProps { +interface VaultSimulateProps { address: Address; account: Address; amount: number; - vault: Address; - gauge: Address; + functionName: string; publicClient: PublicClient; - walletClient: WalletClient; } - -interface VaultRouterSimulateProps { - address: Address; - account: Address; - amount: number; +interface VaultRouterSimulateProps extends VaultSimulateProps { vault: Address; gauge: Address; - functionName: string; - publicClient: PublicClient; } - - async function simulateVaultCall({ address, account, amount, functionName, publicClient }: VaultSimulateProps): Promise { try { const { request } = await publicClient.simulateContract({ @@ -76,91 +64,43 @@ async function simulateVaultRouterCall({ address, account, amount, vault, gauge, } } -export async function vaultDeposit({ address, account, amount, publicClient, walletClient }: VaultWriteProps): Promise { +export async function vaultDeposit({ chainId, vault, account, amount, clients }: VaultWriteProps): Promise { showLoadingToast("Depositing into the vault...") - const { request, success, error: simulationError } = await simulateVaultCall({ address, account, amount, functionName: "deposit", publicClient }) - - if (success) { - try { - const hash = await walletClient.writeContract(request) - const receipt = await publicClient.waitForTransactionReceipt({ hash }) - showSuccessToast("Deposited into the vault!") - return true; - } catch (error: any) { - showErrorToast(error.shortMessage) - return false; - } - } else { - showErrorToast(simulationError) - return false; - } + return handleCallResult({ + successMessage: "Deposited into the vault!", + simulationResponse: await simulateVaultCall({ address: vault, account, amount, functionName: "deposit", publicClient: clients.publicClient }), + clients + }) } -export async function vaultRedeem({ address, account, amount, publicClient, walletClient }: VaultWriteProps): Promise { +export async function vaultRedeem({ chainId, vault, account, amount, clients }: VaultWriteProps): Promise { showLoadingToast("Withdrawing from the vault...") - const { request, success, error: simulationError } = await simulateVaultCall({ address, account, amount, functionName: "redeem", publicClient }) - - if (success) { - try { - const hash = await walletClient.writeContract(request) - const receipt = await publicClient.waitForTransactionReceipt({ hash }) - showSuccessToast("Withdrawn from the vault!") - return true; - } catch (error: any) { - showErrorToast(error.shortMessage) - return false; - } - } else { - showErrorToast(simulationError) - return false; - } + return handleCallResult({ + successMessage: "Withdrawn from the vault!", + simulationResponse: await simulateVaultCall({ address: vault, account, amount, functionName: "redeem", publicClient: clients.publicClient }), + clients + }) } -export async function vaultDepositAndStake({ address, account, amount, vault, gauge, publicClient, walletClient }: VaultRouterWriteProps): Promise { +export async function vaultDepositAndStake({ chainId, router, vault, gauge, account, amount, clients }: VaultRouterWriteProps): Promise { showLoadingToast("Depositing into the vault...") - const { request, success, error: simulationError } = await simulateVaultRouterCall({ - address, account, amount, vault, gauge, functionName: "depositAndStake", publicClient + return handleCallResult({ + successMessage: "Deposited into the vault and staked into Gauge!", + simulationResponse: await simulateVaultRouterCall({ address: router, account, amount, vault, gauge, functionName: "depositAndStake", publicClient: clients.publicClient }), + clients }) - - if (success) { - try { - const hash = await walletClient.writeContract(request) - const receipt = await publicClient.waitForTransactionReceipt({ hash }) - showSuccessToast("Deposited into the vault!") - return true; - } catch (error: any) { - showErrorToast(error.shortMessage) - return false; - } - } else { - showErrorToast(simulationError) - return false; - } } -export async function vaultUnstakeAndWithdraw({ address, account, amount, vault, gauge, publicClient, walletClient }: VaultRouterWriteProps): Promise { +export async function vaultUnstakeAndWithdraw({ chainId, router, vault, gauge, account, amount, clients }: VaultRouterWriteProps): Promise { showLoadingToast("Withdrawing from the vault...") - const { request, success, error: simulationError } = await simulateVaultRouterCall({ - address, account, amount, vault, gauge, functionName: "unstakeAndWithdraw", publicClient + return handleCallResult({ + successMessage: "Unstaked from Gauge and withdrawn from Vault!", + simulationResponse: await simulateVaultRouterCall({ address: router, account, amount, vault, gauge, functionName: "unstakeAndWithdraw", publicClient: clients.publicClient }), + clients }) - - if (success) { - try { - const hash = await walletClient.writeContract(request) - const receipt = await publicClient.waitForTransactionReceipt({ hash }) - showSuccessToast("Withdrawn from the vault!") - return true; - } catch (error: any) { - showErrorToast(error.shortMessage) - return false; - } - } else { - showErrorToast(simulationError) - return false; - } } \ No newline at end of file diff --git a/lib/vault/zap.ts b/lib/vault/zap.ts new file mode 100644 index 0000000..3ff1faa --- /dev/null +++ b/lib/vault/zap.ts @@ -0,0 +1,33 @@ +import axios from "axios" +import { Address, PublicClient, WalletClient, getAddress } from "viem"; +import { showErrorToast, showSuccessToast } from "@/lib/toasts"; +import { handleAllowance } from "@/lib/approve"; +import { Clients } from "../types"; + +interface ZapProps { + chainId: number; + sellToken: Address; + buyToken: Address; + amount: number; + account: Address; + slippage?: number; // slippage allowance in BPS + tradeTimeout?: number; // in s + clients: Clients; +} + +export default async function zap({ chainId, sellToken, buyToken, amount, account, slippage = 100, tradeTimeout = 60, clients }: ZapProps): Promise { + const quote = (await axios.get( + `https://api.enso.finance/api/v1/shortcuts/route?chainId=${chainId}&fromAddress=${account}&spender=${account}&receiver=${account}&amountIn=${amount.toLocaleString("fullwide", { useGrouping: false })}&slippage=${slippage}&tokenIn=${sellToken}&tokenOut=${buyToken}`, + { headers: { Authorization: `Bearer ${process.env.ENSO_API_KEY}` } } + )).data + try { + const hash = await clients.walletClient.sendTransaction(quote.tx) + const receipt = await clients.publicClient.waitForTransactionReceipt({ hash }) + showSuccessToast("Zapped successfully") + return true; + } catch (error: any) { + console.log(error) + showErrorToast(error.shortMessage) + return false; + } +} \ No newline at end of file diff --git a/next.config.js b/next.config.js index 9ef6557..b9faa02 100644 --- a/next.config.js +++ b/next.config.js @@ -9,18 +9,12 @@ module.exports = { ignoreBuildErrors: true, }, env: { - RPC_URL: process.env.RPC_URL, - CHAIN_ID: process.env.CHAIN_ID, - APP_ENV: process.env.APP_ENV, - INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID, - ETHERSCAN_API_KEY: process.env.ETHERSCAN_API_KEY, PINATA_API_SECRET: process.env.PINATA_API_SECRET, PINATA_API_KEY: process.env.PINATA_API_KEY, IPFS_URL: process.env.IPFS_URL, DUNE_API_KEY: process.env.DUNE_API_KEY, - NEXT_PUBLIC_ENABLE_TESTNETS: process.env.ENABLE_TESTNETS, - NEXT_PUBLIC_ALCHEMY_API_KEY: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY, - NEXT_PUBLIC_ZERION_KEY: process.env.ZERION_KEY, + ALCHEMY_API_KEY: process.env.ALCHEMY_API_KEY, + ENSO_API_KEY:process.env.ENSO_API_KEY, }, images: { domains: ["rawcdn.githack.com"], diff --git a/package.json b/package.json index ed32cf9..fb5e999 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@tailwindcss/forms": "^0.5.6", "autoprefixer": "^10.4.13", "axios": "^1.3.6", + "date-fns": "^2.30.0", "dotenv": "^16.0.3", "find-config": "^1.0.0", "highcharts": "^11.1.0", @@ -25,6 +26,7 @@ "marked-react": "^1.3.2", "next": "^13.5.2", "path": "^0.12.7", + "rc-slider": "^10.3.1", "rc-tooltip": "^6.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -33,9 +35,9 @@ "slick-carousel": "^1.8.1", "tailwind-scrollbar-hide": "^1.1.7", "tailwindcss": "^3.2.6", - "vaultcraft-sdk": "0.1.14", - "viem": "1.11.1", - "wagmi": "1.4.2" + "vaultcraft-sdk": "0.1.17", + "viem": "1.18.9", + "wagmi": "1.4.5" }, "devDependencies": { "@types/node": "^17.0.35", diff --git a/pages/_app.tsx b/pages/_app.tsx index 1ab8ef2..deace63 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -22,7 +22,7 @@ import { const { chains, publicClient } = configureChains(SUPPORTED_NETWORKS, [ alchemyProvider({ - apiKey: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY as string, + apiKey: process.env.ALCHEMY_API_KEY as string, }), jsonRpcProvider({ rpc: (chain) => ({ http: chain.rpcUrls.default.http[0] }) })], { @@ -36,17 +36,17 @@ const connectors = connectorsForWallets([ groupName: 'Suggested', wallets: [ injectedWallet({ chains }), - rainbowWallet({ projectId:'b2f883ab9ae2fbb812cb8e0d83efea7b', chains }), - metaMaskWallet({ projectId:'b2f883ab9ae2fbb812cb8e0d83efea7b', chains }), + rainbowWallet({ projectId: 'b2f883ab9ae2fbb812cb8e0d83efea7b', chains }), + metaMaskWallet({ projectId: 'b2f883ab9ae2fbb812cb8e0d83efea7b', chains }), ], }, { groupName: 'Others', wallets: [ coinbaseWallet({ chains, appName: 'Popcorn' }), - walletConnectWallet({ projectId:'b2f883ab9ae2fbb812cb8e0d83efea7b', chains }), - coin98Wallet({ projectId:'b2f883ab9ae2fbb812cb8e0d83efea7b', chains }) - ] + walletConnectWallet({ projectId: 'b2f883ab9ae2fbb812cb8e0d83efea7b', chains }), + coin98Wallet({ projectId: 'b2f883ab9ae2fbb812cb8e0d83efea7b', chains }) + ] } ]); @@ -100,9 +100,9 @@ export default function MyApp(props: any) { - - {getLayout()} - + + {getLayout()} + diff --git a/pages/boost.tsx b/pages/boost.tsx new file mode 100644 index 0000000..f12c411 --- /dev/null +++ b/pages/boost.tsx @@ -0,0 +1,140 @@ +// @ts-ignore +import NoSSR from "react-no-ssr"; +import { mainnet, useAccount, useBalance, usePublicClient, useWalletClient } from "wagmi"; +import { Address, WalletClient } from "viem"; +import { useEffect, useState } from "react"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { hasAlreadyVoted } from "@/lib/gauges/hasAlreadyVoted"; +import { Token, VaultData } from "@/lib/types"; +import { getVaultsByChain } from "@/lib/vault/getVault"; +import StakingInterface from "@/components/vepop/StakingInterface"; +import { sendVotes } from "@/lib/gauges/interactions"; +import Gauge from "@/components/vepop/Gauge"; +import LockModal from "@/components/vepop/modals/lock/LockModal"; +import ManageLockModal from "@/components/vepop/modals/manage/ManageLockModal"; +import OPopModal from "@/components/vepop/modals/oPop/OPopModal"; +import OPopInterface from "@/components/vepop/OPopInterface"; +import { vaultsAtom } from "@/lib/atoms/vaults"; +import { useAtom } from "jotai"; + +const { VotingEscrow: VOTING_ESCROW } = getVeAddresses(); + +function VePopContainer() { + const { address: account } = useAccount() + const publicClient = usePublicClient(); + const { data: walletClient } = useWalletClient() + + const { data: veBal } = useBalance({ chainId: 1, address: account, token: VOTING_ESCROW, watch: true }) + + const [initalLoad, setInitalLoad] = useState(false); + const [accountLoad, setAccountLoad] = useState(false); + + const [vaults, setVaults] = useAtom(vaultsAtom) + const [votes, setVotes] = useState([]); + const [canVote, setCanVote] = useState(false); + + const [showLockModal, setShowLockModal] = useState(false); + const [showMangementModal, setShowMangementModal] = useState(false); + const [showOPopModal, setShowOPopModal] = useState(false); + + useEffect(() => { + async function initialSetup() { + setInitalLoad(true) + if (account) setAccountLoad(true) + + const vaultsWithGauges = vaults.filter(vault => !!vault.gauge) + setVaults(vaultsWithGauges); + if (vaultsWithGauges.length > 0 && votes.length === 0 && publicClient.chain.id === 1) { + setVotes(vaultsWithGauges.map(gauge => 0)); + + const hasVoted = await hasAlreadyVoted({ + addresses: vaultsWithGauges?.map((vault: VaultData) => vault.gauge?.address as Address), + publicClient, + account: account as Address + }) + setCanVote(!!account && Number(veBal?.value) > 0 && !hasVoted) + } + } + if (!account && !initalLoad && vaults.length > 0) initialSetup(); + if (account && !accountLoad && vaults.length > 0) initialSetup() + }, [account, initalLoad, accountLoad, vaults]) + + function handleVotes(val: number, index: number) { + const updatedVotes = [...votes]; + const updatedTotalVotes = updatedVotes.reduce((a, b) => a + b, 0) - updatedVotes[index] + val; + + if (updatedTotalVotes <= 10000) { + // TODO should we adjust the val to the max possible value if it exceeds 10000? + updatedVotes[index] = val; + } + + setVotes((prevVotes) => updatedVotes); + } + + return ( + <> + + + +
+
+
+

+ Lock 20WETH-80VCX for veVCX, voting Power & oVCX +

+

+ Vote with your veVCX below to influence how much $oVCX each pool will receive. Your vote will persist until you change it and editing a pool can only be done once every 10 days. +

+
+
+ +
+ + 0 ? vaults.filter(vault => !!vault.gauge?.address).map((vault: VaultData) => vault.gauge as Token) : []} + setShowOPopModal={setShowOPopModal} + /> +
+ +
+ {vaults?.length > 0 ? vaults.filter(vault => !!vault.gauge?.address).map((vault: VaultData, index: number) => + + ) + :

Loading Gauges...

+ } +
+ +
+

Gauge Voting not available on mobile.

+
+ +
+ {canVote && <> +
+

+ Voting power used: + { + veBal && veBal.value + ? (votes?.reduce((a, b) => a + b, 0) / 100).toFixed(2) + : "0" + }% + +

+ +
+ } +
+ +
+ + ) +} + +export default function VeVCX() { + return +} diff --git a/pages/disclaimer.tsx b/pages/disclaimer.tsx index c6b737e..568ce34 100644 --- a/pages/disclaimer.tsx +++ b/pages/disclaimer.tsx @@ -32,7 +32,7 @@ export default function DisclaimerPage(): JSX.Element { factual relationship with any User of the Popcorn Software. Consequently, pop.network is not liable to any user for damages, including any general, special, incidental, or consequential damages arising out of the use, in connection with the use or inability to use the Popcorn Software (including but not limited to loss of - POP, USDC, USDT, DAI, 3CRV, XEN, 3X, BTR, Arrakis USDC/POP LP, loss of data, business interruption, data being + POP, VCX, USDC, USDT, DAI, 3CRV, XEN, 3X, BTR, Arrakis USDC/POP LP, VCX LP, loss of data, business interruption, data being rendered inaccurate or losses sustained by a user or third parties.

diff --git a/pages/experimental/vaults.tsx b/pages/experimental/vaults.tsx index d89f813..666744e 100644 --- a/pages/experimental/vaults.tsx +++ b/pages/experimental/vaults.tsx @@ -2,63 +2,202 @@ import NoSSR from "react-no-ssr"; import { useEffect, useState } from "react"; import type { NextPage } from "next"; -import { useAccount } from "wagmi"; +import { Address, useAccount, useBalance, usePublicClient, useWalletClient } from "wagmi"; import { MagnifyingGlassIcon } from "@heroicons/react/24/outline"; -import { ChainId, SUPPORTED_NETWORKS } from "@/lib/utils/connectors"; +import { SUPPORTED_NETWORKS } from "@/lib/utils/connectors"; import { NumberFormatter } from "@/lib/utils/formatBigNumber"; import useNetworkFilter from "@/lib/useNetworkFilter"; -import getVaultNetworth from "@/lib/vault/getVaultNetworth"; import useVaultTvl from "@/lib/useVaultTvl"; -import { getVaultsByChain } from "@/lib/vault/getVault"; -import { VaultData } from "@/lib/types"; +import { Token, VaultData } from "@/lib/types"; import SmartVault from "@/components/vault/SmartVault"; import NetworkFilter from "@/components/network/NetworkFilter"; +import MainActionButton from "@/components/button/MainActionButton"; +import getGaugeRewards, { GaugeRewards } from "@/lib/gauges/getGaugeRewards"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { claimOPop } from "@/lib/oPop/interactions"; +import { WalletClient } from "viem"; +import getZapAssets, { getAvailableZapAssets } from "@/lib/utils/getZapAssets"; +import { ERC20Abi, VaultAbi } from "@/lib/constants"; +import { getVaultNetworthByChain } from "@/lib/getNetworth"; +import { useAtom } from "jotai"; +import { vaultsAtom } from "@/lib/atoms/vaults"; +import VaultsSorting, { VAULT_SORTING_TYPE } from "@/components/vault/VaultsSorting"; export const HIDDEN_VAULTS = ["0xb6cED1C0e5d26B815c3881038B88C829f39CE949", "0x2fD2C18f79F93eF299B20B681Ab2a61f5F28A6fF", "0xDFf04Efb38465369fd1A2E8B40C364c22FfEA340", "0xd4D442AC311d918272911691021E6073F620eb07", //@dev for some reason the live 3Crypto yVault isnt picked up by the yearnAdapter nor the yearnFactoryAdapter "0x8bd3D95Ec173380AD546a4Bd936B9e8eCb642de1", // Sample Stargate Vault "0xcBb5A4a829bC086d062e4af8Eba69138aa61d567", // yOhmFrax factory "0x9E237F8A3319b47934468e0b74F0D5219a967aB8", // yABoosted Balancer - "0x860b717B360378E44A241b23d8e8e171E0120fF0", // R/Dai + "0x860b717B360378E44A241b23d8e8e171E0120fF0", // R/Dai + "0xBae30fBD558A35f147FDBaeDbFF011557d3C8bd2", // 50OHM - 50 DAI + "0xa6fcC7813d9D394775601aD99874c9f8e95BAd78", // Automated Pool Token - Oracle Vault 3 ] +const { oVCX } = getVeAddresses(); + +const NETWORKS_SUPPORTING_ZAP = [1] + +export interface MutateTokenBalanceProps { + inputToken: Address; + outputToken: Address; + vault: Address; + chainId: number; + account: Address; +} + const Vaults: NextPage = () => { const { address: account } = useAccount(); + const publicClient = usePublicClient() + const { data: walletClient } = useWalletClient() const [initalLoad, setInitalLoad] = useState(false); const [accountLoad, setAccountLoad] = useState(false); const [selectedNetworks, selectNetwork] = useNetworkFilter(SUPPORTED_NETWORKS.map(network => network.id)); - const [vaults, setVaults] = useState([]); + + const [vaults, setVaults] = useAtom(vaultsAtom) + + const [zapAssets, setZapAssets] = useState<{ [key: number]: Token[] }>({}); + const [availableZapAssets, setAvailableZapAssets] = useState<{ [key: number]: Address[] }>({}) + const vaultTvl = useVaultTvl(); + const [networth, setNetworth] = useState(0); + + const [gaugeRewards, setGaugeRewards] = useState() + const { data: oBal } = useBalance({ chainId: 1, address: account, token: oVCX, watch: true }) const [searchString, handleSearch] = useState(""); + const [sortingType, setSortingType] = useState(VAULT_SORTING_TYPE.none) useEffect(() => { async function getVaults() { setInitalLoad(true) if (account) setAccountLoad(true) - const fetchedVaults = await Promise.all( - SUPPORTED_NETWORKS.map(async (chain) => getVaultsByChain({ chain, account })) - ); - setVaults(fetchedVaults.flat()); + // get zap assets + const newZapAssets: { [key: number]: Token[] } = {} + SUPPORTED_NETWORKS.forEach(async (chain) => newZapAssets[chain.id] = await getZapAssets({ chain, account })) + setZapAssets(newZapAssets); + + // get available zapAddresses + setAvailableZapAssets({ + 1: await getAvailableZapAssets(1), + 137: await getAvailableZapAssets(137), + 10: await getAvailableZapAssets(10), + 42161: await getAvailableZapAssets(42161), + 56: await getAvailableZapAssets(56) + }) + + // get gauge rewards + if (account) { + const rewards = await getGaugeRewards({ + gauges: vaults.filter(vault => vault.gauge && vault.chainId === 1).map(vault => vault.gauge?.address) as Address[], + account: account as Address, + publicClient + }) + setGaugeRewards(rewards) + } + setNetworth(SUPPORTED_NETWORKS.map(chain => getVaultNetworthByChain({ vaults, chainId: chain.id })).reduce((a, b) => a + b, 0)); } - if (!account && !initalLoad) getVaults(); - if (account && !accountLoad) getVaults() - }, [account]) + if (!account && !initalLoad && vaults.length > 0) getVaults(); + if (account && !accountLoad && vaults.length > 0) getVaults() + }, [account, initalLoad, accountLoad, vaults]) - const [networth, setNetworth] = useState(0); - const [loading, setLoading] = useState(true); + async function mutateTokenBalance({ inputToken, outputToken, vault, chainId, account }: MutateTokenBalanceProps) { + const data = await publicClient.multicall({ + contracts: [ + { + address: inputToken, + abi: ERC20Abi, + functionName: "balanceOf", + args: [account] + }, + { + address: outputToken, + abi: ERC20Abi, + functionName: "balanceOf", + args: [account] + }, + { + address: vault, + abi: VaultAbi, + functionName: 'totalAssets' + }, + { + address: vault, + abi: VaultAbi, + functionName: 'totalSupply' + }], + allowFailure: false + }) - useEffect(() => { - if (account && loading) - // fetch and set networth - getVaultNetworth({ account }).then(res => { - setNetworth(res.total); - setLoading(false); - }); - }, [account]); + // Modify zap assets + if (NETWORKS_SUPPORTING_ZAP.includes(chainId)) { + const zapAssetFound = zapAssets[chainId].find(asset => asset.address === inputToken || asset.address === outputToken) // @dev -- might need to copy the state here already to avoid modifing a pointer + if (zapAssetFound) { + zapAssetFound.balance = zapAssetFound.address === inputToken ? Number(data[0]) : Number(data[1]) + setZapAssets({ ...zapAssets, [chainId]: [...zapAssets[chainId], zapAssetFound] }) + } + } + + // Modify vaults, assets and gauges + const newVaultState: VaultData[] = [...vaults] + newVaultState.forEach(vaultData => { + if (vaultData.chainId === chainId) { + // Modify vault pricing and tvl + if (vaultData.address === vault) { + const assetsPerShare = Number(data[3]) > 0 ? Number(data[2]) / Number(data[3]) : Number(1e-9) + const pricePerShare = assetsPerShare * vaultData.assetPrice + + vaultData.totalAssets = Number(data[2]) + vaultData.totalSupply = Number(data[3]) + vaultData.assetsPerShare = assetsPerShare + vaultData.pricePerShare = pricePerShare + vaultData.tvl = (Number(data[3]) * pricePerShare) / (10 ** vaultData.asset.decimals) + vaultData.vault.price = pricePerShare * 1e9 + + if (vaultData.gauge) vaultData.gauge.price = pricePerShare * 1e9 + } + // Adjust vault balance + if (vaultData.vault.address === inputToken || vaultData.vault.address === outputToken) { + vaultData.vault.balance = vaultData.vault.address === inputToken ? Number(data[0]) : Number(data[1]) + } + // Adjust asset balance + if (vaultData.asset.address === inputToken || vaultData.asset.address === outputToken) { + vaultData.asset.balance = vaultData.asset.address === inputToken ? Number(data[0]) : Number(data[1]) + } + // Adjust gauge balance + if (vaultData.gauge?.address === inputToken || vaultData.gauge?.address === outputToken) { + vaultData.gauge.balance = vaultData.gauge.address === inputToken ? Number(data[0]) : Number(data[1]) + } + } + }) + setVaults(newVaultState) + } + + const sortByAscendingTvl = () => { + const sortedVaults = [...vaults].sort((a, b) => b.tvl - a.tvl); + setSortingType(VAULT_SORTING_TYPE.mostTvl) + setVaults(sortedVaults) + } + + const sortByDescendingTvl = () => { + const sortedVaults = [...vaults].sort((a, b) => a.tvl - b.tvl); + setSortingType(VAULT_SORTING_TYPE.lessTvl) + setVaults(sortedVaults) + } + + const sortByAscendingApy = () => { + const sortedVaults = [...vaults].sort((a, b) => b.apy - a.apy); + setSortingType(VAULT_SORTING_TYPE.mostvAPR) + setVaults(sortedVaults) + } + + const sortByDescendingApy = () => { + const sortedVaults = [...vaults].sort((a, b) => a.apy - b.apy); + setSortingType(VAULT_SORTING_TYPE.lessvAPR) + setVaults(sortedVaults) + } return ( @@ -73,8 +212,8 @@ const Vaults: NextPage = () => {

-
-
+
+

TVL

@@ -85,38 +224,83 @@ const Vaults: NextPage = () => {

Deposits

- {`$${loading ? "..." : NumberFormatter.format(networth)}`} + {`$${NumberFormatter.format(networth)}`} +
+
+
+ +
+
+

My oVCX

+
+ {`${oBal ? NumberFormatter.format(Number(oBal?.value) / 1e18) : "0"}`} +
+
+ +
+

Claimable oVCX

+
+ {`$${gaugeRewards ? NumberFormatter.format(Number(gaugeRewards?.total) / 1e18) : "0"}`}
+ +
+ + claimOPop({ + gauges: gaugeRewards?.amounts?.filter(gauge => Number(gauge.amount) > 0).map(gauge => gauge.address) as Address[], + account: account as Address, + clients: { publicClient, walletClient: walletClient as WalletClient } + })} + /> +
+
+
+ + claimOPop({ + gauges: gaugeRewards?.amounts?.filter(gauge => Number(gauge.amount) > 0).map(gauge => gauge.address) as Address[], + account: account as Address, + clients: { publicClient, walletClient: walletClient as WalletClient } + })} + />
-
+
chain.id)} selectNetwork={selectNetwork} /> -
- - handleSearch(e.target.value.toLowerCase())} - defaultValue={searchString} - /> +
+
+ + handleSearch(e.target.value.toLowerCase())} + defaultValue={searchString} + /> +
+
+
- {vaults.length > 0 ? vaults.filter(vault => selectedNetworks.includes(vault.chainId)).filter(vault => !HIDDEN_VAULTS.includes(vault.address)).map((vault) => { + {(vaults.length > 0 && Object.keys(availableZapAssets).length > 0) ? vaults.filter(vault => selectedNetworks.includes(vault.chainId)).filter(vault => !HIDDEN_VAULTS.includes(vault.address)).map((vault) => { return ( ) }) - :

Loading Vaults...

+ :

Loading Vaults...

}
diff --git a/pages/migration.tsx b/pages/migration.tsx new file mode 100644 index 0000000..74830f3 --- /dev/null +++ b/pages/migration.tsx @@ -0,0 +1,185 @@ +import MainActionButton from "@/components/button/MainActionButton"; +import InputTokenWithError from "@/components/input/InputTokenWithError"; +import { handleAllowance } from "@/lib/approve"; +import { ROUNDING_VALUE, VCXAbi } from "@/lib/constants"; +import { showErrorToast, showLoadingToast, showSuccessToast } from "@/lib/toasts"; +import { SimulationResponse } from "@/lib/types"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { validateInput } from "@/lib/utils/helpers"; +import { ArrowDownIcon } from "@heroicons/react/24/outline"; +import { useState } from "react"; +import { Address, WalletClient, formatEther, zeroAddress } from "viem"; +import { PublicClient, useAccount, useBalance, useNetwork, usePublicClient, useSwitchNetwork, useWalletClient } from "wagmi"; + +const { VCX, POP } = getVeAddresses(); + +interface SimulateProps { + address: Address; + account: Address; + amount: number; + publicClient: PublicClient; +} + +interface MigrateWriteProps { + address: Address; + account: Address; + amount: number; + publicClient: PublicClient; + walletClient: WalletClient; +} + +async function simulate({ address, account, amount, publicClient }: SimulateProps): Promise { + try { + const { request } = await publicClient.simulateContract({ + account, + address, + abi: VCXAbi, + // @ts-ignore + functionName: "migrate", + // @dev Since numbers get converted to strings like 1e+21 or similar we need to convert it back to numbers like 10000000000000 and than cast them into BigInts + args: [account, BigInt(Number(amount).toLocaleString("fullwide", { useGrouping: false }))] + }) + return { request: request, success: true, error: null } + } catch (error: any) { + return { request: null, success: false, error: error.shortMessage } + } +} + +async function migrate({ address, account, amount, publicClient, walletClient }: MigrateWriteProps): Promise { + showLoadingToast("Migrating POP to VCX...") + + const { request, success, error: simulationError } = await simulate({ address, account, amount, publicClient }) + + if (success) { + try { + const hash = await walletClient.writeContract(request) + const receipt = await publicClient.waitForTransactionReceipt({ hash }) + showSuccessToast("Migration sucessful!") + return true; + } catch (error: any) { + showErrorToast(error.shortMessage) + return false; + } + } else { + showErrorToast(simulationError) + return false; + } +} + +export default function Migration(): JSX.Element { + const { address: account } = useAccount(); + const publicClient = usePublicClient() + const { data: walletClient } = useWalletClient() + const { chain } = useNetwork(); + const { switchNetwork } = useSwitchNetwork(); + + const { data: vcxBal } = useBalance({ chainId: 1, address: account || zeroAddress, token: VCX, watch: true }) + const { data: popBal } = useBalance({ chainId: 1, address: account || zeroAddress, token: POP, watch: true }) + + const [inputBalance, setInputBalance] = useState("0"); + + function handleChangeInput(e: any) { + const value = e.currentTarget.value + setInputBalance(validateInput(value).isValid ? value : "0"); + }; + + async function handleMainAction() { + const val = Number(inputBalance) + if (val === 0 || !account || !walletClient) return; + + if (chain?.id !== 1) switchNetwork?.(1); + + await handleAllowance({ + token: POP, + amount: (val * (10 ** 18)), + account, + spender: VCX, + clients: { + publicClient, + walletClient + } + }) + migrate({ + address: VCX, + account, + amount: (val * (10 ** 18)), + publicClient, + walletClient + }) + } + + return ( + <> +
+

+ POP Migration +

+

+ Migrate your POP to VCX +

+
+
+ {(vcxBal && popBal) ? +
+ { }} + onMaxClick={() => handleChangeInput({ currentTarget: { value: Math.round(Number(formatEther(popBal.value)) * ROUNDING_VALUE) / ROUNDING_VALUE } })} + chainId={1} + value={inputBalance} + onChange={handleChangeInput} + selectedToken={{ + address: POP, + name: "POP", + symbol: "POP", + decimals: 18, + logoURI: "", + balance: Number(popBal.value), + price: 1, + }} + errorMessage={""} + tokenList={[]} + allowInput + /> +
+ + { }} + onMaxClick={() => { }} + chainId={1} + value={(Number(inputBalance) * 10) || 0} + onChange={() => { }} + selectedToken={{ + address: VCX, + name: "VCX", + symbol: "VCX", + decimals: 18, + logoURI: "/images/tokens/vcx.svg", + balance: 0, + price: 1, + }} + errorMessage={""} + tokenList={[]} + allowSelection={false} + allowInput={false} + /> + +
+ :

Loading...

+ } +
+ + ) +} \ No newline at end of file diff --git a/pages/stats.tsx b/pages/stats.tsx index d5a6323..2097236 100644 --- a/pages/stats.tsx +++ b/pages/stats.tsx @@ -88,7 +88,6 @@ export default function Vaults() { }[] totalRevenue: number cPopRevenue: number - publicGoodFunding: number weekCexVolume: number weekDexVolume: number walletsPopMoreZero: number @@ -122,7 +121,6 @@ export default function Vaults() { tvlMonthByMonth: [], totalRevenue: 0, cPopRevenue: 0, - publicGoodFunding: 0, weekCexVolume: 0, weekDexVolume: 0, walletsPopMoreZero: 0, @@ -401,7 +399,7 @@ export default function Vaults() { color: "#9B55FF" }, { - name: "POP in 80/20 BAL pool, USD", + name: "VCX in 80/20 BAL pool, USD", y: 80, //Number(popInBalPool?.token?.latestUSDPrice) * Number(popInBalPool?.balance), color: "#7AFB79" }, @@ -441,7 +439,7 @@ export default function Vaults() {

Popcorn Statistics

-

Total Stats start from 23 June 2023.

+

Total Stats start from 30 November 2023

@@ -461,11 +459,11 @@ export default function Vaults() {

${statistics.marketCap.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })}

-

POP Price

+

VCX Price

${statistics.popPrice.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })}

-

Burned POP

+

Burned VCX

Coming Soon

@@ -473,14 +471,14 @@ export default function Vaults() {
Logo
-

POPCORN

-

Liquid POP market (Mainnet only)

+

VCX

+

Liquid VCX market (Mainnet only)

-

POP in 80/20 BAL pool

+

VCX in 80/20 BAL pool

Coming Soon {/*statistics.popInBalPool.toLocaleString()*/}

@@ -492,15 +490,15 @@ export default function Vaults() {

Coming Soon {/*statistics.balLp.toLocaleString()*/}

-

vePOP (staked LPs)

+

veVCX (staked LPs)

Coming Soon {/*statistics.vePop.toLocaleString()*/}

-

cPOP emissions

+

oVCX emissions

Coming Soon {/*statistics.cPopEmissions.toLocaleString()*/}

-

cPOP exercised

+

oVCX exercised

Coming Soon {/*(statistics.cPopExercised * 100).toLocaleString() %*/}

@@ -541,17 +539,13 @@ export default function Vaults() {

Coming Soon

-

cPOP Revenue

+

oVCX Revenue

Coming Soon {/*statistics.cPopRevenue.toLocaleString()*/}

Total Users

{statistics.walletsPopMoreZero.toLocaleString()}

-
-

Public Good Funding

-

${statistics.publicGoodFunding.toLocaleString()}

-

7 Day Cex Volume

${statistics.weekCexVolume.toLocaleString()}

@@ -561,19 +555,19 @@ export default function Vaults() {

${statistics.weekDexVolume.toLocaleString()}

-

{'Wallets with POP > 100'}

+

{'Wallets with VCX > 100'}

{statistics.walletsPopMoreHundred.toLocaleString()}

-

{'Wallets with POP > 1,000'}

+

{'Wallets with VCX > 1,000'}

{statistics.walletsPopMoreThousand.toLocaleString()}

-

{'Wallets with POP > 100,000'}

+

{'Wallets with VCX > 100,000'}

{statistics.walletsPopMoreHundredThousand.toLocaleString()}

-

{'Wallets with POP > 1,000,000'}

+

{'Wallets with VCX > 1,000,000'}

{statistics.walletsPopMoreMillion.toLocaleString()}

diff --git a/pages/vaults.tsx b/pages/vaults.tsx index 570f312..6a8fa86 100644 --- a/pages/vaults.tsx +++ b/pages/vaults.tsx @@ -2,63 +2,219 @@ import NoSSR from "react-no-ssr"; import { useEffect, useState } from "react"; import type { NextPage } from "next"; -import { useAccount } from "wagmi"; +import { Address, useAccount, useBalance, usePublicClient, useWalletClient } from "wagmi"; import { MagnifyingGlassIcon } from "@heroicons/react/24/outline"; -import { ChainId, SUPPORTED_NETWORKS } from "@/lib/utils/connectors"; +import { SUPPORTED_NETWORKS } from "@/lib/utils/connectors"; import { NumberFormatter } from "@/lib/utils/formatBigNumber"; import useNetworkFilter from "@/lib/useNetworkFilter"; -import getVaultNetworth from "@/lib/vault/getVaultNetworth"; import useVaultTvl from "@/lib/useVaultTvl"; -import { getVaultsByChain } from "@/lib/vault/getVault"; -import { VaultData } from "@/lib/types"; +import { Token, VaultData } from "@/lib/types"; import SmartVault from "@/components/vault/SmartVault"; import NetworkFilter from "@/components/network/NetworkFilter"; +import MainActionButton from "@/components/button/MainActionButton"; +import getGaugeRewards, { GaugeRewards } from "@/lib/gauges/getGaugeRewards"; +import { getVeAddresses } from "@/lib/utils/addresses"; +import { claimOPop } from "@/lib/oPop/interactions"; +import { WalletClient } from "viem"; +import getZapAssets, { getAvailableZapAssets } from "@/lib/utils/getZapAssets"; +import { ERC20Abi, VaultAbi } from "@/lib/constants"; +import { getVaultNetworthByChain } from "@/lib/getNetworth"; +import { useAtom } from "jotai"; +import { vaultsAtom } from "@/lib/atoms/vaults"; +import VaultsSorting, { VAULT_SORTING_TYPE } from "@/components/vault/VaultsSorting"; -export const HIDDEN_VAULTS = ["0xb6cED1C0e5d26B815c3881038B88C829f39CE949", "0x2fD2C18f79F93eF299B20B681Ab2a61f5F28A6fF", - "0xDFf04Efb38465369fd1A2E8B40C364c22FfEA340", "0xd4D442AC311d918272911691021E6073F620eb07", //@dev for some reason the live 3Crypto yVault isnt picked up by the yearnAdapter nor the yearnFactoryAdapter - "0x8bd3D95Ec173380AD546a4Bd936B9e8eCb642de1", // Sample Stargate Vault - "0xcBb5A4a829bC086d062e4af8Eba69138aa61d567", // yOhmFrax factory - "0x9E237F8A3319b47934468e0b74F0D5219a967aB8", // yABoosted Balancer - "0x860b717B360378E44A241b23d8e8e171E0120fF0", // R/Dai +const FLAGSHIP_VAULTS = [ + // eth + "0x6cE9c05E159F8C4910490D8e8F7a63e95E6CEcAF", // DAI IdleJunior + "0x52Aef3ea0D3F93766D255A1bb0aA7F1C4885E622", // USDC IdleJunior + "0x3D04Aade5388962C9A4f83B636a3a8ED63ea5b4D", // USDT IdleJunior + "0xdC266B3D2c62Ce094ff4E12DC52399c430283417", // pCVX Pirex + "0x6B2c5ef7FB59e6A1Ad79a4dB65234fb7bDDcaD6b", // oETH-LP Beefy + "0xD211486ed1A04A176E588b67dd3A30a7dE164C0B", // WETH-AURA Beefy + "0xA3cd112fFb1E3A358EF270a07F5901FF0fD1CD0f", // MIM Yearn + "0xe1489Af32c45c51f94Acdb3F36B7032A82F6f55D", // WETH Sommelier + "0x759281a408A48bfe2029D259c23D7E848A7EA1bC", // yCRV Yearn + // op + "0x5Df527eb4cE7dE09f8e966F9bbc9bc4Edbc7f458", // USDT IdleSenior + "0x78C44B3A63b94d2EFc98c2Cc9701F9BEE1b6a56A", // USDT IdleJunior + "0x5372c5AF5f078f2d4B5dbBE4377b2f0225f2863A", // USDC IdleSenior + "0x4E564bC61Cf97737cE110c7929b17963E9232aE9", // USDC IdleJunior + "0x400a838eeA2ec6Daf6fA30d7Bc60505f0CecCec1", // wstETH/WETH Beefy + "0x5D45accb18A88895aCac95F13a2882C273E22e3A", // USDC/VELO Beefy + "0x740dc6c1eA74BbbadCCA0aB6253319e200c421a5", // STG/USDC Beefy + "0x48b2Bc0C40F4483EC982408F06Dc0E1e111D966b", // USDC/DOLA Beefy + "0x1F01c6bFDE973be1573AbFC1B6b1dFb1D8F22A86", // wstETH/OP Beefy + "0x0825bb2F6Ce26af1652584F1Da9e55e54015904A", // OP/USDC Beefy + // arb + "0x54d921B6397731222aB0b898bAE58c948d187Cd1", // StakedGlp Beefy + "0x1225354B00372c531e1c39ECe1cec548358926bb", // pGMX Pirex ] +const { oVCX } = getVeAddresses(); + +const NETWORKS_SUPPORTING_ZAP = [1, 137, 10, 42161, 56] + +export interface MutateTokenBalanceProps { + inputToken: Address; + outputToken: Address; + vault: Address; + chainId: number; + account: Address; +} + const Vaults: NextPage = () => { const { address: account } = useAccount(); + const publicClient = usePublicClient() + const { data: walletClient } = useWalletClient() const [initalLoad, setInitalLoad] = useState(false); const [accountLoad, setAccountLoad] = useState(false); const [selectedNetworks, selectNetwork] = useNetworkFilter(SUPPORTED_NETWORKS.map(network => network.id)); - const [vaults, setVaults] = useState([]); + + const [vaults, setVaults] = useAtom(vaultsAtom) + + const [zapAssets, setZapAssets] = useState<{ [key: number]: Token[] }>({}); + const [availableZapAssets, setAvailableZapAssets] = useState<{ [key: number]: Address[] }>({}) + const vaultTvl = useVaultTvl(); + const [networth, setNetworth] = useState(0); + + const [gaugeRewards, setGaugeRewards] = useState() + const { data: oBal } = useBalance({ chainId: 1, address: account, token: oVCX, watch: true }) const [searchString, handleSearch] = useState(""); + const [sortingType, setSortingType] = useState(VAULT_SORTING_TYPE.none) useEffect(() => { async function getVaults() { setInitalLoad(true) if (account) setAccountLoad(true) - const fetchedVaults = await Promise.all( - SUPPORTED_NETWORKS.map(async (chain) => getVaultsByChain({ chain, account })) - ); - setVaults(fetchedVaults.flat()); + // get zap assets + const newZapAssets: { [key: number]: Token[] } = {} + SUPPORTED_NETWORKS.forEach(async (chain) => newZapAssets[chain.id] = await getZapAssets({ chain, account })) + setZapAssets(newZapAssets); + + // get available zapAddresses + setAvailableZapAssets({ + 1: await getAvailableZapAssets(1), + 137: await getAvailableZapAssets(137), + 10: await getAvailableZapAssets(10), + 42161: await getAvailableZapAssets(42161), + 56: await getAvailableZapAssets(56) + }) + + // get gauge rewards + if (account) { + const rewards = await getGaugeRewards({ + gauges: vaults.filter(vault => vault.gauge && vault.chainId === 1).map(vault => vault.gauge?.address) as Address[], + account: account as Address, + publicClient + }) + setGaugeRewards(rewards) + } + setNetworth(SUPPORTED_NETWORKS.map(chain => getVaultNetworthByChain({ vaults, chainId: chain.id })).reduce((a, b) => a + b, 0)); } - if (!account && !initalLoad) getVaults(); - if (account && !accountLoad) getVaults() - }, [account]) + if (!account && !initalLoad && vaults.length > 0) getVaults(); + if (account && !accountLoad && vaults.length > 0) getVaults() + }, [account, initalLoad, accountLoad, vaults]) - const [networth, setNetworth] = useState(0); - const [loading, setLoading] = useState(true); + async function mutateTokenBalance({ inputToken, outputToken, vault, chainId, account }: MutateTokenBalanceProps) { + const data = await publicClient.multicall({ + contracts: [ + { + address: inputToken, + abi: ERC20Abi, + functionName: "balanceOf", + args: [account] + }, + { + address: outputToken, + abi: ERC20Abi, + functionName: "balanceOf", + args: [account] + }, + { + address: vault, + abi: VaultAbi, + functionName: 'totalAssets' + }, + { + address: vault, + abi: VaultAbi, + functionName: 'totalSupply' + }], + allowFailure: false + }) - useEffect(() => { - if (account && loading) - // fetch and set networth - getVaultNetworth({ account }).then(res => { - setNetworth(res.total); - setLoading(false); - }); - }, [account]); + // Modify zap assets + if (NETWORKS_SUPPORTING_ZAP.includes(chainId)) { + const zapAssetFound = zapAssets[chainId].find(asset => asset.address === inputToken || asset.address === outputToken) // @dev -- might need to copy the state here already to avoid modifing a pointer + if (zapAssetFound) { + zapAssetFound.balance = zapAssetFound.address === inputToken ? Number(data[0]) : Number(data[1]) + setZapAssets({ ...zapAssets, [chainId]: [...zapAssets[chainId], zapAssetFound] }) + } + } + + // Modify vaults, assets and gauges + const newVaultState: VaultData[] = [...vaults] + newVaultState.forEach(vaultData => { + if (vaultData.chainId === chainId) { + // Modify vault pricing and tvl + if (vaultData.address === vault) { + const assetsPerShare = Number(data[3]) > 0 ? Number(data[2]) / Number(data[3]) : Number(1e-9) + const pricePerShare = assetsPerShare * vaultData.assetPrice + + vaultData.totalAssets = Number(data[2]) + vaultData.totalSupply = Number(data[3]) + vaultData.assetsPerShare = assetsPerShare + vaultData.pricePerShare = pricePerShare + vaultData.tvl = (Number(data[3]) * pricePerShare) / (10 ** vaultData.asset.decimals) + vaultData.vault.price = pricePerShare * 1e9 + + if (vaultData.gauge) vaultData.gauge.price = pricePerShare * 1e9 + } + // Adjust vault balance + if (vaultData.vault.address === inputToken || vaultData.vault.address === outputToken) { + vaultData.vault.balance = vaultData.vault.address === inputToken ? Number(data[0]) : Number(data[1]) + } + // Adjust asset balance + if (vaultData.asset.address === inputToken || vaultData.asset.address === outputToken) { + vaultData.asset.balance = vaultData.asset.address === inputToken ? Number(data[0]) : Number(data[1]) + } + // Adjust gauge balance + if (vaultData.gauge?.address === inputToken || vaultData.gauge?.address === outputToken) { + vaultData.gauge.balance = vaultData.gauge.address === inputToken ? Number(data[0]) : Number(data[1]) + } + } + }) + setVaults(newVaultState) + } + + const sortByAscendingTvl = () => { + const sortedVaults = [...vaults].sort((a, b) => b.tvl - a.tvl); + setSortingType(VAULT_SORTING_TYPE.mostTvl) + setVaults(sortedVaults) + } + + const sortByDescendingTvl = () => { + const sortedVaults = [...vaults].sort((a, b) => a.tvl - b.tvl); + setSortingType(VAULT_SORTING_TYPE.lessTvl) + setVaults(sortedVaults) + } + + const sortByAscendingApy = () => { + const sortedVaults = [...vaults].sort((a, b) => b.apy - a.apy); + setSortingType(VAULT_SORTING_TYPE.mostvAPR) + setVaults(sortedVaults) + } + + const sortByDescendingApy = () => { + const sortedVaults = [...vaults].sort((a, b) => a.apy - b.apy); + setSortingType(VAULT_SORTING_TYPE.lessvAPR) + setVaults(sortedVaults) + } return ( @@ -73,8 +229,8 @@ const Vaults: NextPage = () => {

-
-
+
+

TVL

@@ -85,39 +241,83 @@ const Vaults: NextPage = () => {

Deposits

- {`$${loading ? "..." : NumberFormatter.format(networth)}`} + {`$${NumberFormatter.format(networth)}`} +
+
+
+ +
+
+

My oVCX

+
+ {`${oBal ? NumberFormatter.format(Number(oBal?.value) / 1e18) : "0"}`}
+ +
+

Claimable oVCX

+
+ {`$${gaugeRewards ? NumberFormatter.format(Number(gaugeRewards?.total) / 1e18) : "0"}`} +
+
+ +
+ + claimOPop({ + gauges: gaugeRewards?.amounts?.filter(gauge => Number(gauge.amount) > 0).map(gauge => gauge.address) as Address[], + account: account as Address, + clients: { publicClient, walletClient: walletClient as WalletClient } + })} + /> +
+
+
+ + claimOPop({ + gauges: gaugeRewards?.amounts?.filter(gauge => Number(gauge.amount) > 0).map(gauge => gauge.address) as Address[], + account: account as Address, + clients: { publicClient, walletClient: walletClient as WalletClient } + })} + />
-
+
chain.id)} selectNetwork={selectNetwork} /> -
- - handleSearch(e.target.value.toLowerCase())} - defaultValue={searchString} - /> +
+
+ + handleSearch(e.target.value.toLowerCase())} + defaultValue={searchString} + /> +
+
- {vaults.length > 0 ? vaults.filter(vault => selectedNetworks.includes(vault.chainId)).filter(vault => !HIDDEN_VAULTS.includes(vault.address)).map((vault) => { + {(vaults.length > 0 && Object.keys(availableZapAssets).length > 0) ? vaults.filter(vault => selectedNetworks.includes(vault.chainId)).filter(vault => FLAGSHIP_VAULTS.includes(vault.address)).map((vault) => { return ( ) }) - :

Loading Vaults...

+ :

Loading Vaults...

}
diff --git a/public/images/icons/checkIcon.svg b/public/images/icons/checkIcon.svg new file mode 100644 index 0000000..74b3a30 --- /dev/null +++ b/public/images/icons/checkIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/loader/grid.svg b/public/images/loader/grid.svg new file mode 100644 index 0000000..1015da8 --- /dev/null +++ b/public/images/loader/grid.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/loader/progressBar.svg b/public/images/loader/progressBar.svg new file mode 100644 index 0000000..888cf53 --- /dev/null +++ b/public/images/loader/progressBar.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/loader/puff.svg b/public/images/loader/puff.svg new file mode 100644 index 0000000..b6ae088 --- /dev/null +++ b/public/images/loader/puff.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/loader/spinner.svg b/public/images/loader/spinner.svg new file mode 100644 index 0000000..18d12b6 --- /dev/null +++ b/public/images/loader/spinner.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/tokens/oEth.png b/public/images/tokens/oEth.png new file mode 100644 index 0000000..1a707f5 Binary files /dev/null and b/public/images/tokens/oEth.png differ diff --git a/public/images/tokens/oPop.svg b/public/images/tokens/oPop.svg new file mode 100644 index 0000000..c4eb769 --- /dev/null +++ b/public/images/tokens/oPop.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/public/images/tokens/vcx.svg b/public/images/tokens/vcx.svg new file mode 100644 index 0000000..fdaac91 --- /dev/null +++ b/public/images/tokens/vcx.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index fc313bd..113ad21 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -10,6 +10,9 @@ module.exports = { ], theme: { + letterSpacing: { + none: "-.1em", + }, screens: { xs: "400px", // => @media (min-"440px) { ... } @@ -42,7 +45,8 @@ module.exports = { customLight: "0px 4px 4px rgba(0, 0, 0, 0.25)", custom: "0 4px 14px rgba(101, 135, 169, 0.16)", "custom-2": "0px -20px 25px -5px rgba(0, 0, 0, 0.05)", - scrollableSelect: "inset 0px -4px 11px rgba(0, 0, 0, 0.1), inset 0px 4px 11px rgba(0, 0, 0, 0.1)", + scrollableSelect: + "inset 0px -4px 11px rgba(0, 0, 0, 0.1), inset 0px 4px 11px rgba(0, 0, 0, 0.1)", }, borderRadius: { "4xl": "2rem", diff --git a/yarn.lock b/yarn.lock index 3c85e33..a3ccb4c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + "@adraffy/ens-normalize@1.9.4": version "1.9.4" resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.4.tgz#aae21cb858bbb0411949d5b7b3051f4209043f62" @@ -17,10 +22,10 @@ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== -"@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.22.6", "@babel/runtime@^7.23.2": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" - integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== +"@babel/runtime@^7.10.1", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.2": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.4.tgz#36fa1d2b36db873d25ec631dcc4923fdc1cf2e2e" + integrity sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg== dependencies: regenerator-runtime "^0.14.0" @@ -47,6 +52,17 @@ stream-browserify "^3.0.0" util "^0.12.4" +"@curvefi/api@2.44.0": + version "2.44.0" + resolved "https://registry.yarnpkg.com/@curvefi/api/-/api-2.44.0.tgz#0df6149c8f0764f56a9905438aa37099f1710705" + integrity sha512-3GPrUf2wTE2q7Lf0j7EpDpObwAG3Qn480UvY6YeMzq+8sQpuBsa42uXtXidNEr2vr7uA47hKH1tDrYbCmo/gdQ== + dependencies: + axios "^0.21.1" + bignumber.js "^9.0.1" + ethcall "^6.0.1" + ethers "^6.3.0" + memoizee "^0.4.15" + "@emotion/hash@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" @@ -60,14 +76,14 @@ eslint-visitor-keys "^3.3.0" "@eslint-community/regexpp@^4.6.1": - version "4.9.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" - integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== -"@eslint/eslintrc@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" - integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== +"@eslint/eslintrc@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.3.tgz#797470a75fe0fbd5a53350ee715e85e87baff22d" + integrity sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -79,10 +95,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.51.0": - version "8.51.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.51.0.tgz#6d419c240cfb2b66da37df230f7e7eef801c32fa" - integrity sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg== +"@eslint/js@8.54.0": + version "8.54.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.54.0.tgz#4fab9a2ff7860082c304f750e94acd644cf984cf" + integrity sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ== "@headlessui/react@^1.7.10": version "1.7.17" @@ -96,12 +112,12 @@ resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-2.0.18.tgz#f80301907c243df03c7e9fd76c0286e95361f7c1" integrity sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw== -"@humanwhocodes/config-array@^0.11.11": - version "0.11.11" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" - integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA== +"@humanwhocodes/config-array@^0.11.13": + version "0.11.13" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" + integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== dependencies: - "@humanwhocodes/object-schema" "^1.2.1" + "@humanwhocodes/object-schema" "^2.0.1" debug "^4.1.1" minimatch "^3.0.5" @@ -110,10 +126,15 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@humanwhocodes/object-schema@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" + integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== + +"@ioredis/commands@^1.1.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" + integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" @@ -346,10 +367,102 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@parcel/watcher-android-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.3.0.tgz#d82e74bb564ebd4d8a88791d273a3d2bd61e27ab" + integrity sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA== + +"@parcel/watcher-darwin-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.3.0.tgz#c9cd03f8f233d512fcfc873d5b4e23f1569a82ad" + integrity sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw== + +"@parcel/watcher-darwin-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.3.0.tgz#83c902994a2a49b9e1ab5050dba24876fdc2c219" + integrity sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow== + +"@parcel/watcher-freebsd-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.3.0.tgz#7a0f4593a887e2752b706aff2dae509aef430cf6" + integrity sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw== + +"@parcel/watcher-linux-arm-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.3.0.tgz#3fc90c3ebe67de3648ed2f138068722f9b1d47da" + integrity sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ== + +"@parcel/watcher-linux-arm64-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.3.0.tgz#f7bbbf2497d85fd11e4c9e9c26ace8f10ea9bcbc" + integrity sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA== + +"@parcel/watcher-linux-arm64-musl@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.3.0.tgz#de131a9fcbe1fa0854e9cbf4c55bed3b35bcff43" + integrity sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw== + +"@parcel/watcher-linux-x64-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.3.0.tgz#193dd1c798003cdb5a1e59470ff26300f418a943" + integrity sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow== + +"@parcel/watcher-linux-x64-musl@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.3.0.tgz#6dbdb86d96e955ab0fe4a4b60734ec0025a689dd" + integrity sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g== + +"@parcel/watcher-wasm@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-wasm/-/watcher-wasm-2.3.0.tgz#73b66c6fbd2a3326ae86a1ec77eab7139d0dd725" + integrity sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA== + dependencies: + is-glob "^4.0.3" + micromatch "^4.0.5" + napi-wasm "^1.1.0" + +"@parcel/watcher-win32-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.3.0.tgz#59da26a431da946e6c74fa6b0f30b120ea6650b6" + integrity sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw== + +"@parcel/watcher-win32-ia32@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.3.0.tgz#3ee6a18b08929cd3b788e8cc9547fd9a540c013a" + integrity sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow== + +"@parcel/watcher-win32-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.3.0.tgz#14e7246289861acc589fd608de39fe5d8b4bb0a7" + integrity sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA== + +"@parcel/watcher@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.3.0.tgz#803517abbc3981a1a1221791d9f59dc0590d50f9" + integrity sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + 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" + "@rainbow-me/rainbowkit@^1.0.11": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@rainbow-me/rainbowkit/-/rainbowkit-1.1.2.tgz#733a2c864dd7dd3625ed54440a1ccb18b0636c72" - integrity sha512-yWxKDfHL4xDZJW34APGkmO2SkxjHwrEeAfvx6+137hWLttQwHcalG9nj4II8roYV2/2XJPmQsbEs7TM0rC0fOg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/@rainbow-me/rainbowkit/-/rainbowkit-1.3.0.tgz#b5546a6b530bbe1dac13b88708ab17d4164327fa" + integrity sha512-y5/JZIdYjqc84QFqKc1AhOHctnFC7quaDE3K8bueGfa0TgyrXcA6XgN3Dko530b3sxJJiTgvu2LxWlNUg8Felg== dependencies: "@vanilla-extract/css" "1.9.1" "@vanilla-extract/dynamic" "2.0.2" @@ -358,6 +471,7 @@ i18n-js "^4.3.2" qrcode "1.5.0" react-remove-scroll "2.5.4" + ua-parser-js "^1.0.35" "@rc-component/portal@^1.1.0": version "1.1.2" @@ -368,10 +482,10 @@ classnames "^2.3.2" rc-util "^5.24.4" -"@rc-component/trigger@^1.17.0": - version "1.17.1" - resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-1.17.1.tgz#3de00f7a8997bb4d8e608502e095d6d4e713ddc9" - integrity sha512-ocD6GlyrPMtWfSdGmfURpudj6ZQqykG/+GH9QVhziG/0EtpPqK5FUbptwXDJGBJwvKhk4Z6jhxJE7utH464SgQ== +"@rc-component/trigger@^1.18.0": + version "1.18.2" + resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-1.18.2.tgz#dc52c4c66fa8aaccaf0710498f2429fc05454e3b" + integrity sha512-jRLYgFgjLEPq3MvS87fIhcfuywFSRDaDrYw1FLku7Cm4esszvzTbA0JBsyacAyLrK9rF3TiHFcvoEDMzoD3CTA== dependencies: "@babel/runtime" "^7.23.2" "@rc-component/portal" "^1.1.0" @@ -381,9 +495,9 @@ rc-util "^5.38.0" "@rushstack/eslint-patch@^1.3.3": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz#5f1b518ec5fa54437c0b7c4a821546c64fed6922" - integrity sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA== + version "1.6.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz#1898e7a7b943680d757417a47fb10f5fcc230b39" + integrity sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA== "@safe-global/safe-apps-provider@^0.17.1": version "0.17.1" @@ -410,9 +524,9 @@ viem "^1.0.0" "@safe-global/safe-gateway-typescript-sdk@^3.5.3": - version "3.12.0" - resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.12.0.tgz#aa767a32f4d10f4ec9a47ad7e32d547d3b51e94c" - integrity sha512-hExCo62lScVC9/ztVqYEYL2pFxcqLTvB8fj0WtdP5FWrvbtEgD0pbVolchzD5bf85pbzvEwdAxSVS7EdCZxTNw== + version "3.13.2" + resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.13.2.tgz#f03884c7eb766f5508085d95ab96063a28e20920" + integrity sha512-kGlJecJHBzGrGTq/yhLANh56t+Zur6Ubpt+/w03ARX1poDb4TM8vKU3iV8tuYpk359PPWp+Qvjnqb9oW2YQcYw== "@scure/base@~1.1.0", "@scure/base@~1.1.2": version "1.1.3" @@ -444,11 +558,11 @@ buffer "~6.0.3" "@solana/web3.js@^1.70.1": - version "1.87.1" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.87.1.tgz#da376cebbc4cc97ece0cb028d799163ea147f299" - integrity sha512-E8Y9bNlZ8TQlhOvCx1b7jG+TjA4SJLVwufmIk1+tcQctUhK5HiB1Q8ljd4yQDkFlk6OOeAlAeqvW0YntWJU94Q== + version "1.87.6" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.87.6.tgz#6744cfc5f4fc81e0f58241c0a92648a7320bb3bf" + integrity sha512-LkqsEBgTZztFiccZZXnawWa8qNCATEqE97/d0vIwjTclmVlc8pBpD1DmjfVHtZ1HS5fZorFlVhXfpwnCNDZfyg== dependencies: - "@babel/runtime" "^7.22.6" + "@babel/runtime" "^7.23.2" "@noble/curves" "^1.2.0" "@noble/hashes" "^1.3.1" "@solana/buffer-layout" "^4.0.0" @@ -606,9 +720,9 @@ tslib "^2.4.0" "@tailwindcss/forms@^0.5.6": - version "0.5.6" - resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.6.tgz#29c6c2b032b363e0c5110efed1499867f6d7e868" - integrity sha512-Fw+2BJ0tmAwK/w01tEFL5TiaJBX1NLT1/YbWgvm7ws3Qcn11kiXxzNTEQDMs5V3mQemhB56l3u0i9dwdzSQldA== + version "0.5.7" + resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.7.tgz#db5421f062a757b5f828bc9286ba626c6685e821" + integrity sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw== dependencies: mini-svg-data-uri "^1.2.3" @@ -647,16 +761,16 @@ use-sync-external-store "^1.2.0" "@types/connect@^3.4.33": - version "3.4.37" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.37.tgz#c66a96689fd3127c8772eb3e9e5c6028ec1a9af5" - integrity sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q== + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" "@types/debug@^4.1.7": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.10.tgz#f23148a6eb771a34c466a4fc28379d8101e84494" - integrity sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA== + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== dependencies: "@types/ms" "*" @@ -671,16 +785,21 @@ integrity sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w== "@types/ms@*": - version "0.7.33" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.33.tgz#80bf1da64b15f21fd8c1dc387c31929317d99ee9" - integrity sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ== + version "0.7.34" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" + integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== -"@types/node@*": - version "20.8.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.7.tgz#ad23827850843de973096edfc5abc9e922492a25" - integrity sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ== +"@types/node@*", "@types/node@^20.2.5": + version "20.9.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.4.tgz#cc8f970e869c26834bdb7ed480b30ede622d74c7" + integrity sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA== dependencies: - undici-types "~5.25.1" + undici-types "~5.26.4" + +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== "@types/node@^12.12.54": version "12.20.55" @@ -693,28 +812,28 @@ integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/prop-types@*": - version "15.7.9" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.9.tgz#b6f785caa7ea1fe4414d9df42ee0ab67f23d8a6d" - integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g== + version "15.7.11" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" + integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== "@types/react@^18.0.9": - version "18.2.29" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.29.tgz#88b48a287e00f6fdcd6f95662878fb701ae18b27" - integrity sha512-Z+ZrIRocWtdD70j45izShRwDuiB4JZqDegqMFW/I8aG5DxxLKOzVNoq62UIO82v9bdgi+DO1jvsb9sTEZUSm+Q== + version "18.2.38" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.38.tgz#3605ca41d3daff2c434e0b98d79a2469d4c2dd52" + integrity sha512-cBBXHzuPtQK6wNthuVMV6IjHAFkdl/FOPFIlkd81/Cd1+IqkHu/A+w4g43kaQQoYHik/ruaQBDL72HyCy1vuMw== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" csstype "^3.0.2" "@types/scheduler@*": - version "0.16.5" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.5.tgz#4751153abbf8d6199babb345a52e1eb4167d64af" - integrity sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw== + version "0.16.8" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" + integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== "@types/trusted-types@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.5.tgz#5cac7e7df3275bb95f79594f192d97da3b4fd5fe" - integrity sha512-I3pkr8j/6tmQtKV/ZzHtuaqYSQvyjGRKH4go60Rr0IDLlFxuRT5V32uvB1mecM5G1EVAUyF/4r4QZ1GHgz+mxA== + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== "@types/ws@^7.4.4": version "7.4.7" @@ -723,58 +842,56 @@ dependencies: "@types/node" "*" -"@types/ws@^8.5.5": - version "8.5.8" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.8.tgz#13efec7bd439d0bdf2af93030804a94f163b1430" - integrity sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg== - dependencies: - "@types/node" "*" - "@typescript-eslint/parser@^5.4.2 || ^6.0.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.8.0.tgz#bb2a969d583db242f1ee64467542f8b05c2e28cb" - integrity sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg== - dependencies: - "@typescript-eslint/scope-manager" "6.8.0" - "@typescript-eslint/types" "6.8.0" - "@typescript-eslint/typescript-estree" "6.8.0" - "@typescript-eslint/visitor-keys" "6.8.0" + version "6.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.12.0.tgz#9fb21ed7d88065a4a2ee21eb80b8578debb8217c" + integrity sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg== + dependencies: + "@typescript-eslint/scope-manager" "6.12.0" + "@typescript-eslint/types" "6.12.0" + "@typescript-eslint/typescript-estree" "6.12.0" + "@typescript-eslint/visitor-keys" "6.12.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz#5cac7977385cde068ab30686889dd59879811efd" - integrity sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g== +"@typescript-eslint/scope-manager@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz#5833a16dbe19cfbad639d4d33bcca5e755c7044b" + integrity sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw== dependencies: - "@typescript-eslint/types" "6.8.0" - "@typescript-eslint/visitor-keys" "6.8.0" + "@typescript-eslint/types" "6.12.0" + "@typescript-eslint/visitor-keys" "6.12.0" -"@typescript-eslint/types@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.8.0.tgz#1ab5d4fe1d613e3f65f6684026ade6b94f7e3ded" - integrity sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ== +"@typescript-eslint/types@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.12.0.tgz#ffc5297bcfe77003c8b7b545b51c2505748314ac" + integrity sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q== -"@typescript-eslint/typescript-estree@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz#9565f15e0cd12f55cf5aa0dfb130a6cb0d436ba1" - integrity sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg== +"@typescript-eslint/typescript-estree@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz#764ccc32598549e5b48ec99e3b85f89b1385310c" + integrity sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw== dependencies: - "@typescript-eslint/types" "6.8.0" - "@typescript-eslint/visitor-keys" "6.8.0" + "@typescript-eslint/types" "6.12.0" + "@typescript-eslint/visitor-keys" "6.12.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/visitor-keys@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz#cffebed56ae99c45eba901c378a6447b06be58b8" - integrity sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg== +"@typescript-eslint/visitor-keys@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz#5877950de42a0f3344261b7a1eee15417306d7e9" + integrity sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw== dependencies: - "@typescript-eslint/types" "6.8.0" + "@typescript-eslint/types" "6.12.0" eslint-visitor-keys "^3.4.1" +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + "@vanilla-extract/css@1.9.1": version "1.9.1" resolved "https://registry.yarnpkg.com/@vanilla-extract/css/-/css-1.9.1.tgz#337b79faa5f8f98915a90c3fe3c30b54be746c09" @@ -809,36 +926,36 @@ resolved "https://registry.yarnpkg.com/@vanilla-extract/sprinkles/-/sprinkles-1.5.0.tgz#c921183ae518bb484299c2dc81f2acefd91c3dbe" integrity sha512-W58f2Rzz5lLmk0jbhgStVlZl5wEiPB1Ur3fRvUaBM+MrifZ3qskmFq/CiH//fEYeG5Dh9vF1qRviMMH46cX9Nw== -"@wagmi/connectors@3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-3.1.2.tgz#4fd33fc4061ffb53c68860a203f099c6cac649c3" - integrity sha512-IlLKErqCzQRBUcCvXGPowcczbWcvJtEG006gPsAoePNJEXCHEWoKASghgu+L/bqD7006Z6mW6zlTNjcSQJvFAg== +"@wagmi/connectors@3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-3.1.3.tgz#112aad63a8042ce4a5a3dc4db9eaa4da0fbcf0fc" + integrity sha512-UgwsQKQDFObJVJMf9pDfFoXTv710o4zrTHyhIWKBTMMkLpCMsMxN5+ZaDhBYt/BgoRinfRYQo8uwuwLhxE6Log== 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.1" + "@walletconnect/ethereum-provider" "2.10.2" "@walletconnect/legacy-provider" "^2.0.0" "@walletconnect/modal" "2.6.2" - "@walletconnect/utils" "2.10.1" + "@walletconnect/utils" "2.10.2" abitype "0.8.7" eventemitter3 "^4.0.7" -"@wagmi/core@1.4.2": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-1.4.2.tgz#facf21c06d236b651782cfdd20005f02a3afcb9b" - integrity sha512-szgNs2DCbBXKsq3wdm/YD8FWkg7lfmTRAv25b2nJYJUTQN59pVXznlWfq8VCJLamhKOYjeYHlTQxXkAeUAJdhw== +"@wagmi/core@1.4.5": + version "1.4.5" + resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-1.4.5.tgz#bab215bfc1e028bc720b772d8d69dd12ae0c0ebf" + integrity sha512-N9luRb1Uk4tBN9kaYcQSWKE9AsRt/rvZaFt5IZech4JPzNN2sQlfhKd9GEjOXYRDqEPHdDvos7qyBKiDNTz4GA== dependencies: - "@wagmi/connectors" "3.1.2" + "@wagmi/connectors" "3.1.3" abitype "0.8.7" eventemitter3 "^4.0.7" zustand "^4.3.1" -"@walletconnect/core@2.10.1": - version "2.10.1" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.10.1.tgz#d1fb442bd77424666bacdb0f5a07f7708fb3d984" - integrity sha512-WAoXfmj+Zy5q48TnrKUjmHXJCBahzKwbul+noepRZf7JDtUAZ9IOWpUjg+UPRbfK5EiWZ0TF42S6SXidf7EHoQ== +"@walletconnect/core@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.10.2.tgz#a1bf6e3e87b33f9df795ce0970d8ddd400fdc8a3" + integrity sha512-JQz/xp3SLEpTeRQctdck2ugSBVEpMxoSE+lFi2voJkZop1hv6P+uqr6E4PzjFluAjeAnKlT1xvra0aFWjPWVcw== dependencies: "@walletconnect/heartbeat" "1.2.1" "@walletconnect/jsonrpc-provider" "1.0.13" @@ -851,8 +968,8 @@ "@walletconnect/relay-auth" "^1.0.4" "@walletconnect/safe-json" "^1.0.2" "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.10.1" - "@walletconnect/utils" "2.10.1" + "@walletconnect/types" "2.10.2" + "@walletconnect/utils" "2.10.2" events "^3.3.0" lodash.isequal "4.5.0" uint8arrays "^3.1.0" @@ -885,19 +1002,19 @@ dependencies: tslib "1.14.1" -"@walletconnect/ethereum-provider@2.10.1": - version "2.10.1" - resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.10.1.tgz#4733a98f0b388cf5ae6c2b269f50da87da432ee5" - integrity sha512-Yhoz8EXkKzxOlBT6G+elphqCx/gkH6RxD9/ZAiy9lLc8Ng5p1gvKCVVP5zsGNE9FbkKmHd+J9JJRzn2Bw2yqtQ== +"@walletconnect/ethereum-provider@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.10.2.tgz#d5aca538fbcbbf7dd771bceb2430de30f06411de" + integrity sha512-QMYFZ6+rVq2CJLdIPdKK0j1Qm66UA27oQU5V2SrL8EVwl7wFfm0Bq7fnL+qAWeDpn612dNeNErpk/ROa1zWlWg== 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.1" - "@walletconnect/types" "2.10.1" - "@walletconnect/universal-provider" "2.10.1" - "@walletconnect/utils" "2.10.1" + "@walletconnect/sign-client" "2.10.2" + "@walletconnect/types" "2.10.2" + "@walletconnect/universal-provider" "2.10.2" + "@walletconnect/utils" "2.10.2" events "^3.3.0" "@walletconnect/events@^1.0.1": @@ -965,12 +1082,13 @@ ws "^7.5.1" "@walletconnect/keyvaluestorage@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.0.2.tgz#92f5ca0f54c1a88a093778842ce0c874d86369c8" - integrity sha512-U/nNG+VLWoPFdwwKx0oliT4ziKQCEoQ27L5Hhw8YOFGA2Po9A9pULUYNWhDgHkrb0gYDNt//X7wABcEWWBd3FQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz#dd2caddabfbaf80f6b8993a0704d8b83115a1842" + integrity sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA== dependencies: - safe-json-utils "^1.1.1" - tslib "1.14.1" + "@walletconnect/safe-json" "^1.0.1" + idb-keyval "^6.2.1" + unstorage "^1.9.0" "@walletconnect/legacy-client@^2.0.0": version "2.0.0" @@ -1102,19 +1220,19 @@ dependencies: tslib "1.14.1" -"@walletconnect/sign-client@2.10.1": - version "2.10.1" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.10.1.tgz#db60bc9400cd79f0cb2380067343512b21ee4749" - integrity sha512-iG3eJGi1yXeG3xGeVSSMf8wDFyx239B0prLQfy1uYDtYFb2ynnH/09oqAZyKn96W5nfQzUgM2Mz157PVdloH3Q== +"@walletconnect/sign-client@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.10.2.tgz#33300a9cfe42487473f66b73c99535f6b26f8c54" + integrity sha512-vviSLV3f92I0bReX+OLr1HmbH0uIzYEQQFd1MzIfDk9PkfFT/LLAHhUnDaIAMkIdippqDcJia+5QEtT4JihL3Q== dependencies: - "@walletconnect/core" "2.10.1" + "@walletconnect/core" "2.10.2" "@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.1" - "@walletconnect/utils" "2.10.1" + "@walletconnect/types" "2.10.2" + "@walletconnect/utils" "2.10.2" events "^3.3.0" "@walletconnect/time@^1.0.2": @@ -1124,10 +1242,10 @@ dependencies: tslib "1.14.1" -"@walletconnect/types@2.10.1": - version "2.10.1" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.10.1.tgz#1355bce236f3eef575716ea3efe4beed98a873ef" - integrity sha512-7pccAhajQdiH2kYywjE1XI64IqRI+4ioyGy0wvz8d0UFQ/DSG3MLKR8jHf5aTOafQQ/HRLz6xvlzN4a7gIVkUQ== +"@walletconnect/types@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.10.2.tgz#68e433a29ec2cf42d79d8b50c77bd5c1d91db721" + integrity sha512-luNV+07Wdla4STi9AejseCQY31tzWKQ5a7C3zZZaRK/di+rFaAAb7YW04OP4klE7tw/mJRGPTlekZElmHxO8kQ== dependencies: "@walletconnect/events" "^1.0.1" "@walletconnect/heartbeat" "1.2.1" @@ -1136,25 +1254,25 @@ "@walletconnect/logger" "^2.0.1" events "^3.3.0" -"@walletconnect/universal-provider@2.10.1": - version "2.10.1" - resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.10.1.tgz#c4a77bd2eed1a335edae5b2b298636092fff63ef" - integrity sha512-81QxTH/X4dRoYCz0U9iOrBYOcj7N897ONcB57wsGhEkV7Rc9htmWJq2CzeOuxvVZ+pNZkE+/aw9LrhizO1Ltxg== +"@walletconnect/universal-provider@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.10.2.tgz#85c8da39f65da8fe33f65f62689e703607b5ddc5" + integrity sha512-wFgI0LbQ3D56sgaUMsgOHCM5m8WLxiC71BGuCKQfApgsbNMVKugYVy2zWHyUyi8sqTQHI+uSaVpDev4UHq9LEw== 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.1" - "@walletconnect/types" "2.10.1" - "@walletconnect/utils" "2.10.1" + "@walletconnect/sign-client" "2.10.2" + "@walletconnect/types" "2.10.2" + "@walletconnect/utils" "2.10.2" events "^3.3.0" -"@walletconnect/utils@2.10.1": - version "2.10.1" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.10.1.tgz#65b37c9800eb0e80a08385b6987471fb46e1e22e" - integrity sha512-DM0dKgm9O58l7VqJEyV2OVv16XRePhDAReI23let6WdW1dSpw/Y/A89Lp99ZJOjLm2FxyblMRF3YRaZtHwBffw== +"@walletconnect/utils@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.10.2.tgz#1f2c6a2f1bb95bcc4517b1e94aa7164c9286eb46" + integrity sha512-syxXRpc2yhSknMu3IfiBGobxOY7fLfLTJuw+ppKaeO6WUdZpIit3wfuGOcc0Ms3ZPFCrGfyGOoZsCvgdXtptRg== dependencies: "@stablelib/chacha20poly1305" "1.0.1" "@stablelib/hkdf" "1.0.1" @@ -1164,7 +1282,7 @@ "@walletconnect/relay-api" "^1.0.9" "@walletconnect/safe-json" "^1.0.2" "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.10.1" + "@walletconnect/types" "2.10.2" "@walletconnect/window-getters" "^1.0.1" "@walletconnect/window-metadata" "^1.0.1" detect-browser "5.3.0" @@ -1194,6 +1312,11 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" +abi-coder@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/abi-coder/-/abi-coder-5.0.0.tgz#df36b51bb02aea45f54f24c403b4245f79a75fcf" + integrity sha512-Kpyv/AhAaIaVJiJ6S/xqoTsiJrfSMc3QsBCiRDqic3o1CZNKGR3CIeT1K/1VZ7Wk5uSwsOAxQcke1TVUEz+usg== + abitype@0.8.7: version "0.8.7" resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.7.tgz#e4b3f051febd08111f486c0cc6a98fa72d033622" @@ -1209,10 +1332,15 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.9.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== +acorn@^8.10.0, acorn@^8.9.0: + version "8.11.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" + integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== aes-js@^3.1.2: version "3.1.2" @@ -1258,7 +1386,7 @@ any-promise@^1.0.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== -anymatch@~3.1.2: +anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -1266,6 +1394,11 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +arch@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + arg@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" @@ -1276,7 +1409,7 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-query@^5.1.3: +aria-query@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== @@ -1291,7 +1424,7 @@ array-buffer-byte-length@^1.0.0: call-bind "^1.0.2" is-array-buffer "^3.0.1" -array-includes@^3.1.6: +array-includes@^3.1.6, array-includes@^3.1.7: version "3.1.7" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== @@ -1307,7 +1440,7 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.findlastindex@^1.2.2: +array.prototype.findlastindex@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== @@ -1318,7 +1451,7 @@ array.prototype.findlastindex@^1.2.2: es-shim-unscopables "^1.0.0" get-intrinsic "^1.2.1" -array.prototype.flat@^1.3.1: +array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== @@ -1328,7 +1461,7 @@ array.prototype.flat@^1.3.1: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.3.1: +array.prototype.flatmap@^1.3.1, array.prototype.flatmap@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== @@ -1362,10 +1495,10 @@ arraybuffer.prototype.slice@^1.0.2: is-array-buffer "^3.0.2" is-shared-array-buffer "^1.0.2" -ast-types-flow@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" - integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== +ast-types-flow@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" + integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== async-mutex@^0.2.6: version "0.2.6" @@ -1408,21 +1541,28 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -axe-core@^4.6.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.2.tgz#2f6f3cde40935825cf4465e3c1c9e77b240ff6ae" - integrity sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g== +axe-core@=4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" + integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" axios@^1.3.6, axios@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.1.tgz#11fbaa11fc35f431193a9564109c88c1f27b585f" - integrity sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A== + version "1.6.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2" + integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" proxy-from-env "^1.1.0" -axobject-query@^3.1.1: +axobject-query@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== @@ -1461,7 +1601,7 @@ bigint-buffer@^1.1.5: dependencies: bindings "^1.3.0" -bignumber.js@*: +bignumber.js@*, bignumber.js@^9.0.1: version "9.1.2" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== @@ -1551,13 +1691,14 @@ busboy@1.6.0: dependencies: streamsearch "^1.1.0" -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" callsites@^3.0.0: version "3.1.0" @@ -1575,9 +1716,9 @@ camelcase@^5.0.0: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541: - version "1.0.30001551" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz#1f2cfa8820bd97c971a57349d7fd8f6e08664a3e" - integrity sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg== + version "1.0.30001564" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001564.tgz#eaa8bbc58c0cbccdcb7b41186df39dd2ba591889" + integrity sha512-DqAOf+rhof+6GVx1y+xzbFPeOumfQnhYzVnZD6LAXijR77yPtm9mfOcqOnT3mpnJiZVT+kwLAFnRlZcIz+c6bg== chalk@^4.0.0, chalk@^4.1.1: version "4.1.2" @@ -1602,7 +1743,14 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -classnames@^2.2.1, classnames@^2.3.1, classnames@^2.3.2: +citty@^0.1.3, citty@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.5.tgz#fe37ceae5dc764af75eb2fece99d2bf527ea4e50" + integrity sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ== + dependencies: + consola "^3.2.3" + +classnames@^2.2.1, classnames@^2.2.5, classnames@^2.3.1, classnames@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== @@ -1612,6 +1760,15 @@ client-only@0.0.1, client-only@^0.0.1: resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== +clipboardy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-3.0.0.tgz#f3876247404d334c9ed01b6f269c11d09a5e3092" + integrity sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg== + dependencies: + arch "^2.2.0" + execa "^5.1.1" + is-wsl "^2.2.0" + cliui@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" @@ -1636,6 +1793,11 @@ clsx@^1.1.0: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== +cluster-key-slot@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1666,15 +1828,25 @@ commander@^4.0.0: integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== component-emitter@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + version "1.3.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" + integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +consola@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" + integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== + +cookie-es@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cookie-es/-/cookie-es-1.0.0.tgz#4759684af168dfc54365b2c2dda0a8d7ee1e4865" + integrity sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ== + cookiejar@^2.1.0: version "2.1.4" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" @@ -1704,7 +1876,7 @@ cross-fetch@^3.1.4: dependencies: node-fetch "^2.6.12" -cross-spawn@^7.0.2: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -1728,11 +1900,26 @@ csstype@^3.0.2, csstype@^3.0.7: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +date-fns@^2.30.0: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1772,7 +1959,7 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -define-data-property@^1.0.1: +define-data-property@^1.0.1, define-data-property@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== @@ -1790,6 +1977,11 @@ define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, de has-property-descriptors "^1.0.0" object-keys "^1.1.1" +defu@^6.1.2, defu@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.3.tgz#6d7f56bc61668e844f9f593ace66fd67ef1205fd" + integrity sha512-Vy2wmG3NTkmHNg/kzpuvHhkqeIx3ODWqasgCRbKtbXEN0G+HpEEv9BtJLp7ZG1CZloFaC41Ah3ZFbq7aqCqMeQ== + delay@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" @@ -1800,16 +1992,31 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +denque@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== + dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +destr@^2.0.1, destr@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.2.tgz#8d3c0ee4ec0a76df54bc8b819bca215592a8c218" + integrity sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg== + detect-browser@5.3.0, detect-browser@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + detect-node-es@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" @@ -1872,9 +2079,9 @@ duplexify@^4.1.2: stream-shift "^1.0.0" electron-to-chromium@^1.4.535: - version "1.4.559" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.559.tgz#050483c22c5eb2345017a8976a67b060559a33f4" - integrity sha512-iS7KhLYCSJbdo3rUSkhDTVuFNCV34RKs2UaB9Ecr7VlqzjjWW//0nfsFF5dtDmyXlZQaDYYtID5fjtC/6lpRug== + version "1.4.592" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.592.tgz#1ffd49ba3da3da3077ea20014b066c910d50c913" + integrity sha512-D3NOkROIlF+d5ixnz7pAf3Lu/AuWpd6AYgI9O67GQXMXTcCP1gJQRotOq35eQy5Sb4hez33XH1YdTtILA7Udww== emoji-regex@^8.0.0: version "8.0.0" @@ -1907,25 +2114,25 @@ enhanced-resolve@^5.12.0: tapable "^2.2.0" es-abstract@^1.22.1: - version "1.22.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.2.tgz#90f7282d91d0ad577f505e423e52d4c1d93c1b8a" - integrity sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA== + version "1.22.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" + integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== dependencies: array-buffer-byte-length "^1.0.0" arraybuffer.prototype.slice "^1.0.2" available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + call-bind "^1.0.5" es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" function.prototype.name "^1.1.6" - get-intrinsic "^1.2.1" + get-intrinsic "^1.2.2" get-symbol-description "^1.0.0" globalthis "^1.0.3" gopd "^1.0.1" - has "^1.0.3" has-property-descriptors "^1.0.0" 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" is-callable "^1.2.7" @@ -1935,7 +2142,7 @@ es-abstract@^1.22.1: is-string "^1.0.7" is-typed-array "^1.1.12" is-weakref "^1.0.2" - object-inspect "^1.12.3" + object-inspect "^1.13.1" object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.5.1" @@ -1949,9 +2156,9 @@ es-abstract@^1.22.1: typed-array-byte-offset "^1.0.0" typed-array-length "^1.0.4" unbox-primitive "^1.0.2" - which-typed-array "^1.1.11" + which-typed-array "^1.1.13" -es-iterator-helpers@^1.0.12: +es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" integrity sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g== @@ -1972,20 +2179,20 @@ es-iterator-helpers@^1.0.12: safe-array-concat "^1.0.1" es-set-tostringtag@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" + integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" + get-intrinsic "^1.2.2" has-tostringtag "^1.0.0" + hasown "^2.0.0" es-shim-unscopables@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== dependencies: - has "^1.0.3" + hasown "^2.0.0" es-to-primitive@^1.2.1: version "1.2.1" @@ -1996,6 +2203,24 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + es6-promise@^4.0.3: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" @@ -2008,6 +2233,24 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +es6-weak-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -2033,7 +2276,7 @@ eslint-config-next@^13.3.4: eslint-plugin-react "^7.33.2" eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" -eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.7: +eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: version "0.3.9" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== @@ -2063,49 +2306,49 @@ eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: debug "^3.2.7" eslint-plugin-import@^2.28.1: - version "2.28.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4" - integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A== - dependencies: - array-includes "^3.1.6" - array.prototype.findlastindex "^1.2.2" - array.prototype.flat "^1.3.1" - array.prototype.flatmap "^1.3.1" + version "2.29.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz#8133232e4329ee344f2f612885ac3073b0b7e155" + integrity sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg== + dependencies: + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" debug "^3.2.7" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.7" + eslint-import-resolver-node "^0.3.9" eslint-module-utils "^2.8.0" - has "^1.0.3" - is-core-module "^2.13.0" + hasown "^2.0.0" + is-core-module "^2.13.1" is-glob "^4.0.3" minimatch "^3.1.2" - object.fromentries "^2.0.6" - object.groupby "^1.0.0" - object.values "^1.1.6" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" semver "^6.3.1" tsconfig-paths "^3.14.2" eslint-plugin-jsx-a11y@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz#fca5e02d115f48c9a597a6894d5bcec2f7a76976" - integrity sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA== + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" + integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== dependencies: - "@babel/runtime" "^7.20.7" - aria-query "^5.1.3" - array-includes "^3.1.6" - array.prototype.flatmap "^1.3.1" - ast-types-flow "^0.0.7" - axe-core "^4.6.2" - axobject-query "^3.1.1" + "@babel/runtime" "^7.23.2" + aria-query "^5.3.0" + array-includes "^3.1.7" + array.prototype.flatmap "^1.3.2" + ast-types-flow "^0.0.8" + axe-core "=4.7.0" + axobject-query "^3.2.1" damerau-levenshtein "^1.0.8" emoji-regex "^9.2.2" - has "^1.0.3" - jsx-ast-utils "^3.3.3" - language-tags "=1.0.5" + es-iterator-helpers "^1.0.15" + hasown "^2.0.0" + jsx-ast-utils "^3.3.5" + language-tags "^1.0.9" minimatch "^3.1.2" - object.entries "^1.1.6" - object.fromentries "^2.0.6" - semver "^6.3.0" + object.entries "^1.1.7" + object.fromentries "^2.0.7" "eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705": version "4.6.0" @@ -2148,17 +2391,18 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.15.0: - version "8.51.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.51.0.tgz#4a82dae60d209ac89a5cff1604fea978ba4950f3" - integrity sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA== + version "8.54.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.54.0.tgz#588e0dd4388af91a2e8fa37ea64924074c783537" + integrity sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.2" - "@eslint/js" "8.51.0" - "@humanwhocodes/config-array" "^0.11.11" + "@eslint/eslintrc" "^2.1.3" + "@eslint/js" "8.54.0" + "@humanwhocodes/config-array" "^0.11.13" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -2266,6 +2510,35 @@ eth-rpc-errors@^4.0.2: dependencies: fast-safe-stringify "^2.0.6" +ethcall@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/ethcall/-/ethcall-6.0.2.tgz#bc814289453a79402bef514b902fa45ee1f7946a" + integrity sha512-FyaKLlxtaVt+kRmhzDG3YfW4VxqasxZE2CDSfylMVp8kCxsBikzFE1BO90yAMGdjdwaX0kHlvjWSxKRpiEcI4w== + dependencies: + "@types/node" "^20.2.5" + abi-coder "^5.0.0" + +ethers@^6.3.0: + version "6.8.1" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.8.1.tgz#ee2a1a39b5f62a13678f90ccd879175391d0a2b4" + integrity sha512-iEKm6zox5h1lDn6scuRWdIdFJUCGg3+/aQWu0F4K0GVyEZiktFkqrJbRjTn1FlYEPz7RKA707D6g5Kdk6j7Ljg== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -2276,6 +2549,28 @@ events@^3.3.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +execa@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.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" + +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + extend@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -2291,10 +2586,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== +fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -2382,9 +2677,9 @@ find-up@^5.0.0: path-exists "^4.0.0" flat-cache@^3.0.4: - version "3.1.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b" - integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: flatted "^3.2.9" keyv "^4.5.3" @@ -2395,7 +2690,7 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== -follow-redirects@^1.15.0: +follow-redirects@^1.14.0, follow-redirects@^1.15.0: version "1.15.3" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== @@ -2445,7 +2740,7 @@ fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: +function-bind@^1.1.1, function-bind@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== @@ -2470,21 +2765,31 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== dependencies: - function-bind "^1.1.1" - has "^1.0.3" + function-bind "^1.1.2" has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" get-nonce@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== +get-port-please@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.1.tgz#2556623cddb4801d823c0a6a15eec038abb483be" + integrity sha512-3UBAyM3u4ZBVYDsxOQfJDxEa6XTbpBDrOjp4mf7ExFRt5BKs/QywQQiJsh2B+hxcZLSapWqCRvElUe8DnKcFHA== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -2603,6 +2908,20 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +h3@^1.8.1, h3@^1.8.2: + version "1.9.0" + resolved "https://registry.yarnpkg.com/h3/-/h3-1.9.0.tgz#c5f512a93026df9837db6f30c9ef51135dd46752" + integrity sha512-+F3ZqrNV/CFXXfZ2lXBINHi+rM4Xw3CDC5z2CDK3NMPocjonKipGLLDSkrqY9DOrioZNPTIdDMWfQKm//3X2DA== + dependencies: + cookie-es "^1.0.0" + defu "^6.1.3" + destr "^2.0.2" + iron-webcrypto "^1.0.0" + radix3 "^1.1.0" + ufo "^1.3.2" + uncrypto "^0.1.3" + unenv "^1.7.4" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -2614,11 +2933,11 @@ has-flag@^4.0.0: integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== dependencies: - get-intrinsic "^1.1.1" + get-intrinsic "^1.2.2" has-proto@^1.0.1: version "1.0.1" @@ -2637,11 +2956,6 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" - integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== - hash.js@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -2650,15 +2964,32 @@ hash.js@^1.1.7: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + hey-listen@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== highcharts@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/highcharts/-/highcharts-11.1.0.tgz#715eb55fd081351b526e28cd89ac0e4e30b35c15" - integrity sha512-vhmqq6/frteWMx0GKYWwEFL25g4OYc7+m+9KQJb/notXbNtIb8KVy+ijOF7XAFqF165cq0pdLIePAmyFY5ph3g== + version "11.2.0" + resolved "https://registry.yarnpkg.com/highcharts/-/highcharts-11.2.0.tgz#32ddc885b1c7a7d438df30c6d751c28991b16616" + integrity sha512-9i650YK7ZBA1Mgtr3avMkLVCAI45RQvYnwi+eHsdFSaBGuQN6BHoa4j4lMkSJLv0V4LISTK1z7J7G82Lzd7zwg== + +http-shutdown@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f" + integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== humanize-ms@^1.2.1: version "1.2.1" @@ -2676,15 +3007,20 @@ i18n-js@^4.3.2: lodash "*" make-plural "*" +idb-keyval@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33" + integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg== + ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore@^5.2.0: - version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + version "5.3.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" + integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== import-fresh@^3.2.1: version "3.3.0" @@ -2718,12 +3054,12 @@ inherits@2.0.3: integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== internal-slot@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" - integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" + integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== dependencies: - get-intrinsic "^1.2.0" - has "^1.0.3" + get-intrinsic "^1.2.2" + hasown "^2.0.0" side-channel "^1.0.4" invariant@^2.2.4: @@ -2733,6 +3069,26 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" +ioredis@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.3.2.tgz#9139f596f62fc9c72d873353ac5395bcf05709f7" + integrity sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA== + dependencies: + "@ioredis/commands" "^1.1.1" + cluster-key-slot "^1.1.0" + debug "^4.3.4" + denque "^2.1.0" + lodash.defaults "^4.2.0" + lodash.isarguments "^3.1.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + standard-as-callback "^2.1.0" + +iron-webcrypto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.0.0.tgz#e3b689c0c61b434a0a4cb82d0aeabbc8b672a867" + integrity sha512-anOK1Mktt8U1Xi7fCM3RELTuYbnFikQY5VtrDj7kPgpejV7d43tWKhzgioO0zpkazLEL/j/iayRqnJhrGfqUsg== + is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -2784,12 +3140,12 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.11.0, is-core-module@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" - integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== +is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: - has "^1.0.3" + hasown "^2.0.0" is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" @@ -2798,6 +3154,11 @@ is-date-object@^1.0.1, is-date-object@^1.0.5: dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -2856,6 +3217,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-promise@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -2876,6 +3242,11 @@ is-shared-array-buffer@^1.0.2: dependencies: call-bind "^1.0.2" +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -2922,6 +3293,13 @@ is-weakset@^2.0.1: call-bind "^1.0.2" get-intrinsic "^1.1.1" +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" @@ -2937,11 +3315,6 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isomorphic-ws@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" - integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== - isomorphic-ws@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" @@ -2981,15 +3354,15 @@ jayson@^4.1.0: uuid "^8.3.2" ws "^7.4.5" -jiti@^1.18.2: - version "1.20.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.20.0.tgz#2d823b5852ee8963585c8dd8b7992ffc1ae83b42" - integrity sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA== +jiti@^1.19.1, jiti@^1.20.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" + integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== jotai@^2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/jotai/-/jotai-2.4.3.tgz#a8eff8ca6de968d6a04616329dd1335ce52e70f3" - integrity sha512-CSAHX9LqWG5WCrU8OgBoZbBJ+Bo9rQU0mPusEF4e0CZ/SNFgurG26vb3UpgvCSJZgYVcUQNiUBM5q86PA8rstQ== + version "2.5.1" + resolved "https://registry.yarnpkg.com/jotai/-/jotai-2.5.1.tgz#eed05a32a4ac1264c531a77e86478f7ad3197ca3" + integrity sha512-vanPCCSuHczUXNbVh/iUunuMfrWRL4FdBtAbTRmrfqezJcKb8ybBTg8iivyYuUHapjcDETyJe1E4inlo26bVHA== "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" @@ -3043,12 +3416,17 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: version "3.3.5" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== @@ -3079,17 +3457,17 @@ keyvaluestorage-interface@^1.0.0: resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== -language-subtag-registry@~0.3.2: +language-subtag-registry@^0.3.20: version "0.3.22" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== -language-tags@=1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" - integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ== +language-tags@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" + integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== dependencies: - language-subtag-registry "~0.3.2" + language-subtag-registry "^0.3.20" levn@^0.4.1: version "0.4.1" @@ -3099,16 +3477,44 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lilconfig@^2.0.5, lilconfig@^2.1.0: +lilconfig@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== +lilconfig@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.0.0.tgz#f8067feb033b5b74dab4602a5f5029420be749bc" + integrity sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +listhen@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/listhen/-/listhen-1.5.5.tgz#58915512af70f770aa3e9fb19367adf479bb58c4" + integrity sha512-LXe8Xlyh3gnxdv4tSjTjscD1vpr/2PRpzq8YIaMJgyKzRG8wdISlWVWnGThJfHnlJ6hmLt2wq1yeeix0TEbuoA== + dependencies: + "@parcel/watcher" "^2.3.0" + "@parcel/watcher-wasm" "2.3.0" + citty "^0.1.4" + clipboardy "^3.0.0" + consola "^3.2.3" + defu "^6.1.2" + get-port-please "^3.1.1" + h3 "^1.8.1" + http-shutdown "^1.2.2" + jiti "^1.20.0" + mlly "^1.4.2" + node-forge "^1.3.1" + pathe "^1.1.1" + std-env "^3.4.3" + ufo "^1.3.0" + untun "^0.1.2" + uqr "^0.1.2" + lit-element@^3.3.0: version "3.3.3" resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.3.3.tgz#10bc19702b96ef5416cf7a70177255bfb17b3209" @@ -3148,6 +3554,16 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== + +lodash.isarguments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== + lodash.isequal@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -3170,6 +3586,11 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^10.0.2: + version "10.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" + integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -3177,6 +3598,13 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== + dependencies: + es5-ext "~0.10.2" + make-plural@*: version "7.3.0" resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-7.3.0.tgz#2889dbafca2fb097037c47967d3e3afa7e48a52c" @@ -3202,6 +3630,25 @@ media-query-parser@^2.0.2: dependencies: "@babel/runtime" "^7.12.5" +memoizee@^0.4.15: + version "0.4.15" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" + integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.53" + es6-weak-map "^2.0.3" + event-emitter "^0.3.5" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -3237,6 +3684,16 @@ mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + mini-svg-data-uri@^1.2.3: version "1.4.4" resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939" @@ -3259,6 +3716,16 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +mlly@^1.2.0, mlly@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.4.2.tgz#7cf406aa319ff6563d25da6b36610a93f2a8007e" + integrity sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg== + dependencies: + acorn "^8.10.0" + pathe "^1.1.1" + pkg-types "^1.0.3" + ufo "^1.3.0" + motion@10.16.2: version "10.16.2" resolved "https://registry.yarnpkg.com/motion/-/motion-10.16.2.tgz#7dc173c6ad62210a7e9916caeeaf22c51e598d21" @@ -3271,6 +3738,11 @@ motion@10.16.2: "@motionone/utils" "^10.15.1" "@motionone/vue" "^10.16.2" +mri@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -3296,15 +3768,25 @@ mz@^2.7.0: thenify-all "^1.0.0" nanoid@^3.3.6: - version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" - integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + +napi-wasm@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.0.tgz#bbe617823765ae9c1bc12ff5942370eae7b2ba4e" + integrity sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg== natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +next-tick@1, next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + next@^13.5.2: version "13.5.6" resolved "https://registry.yarnpkg.com/next/-/next-13.5.6.tgz#e964b5853272236c37ce0dd2c68302973cf010b1" @@ -3333,6 +3815,11 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== +node-addon-api@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.0.0.tgz#8136add2f510997b3b94814f4af1cce0b0e3962e" + integrity sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA== + node-cache@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d" @@ -3340,6 +3827,11 @@ node-cache@^5.1.2: dependencies: clone "2.x" +node-fetch-native@^1.4.0, node-fetch-native@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.4.1.tgz#5a336e55b4e1b1e72b9927da09fecd2b374c9be5" + integrity sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w== + node-fetch@^2.6.12: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -3347,10 +3839,15 @@ node-fetch@^2.6.12: dependencies: whatwg-url "^5.0.0" +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" - integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== + version "4.7.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.7.0.tgz#749f0033590b2a89ac8edb5e0775f95f5ae86d15" + integrity sha512-PbZERfeFdrHQOOXiAKOY0VPbykZy90ndPKk0d+CFDegTKmWp1VgOTz2xACVbr1BjCWxrQp68CXtvNsveFhqDJg== node-releases@^2.0.13: version "2.0.13" @@ -3367,6 +3864,13 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -3377,10 +3881,10 @@ object-hash@^3.0.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.12.3, object-inspect@^1.9.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.0.tgz#42695d3879e1cd5bda6df5062164d80c996e23e2" - integrity sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g== +object-inspect@^1.13.1, object-inspect@^1.9.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== object-keys@^1.1.1: version "1.1.1" @@ -3397,7 +3901,7 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.6: +object.entries@^1.1.6, object.entries@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131" integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA== @@ -3406,7 +3910,7 @@ object.entries@^1.1.6: define-properties "^1.2.0" es-abstract "^1.22.1" -object.fromentries@^2.0.6: +object.fromentries@^2.0.6, object.fromentries@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== @@ -3415,7 +3919,7 @@ object.fromentries@^2.0.6: define-properties "^1.2.0" es-abstract "^1.22.1" -object.groupby@^1.0.0: +object.groupby@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== @@ -3433,7 +3937,7 @@ object.hasown@^1.1.2: define-properties "^1.2.0" es-abstract "^1.22.1" -object.values@^1.1.6: +object.values@^1.1.6, object.values@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== @@ -3442,6 +3946,15 @@ object.values@^1.1.6: define-properties "^1.2.0" es-abstract "^1.22.1" +ofetch@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.3.tgz#588cb806a28e5c66c2c47dd8994f9059a036d8c0" + integrity sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg== + dependencies: + destr "^2.0.1" + node-fetch-native "^1.4.0" + ufo "^1.3.0" + on-exit-leak-free@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" @@ -3454,6 +3967,13 @@ once@^1.3.0, once@^1.4.0: dependencies: wrappy "1" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -3526,7 +4046,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^3.1.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== @@ -3549,6 +4069,11 @@ path@^0.12.7: process "^0.11.1" util "^0.10.3" +pathe@^1.1.0, pathe@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.1.tgz#1dd31d382b974ba69809adc9a7a347e65d84829a" + integrity sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -3609,6 +4134,15 @@ pirates@^4.0.1: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== +pkg-types@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.3.tgz#988b42ab19254c01614d13f4f65a2cfc7880f868" + integrity sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A== + dependencies: + jsonc-parser "^3.2.0" + mlly "^1.2.0" + pathe "^1.1.0" + pngjs@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" @@ -3631,12 +4165,12 @@ postcss-js@^4.0.1: camelcase-css "^2.0.1" postcss-load-config@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.1.tgz#152383f481c2758274404e4962743191d73875bd" - integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" + integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== dependencies: - lilconfig "^2.0.5" - yaml "^2.1.1" + lilconfig "^3.0.0" + yaml "^2.3.4" postcss-nested@^6.0.1: version "6.0.1" @@ -3668,9 +4202,9 @@ postcss@8.4.31, postcss@^8.4.23: source-map-js "^1.0.2" preact@^10.12.0, preact@^10.5.9: - version "10.18.1" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.18.1.tgz#3b84bb305f0b05f4ad5784b981d15fcec4e105da" - integrity sha512-mKUD7RRkQQM6s7Rkmi7IFkoEHjuFqRQUaXamO61E6Nn7vqF/bo7EZCmSyrUnp2UWHw0O7XjZ2eeXis+m7tf4lg== + version "10.19.2" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.19.2.tgz#841797620dba649aaac1f8be42d37c3202dcea8b" + integrity sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg== prelude-ls@^1.2.1: version "1.2.1" @@ -3717,9 +4251,9 @@ proxy-from-env@^1.1.0: integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== punycode@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" - integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== qrcode@1.5.0: version "1.5.0" @@ -3778,6 +4312,11 @@ quick-format-unescaped@^4.0.3: resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== +radix3@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.0.tgz#9745df67a49c522e94a33d0a93cf743f104b6e0d" + integrity sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -3795,28 +4334,37 @@ rc-motion@^2.0.0: rc-util "^5.21.0" rc-resize-observer@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.3.1.tgz#b61b9f27048001243617b81f95e53d7d7d7a6a3d" - integrity sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg== + version "1.4.0" + resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz#7bba61e6b3c604834980647cce6451914750d0cc" + integrity sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q== dependencies: "@babel/runtime" "^7.20.7" classnames "^2.2.1" - rc-util "^5.27.0" + rc-util "^5.38.0" resize-observer-polyfill "^1.5.1" +rc-slider@^10.3.1: + version "10.4.0" + resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-10.4.0.tgz#efc016583fdea5f5dfb4f3dc61b6755a19e5f453" + integrity sha512-ZlpWjFhOlEf0w4Ng31avFBkXNNBj60NAcTPaIoiCxBkJ29wOtHSPMqv9PZeEoqmx64bpJkgK7kPa47HG4LPzww== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.2.5" + rc-util "^5.27.0" + rc-tooltip@^6.1.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-6.1.1.tgz#8f3bf2b7008f091977da19aa4617a48cefed3d10" - integrity sha512-YoxL0Ev4htsX37qgN23eKr0L5PIRpZaLVL9GX6aJ4x6UEnwgXZYUNCAEHfKlKT3eD1felDq3ob4+Cn9lprLDBw== + version "6.1.2" + resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-6.1.2.tgz#33923ecfb2cf24347975093cbd0b048ab33c9567" + integrity sha512-89zwvybvCxGJu3+gGF8w5AXd4HHk6hIN7K0vZbkzjilVaEAIWPqc1fcyeUeP71n3VCcw7pTL9LyFupFbrx8gHw== dependencies: "@babel/runtime" "^7.11.2" - "@rc-component/trigger" "^1.17.0" + "@rc-component/trigger" "^1.18.0" classnames "^2.3.1" rc-util@^5.21.0, rc-util@^5.24.4, rc-util@^5.27.0, rc-util@^5.38.0: - version "5.38.0" - resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.38.0.tgz#18a3d1c26ba3c43fabfbe6303e825dabd9e5f4f0" - integrity sha512-yV/YBNdFn+edyBpBdCqkPE29Su0jWcHNgwx2dJbRqMrMfrUcMJUjCRV+ZPhcvWyKFJ63GzEerPrz9JIVo0zXmA== + version "5.38.1" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.38.1.tgz#4915503b89855f5c5cd9afd4c72a7a17568777bb" + integrity sha512-e4ZMs7q9XqwTuhIK7zBIVFltUtMSjphuPPQXHoHlzRzNdOwUxDejo0Zls5HYaJfRKNURcsS/ceKVULlhjBrxng== dependencies: "@babel/runtime" "^7.18.3" react-is "^18.2.0" @@ -3929,6 +4477,18 @@ real-require@^0.1.0: resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== +redis-errors@^1.0.0, redis-errors@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== + +redis-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== + dependencies: + redis-errors "^1.0.0" + reflect.getprototypeof@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" @@ -4016,9 +4576,9 @@ rimraf@^3.0.2: glob "^7.1.3" rpc-websockets@^7.5.1: - version "7.6.1" - resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.6.1.tgz#7d1dd00e5ad3e17bbe1d88ba6e66f4cb579cb66b" - integrity sha512-MmRGaJJvxTHSRxYPjJJqcj2zWnCetw7YbYbKlD0Yc7qVw6PsZhRJg1MI3mpWlpBs+4zO+urlNfLl9zLsdOD/gA== + version "7.8.0" + resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.8.0.tgz#1bcf571f65c51803e81f0824e9540a0da35a5287" + integrity sha512-AStkq6KDvSAmA4WiwlK1pDvj/33BWmExTATUokC0v+NhWekXSTNzXS5OGXeYwq501/pj6lBZMofg/h4dx4/tCg== dependencies: "@babel/runtime" "^7.17.2" eventemitter3 "^4.0.7" @@ -4062,11 +4622,6 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-json-utils@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/safe-json-utils/-/safe-json-utils-1.1.1.tgz#0e883874467d95ab914c3f511096b89bfb3e63b1" - integrity sha512-SAJWGKDs50tAbiDXLf89PDwt9XYkWyANFWVzn4dTXl5QyI8t2o/bW5/OJl3lvc2WVU4MEpTo9Yz5NVFNsp+OJQ== - safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -4088,7 +4643,7 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" -semver@^6.3.0, semver@^6.3.1: +semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -4105,6 +4660,16 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + set-function-name@^2.0.0, set-function-name@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" @@ -4143,6 +4708,11 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -4175,6 +4745,16 @@ split2@^4.0.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== +standard-as-callback@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" + integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== + +std-env@^3.4.3: + version "3.5.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.5.0.tgz#83010c9e29bd99bf6f605df87c19012d82d63b97" + integrity sha512-JGUEaALvL0Mf6JCfYnJOTcobY+Nc7sG/TemDRBqCA0wEr4DER7zDchaaixTlmOxAjG1uRJmX82EQcxwTQTkqVA== + stream-browserify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" @@ -4275,6 +4855,11 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -4344,19 +4929,19 @@ tailwind-scrollbar-hide@^1.1.7: integrity sha512-X324n9OtpTmOMqEgDUEA/RgLrNfBF/jwJdctaPZDzB3mppxJk7TLIDmOreEDm1Bq4R9LSPu4Epf8VSdovNU+iA== tailwindcss@^3.2.6: - version "3.3.3" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.3.tgz#90da807393a2859189e48e9e7000e6880a736daf" - integrity sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w== + version "3.3.5" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.5.tgz#22a59e2fbe0ecb6660809d9cc5f3976b077be3b8" + integrity sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA== dependencies: "@alloc/quick-lru" "^5.2.0" arg "^5.0.2" chokidar "^3.5.3" didyoumean "^1.2.2" dlv "^1.1.3" - fast-glob "^3.2.12" + fast-glob "^3.3.0" glob-parent "^6.0.2" is-glob "^4.0.3" - jiti "^1.18.2" + jiti "^1.19.1" lilconfig "^2.1.0" micromatch "^4.0.5" normalize-path "^3.0.0" @@ -4412,6 +4997,14 @@ thread-stream@^0.15.1: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== +timers-ext@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== + dependencies: + es5-ext "~0.10.46" + next-tick "1" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -4454,6 +5047,11 @@ tslib@1.14.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" @@ -4471,6 +5069,16 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -4522,6 +5130,16 @@ typescript@5.0.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +ua-parser-js@^1.0.35: + version "1.0.37" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.37.tgz#b5dc7b163a5c1f0c510b08446aed4da92c46373f" + integrity sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ== + +ufo@^1.3.0, ufo@^1.3.1, ufo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496" + integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA== + uint8arrays@^3.0.0, uint8arrays@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" @@ -4539,10 +5157,52 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -undici-types@~5.25.1: - version "5.25.3" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3" - integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA== +uncrypto@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" + integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +unenv@^1.7.4: + version "1.8.0" + resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.8.0.tgz#0f860d5278405700bd95d47b23bc01f3a735d68c" + integrity sha512-uIGbdCWZfhRRmyKj1UioCepQ0jpq638j/Cf0xFTn4zD1nGJ2lSdzYHLzfdXN791oo/0juUiSWW1fBklXMTsuqg== + dependencies: + consola "^3.2.3" + defu "^6.1.3" + mime "^3.0.0" + node-fetch-native "^1.4.1" + pathe "^1.1.1" + +unstorage@^1.9.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.10.1.tgz#bf8cc00a406e40a6293e893da9807057d95875b0" + integrity sha512-rWQvLRfZNBpF+x8D3/gda5nUCQL2PgXy2jNG4U7/Rc9BGEv9+CAJd0YyGCROUBKs9v49Hg8huw3aih5Bf5TAVw== + dependencies: + anymatch "^3.1.3" + chokidar "^3.5.3" + destr "^2.0.2" + h3 "^1.8.2" + ioredis "^5.3.2" + listhen "^1.5.5" + lru-cache "^10.0.2" + mri "^1.2.0" + node-fetch-native "^1.4.1" + ofetch "^1.3.3" + ufo "^1.3.1" + +untun@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.2.tgz#fa42a62ae24c1c5c6f3209692a2b0e1f573f1353" + integrity sha512-wLAMWvxfqyTiBODA1lg3IXHQtjggYLeTK7RnSfqtOXixWJ3bAa2kK/HHmOOg19upteqO3muLvN6O/icbyQY33Q== + dependencies: + citty "^0.1.3" + consola "^3.2.3" + pathe "^1.1.1" update-browserslist-db@^1.0.13: version "1.0.13" @@ -4552,6 +5212,11 @@ update-browserslist-db@^1.0.13: escalade "^3.1.1" picocolors "^1.0.0" +uqr@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/uqr/-/uqr-0.1.2.tgz#5c6cd5dcff9581f9bb35b982cb89e2c483a41d7d" + integrity sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -4629,37 +5294,37 @@ valtio@1.11.2: proxy-compare "2.5.1" use-sync-external-store "1.2.0" -vaultcraft-sdk@0.1.14: - version "0.1.14" - resolved "https://registry.yarnpkg.com/vaultcraft-sdk/-/vaultcraft-sdk-0.1.14.tgz#a56f97402ace1f46dd15ebec55caceffdf444b66" - integrity sha512-O4kv1BK8xbTylPO+OW2sVMZgO2BMqzHXsNHtyeYlWYwEzC+RhWejwGXu6sUrVsFYPiMmTFbu0ZWDe6jIbb4nTw== +vaultcraft-sdk@0.1.17: + version "0.1.17" + resolved "https://registry.yarnpkg.com/vaultcraft-sdk/-/vaultcraft-sdk-0.1.17.tgz#5419bceedab0ab35c26d72b50cc04f32df3feb18" + integrity sha512-oN/RTWmMXENqfRrMsMdVu/nm4iD7kRMvbsKxSyCcfgm1vG0yAsr/1ZyV3NLxUIVFQ078tKV+PvDwVIuzup6ofg== dependencies: + "@curvefi/api" "2.44.0" axios "^1.5.0" dotenv "^16.3.1" node-cache "^5.1.2" viem "^1.5.3" -viem@1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/viem/-/viem-1.11.1.tgz#30531740eb52e5d1ff1167d8df462d1a8d45afb8" - integrity sha512-PPNsPacRS7nryakQQJ9PjYGjUa0QgV8lbERhRuJm8X4kGUzSAsTQaQmy4hvV0cRAEHg8tG0TMD+GTCfwzZM3Yw== +viem@1.18.9: + version "1.18.9" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.18.9.tgz#8be8fe3148b1c6c3bccc853001df98f91a8aeb30" + integrity sha512-eAXtoTwAFA3YEgjTYMb5ZTQrDC0UPx5qyZ4sv90TirVKepcM9mBPksTkC1SSWya0UdxhBmhEBL/CiYMjmGCTWg== dependencies: "@adraffy/ens-normalize" "1.9.4" "@noble/curves" "1.2.0" "@noble/hashes" "1.3.2" "@scure/bip32" "1.3.2" "@scure/bip39" "1.2.1" - "@types/ws" "^8.5.5" abitype "0.9.8" - isomorphic-ws "5.0.0" + isows "1.0.3" ws "8.13.0" viem@^1.0.0, viem@^1.5.3: - version "1.16.6" - resolved "https://registry.yarnpkg.com/viem/-/viem-1.16.6.tgz#78118c9269506a59e2bc4deab13f1646e113d3fc" - integrity sha512-jcWcFQ+xzIfDwexwPJRvCuCRJKEkK9iHTStG7mpU5MmuSBpACs4nATBDyXNFtUiyYTFzLlVEwWkt68K0nCSImg== + version "1.19.7" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.19.7.tgz#815d100c37ed1dda56809bbbb1c1ca4a7982f5f7" + integrity sha512-NFCqU73CTHML9K7G3K8hnDJ9VjHJbH822Z6U2jUGNr0g5486EHMW0gtwnk6ivFP+ru5UewmUKwEvO0p5m0rvnA== dependencies: - "@adraffy/ens-normalize" "1.9.4" + "@adraffy/ens-normalize" "1.10.0" "@noble/curves" "1.2.0" "@noble/hashes" "1.3.2" "@scure/bip32" "1.3.2" @@ -4668,15 +5333,15 @@ viem@^1.0.0, viem@^1.5.3: isows "1.0.3" ws "8.13.0" -wagmi@1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-1.4.2.tgz#cd681b1d35cf36613a11852cf25c2c39ce456f9f" - integrity sha512-Cxu0LatB44stqHoqdc6dgsTb9woYH1bEquJFq9PbTkePmnRCvceAD4aFUREUTaBWzIBcouhFlanWweDzEnb3mg== +wagmi@1.4.5: + version "1.4.5" + resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-1.4.5.tgz#65ccf763e17892871196b6e5b188e29f0b08d3df" + integrity sha512-Ph62E6cO5n2Z8Z5LTyZrkaNprxTsbC4w0qZJT4OJdXrEELziI8z/b4FO6amVFXdu2rDp/wpvF56e4mhKC8/Kdw== dependencies: "@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.2" + "@wagmi/core" "1.4.5" abitype "0.8.7" use-sync-external-store "^1.2.0" @@ -4745,13 +5410,13 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.11, which-typed-array@^1.1.2, which-typed-array@^1.1.9: - version "1.1.11" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" - integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== +which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.2, which-typed-array@^1.1.9: + version "1.1.13" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" + integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== dependencies: available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + call-bind "^1.0.4" for-each "^0.3.3" gopd "^1.0.1" has-tostringtag "^1.0.0" @@ -4782,6 +5447,11 @@ ws@8.13.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + ws@^7.4.5, ws@^7.5.1: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" @@ -4807,10 +5477,10 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^2.1.1: - version "2.3.3" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.3.tgz#01f6d18ef036446340007db8e016810e5d64aad9" - integrity sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ== +yaml@^2.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" + integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== yargs-parser@^18.1.2: version "18.1.3" @@ -4843,8 +5513,8 @@ yocto-queue@^0.1.0: integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== zustand@^4.3.1: - version "4.4.3" - resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.3.tgz#1d54cf7fa4507ad8bf58e2f13e08ddc8a6730128" - integrity sha512-oRy+X3ZazZvLfmv6viIaQmtLOMeij1noakIsK/Y47PWYhT8glfXzQ4j0YcP5i0P0qI1A4rIB//SGROGyZhx91A== + version "4.4.6" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.6.tgz#03c78e3e2686c47095c93714c0c600b72a6512bd" + integrity sha512-Rb16eW55gqL4W2XZpJh0fnrATxYEG3Apl2gfHTyDSE965x/zxslTikpNch0JgNjJA9zK6gEFW8Fl6d1rTZaqgg== dependencies: use-sync-external-store "1.2.0"