From cd1abc1c78c58517105757c4b691084f54009a9e Mon Sep 17 00:00:00 2001 From: toniocodo Date: Fri, 15 Sep 2023 22:45:23 +0200 Subject: [PATCH 1/3] feat: swap state - add disabled, loading and custom state props - add wait transaction callbacks - add isLoading to SwapRouteCard --- libs/oeth/swap/src/components/BestRoutes.tsx | 38 ++-- libs/oeth/swap/src/components/SwapRoute.tsx | 60 ++--- .../swap/src/components/SwapRouteCard.tsx | 206 ++++++++---------- .../swap/src/components/TokenSelectModal.tsx | 2 +- libs/oeth/swap/src/hooks.ts | 49 ++++- libs/oeth/swap/src/state.ts | 11 +- libs/oeth/swap/src/types.ts | 6 +- libs/oeth/swap/src/views/SwapView.tsx | 102 +++++++-- .../components/src/Inputs/TokenInput.tsx | 1 + 9 files changed, 261 insertions(+), 214 deletions(-) diff --git a/libs/oeth/swap/src/components/BestRoutes.tsx b/libs/oeth/swap/src/components/BestRoutes.tsx index 7521661fb..8de1bc56e 100644 --- a/libs/oeth/swap/src/components/BestRoutes.tsx +++ b/libs/oeth/swap/src/components/BestRoutes.tsx @@ -1,33 +1,33 @@ -import { Box } from '@mui/material'; +import Grid2 from '@mui/material/Unstable_Grid2/Grid2'; import { useHandleSelectSwapRoute } from '../hooks'; import { useSwapState } from '../state'; import { routeEq } from '../utils'; import { SwapRouteCard } from './SwapRouteCard'; -import type { BoxProps } from '@mui/material'; +import type { Grid2Props } from '@mui/material'; -export function BestRoutes(props: BoxProps) { - const [{ swapRoutes, selectedSwapRoute }] = useSwapState(); +export type BestRoutesProps = { isLoading: boolean } & Grid2Props; + +export function BestRoutes(props: Grid2Props) { + const [{ swapRoutes, selectedSwapRoute, isSwapRoutesLoading }] = + useSwapState(); const handleSelectSwapRoute = useHandleSelectSwapRoute(); return ( - + {swapRoutes.slice(0, 2).map((route, index) => ( - + + + ))} - + ); } diff --git a/libs/oeth/swap/src/components/SwapRoute.tsx b/libs/oeth/swap/src/components/SwapRoute.tsx index 1268210c2..2894f5be9 100644 --- a/libs/oeth/swap/src/components/SwapRoute.tsx +++ b/libs/oeth/swap/src/components/SwapRoute.tsx @@ -1,4 +1,4 @@ -import { Skeleton, Stack, Typography } from '@mui/material'; +import { Collapse, Skeleton, Stack, Typography } from '@mui/material'; import { Card, cardStyles } from '@origin/shared/components'; import { useIntl } from 'react-intl'; @@ -9,31 +9,6 @@ import { SwapRouteAccordion } from './SwapRouteAccordion'; import type { CardProps } from '@mui/material'; -import type { EstimatedSwapRoute } from '../types'; - -interface Swap { - type: 'swap'; -} -export interface Redeem { - type: 'redeem'; - tokenAbbreviation: string; - waitTime: string; -} - -export type Route = { - name: string; - icon: string | string[]; - quantity: number; - value: number; - rate: number; - transactionCost: number; -} & (Swap | Redeem); - -export type SwapRouteProps = { - isLoading: boolean; - routes: EstimatedSwapRoute[]; -}; - export function SwapRoute(props: Omit) { const intl = useIntl(); const [{ swapRoutes, isSwapRoutesLoading }] = useSwapState(); @@ -52,27 +27,26 @@ export function SwapRoute(props: Omit) { }} title={ isSwapRoutesLoading ? ( - theme.typography.pxToRem(12), - display: 'flex', - alignItems: 'center', - }} + ({ color: theme.palette.primary.contrastText })} > theme.palette.primary.contrastText, }} /> - {intl.formatMessage({ - defaultMessage: 'Finding the best route...', - })} - + + {intl.formatMessage({ + defaultMessage: 'Finding the best route...', + })} + + ) : ( ) { }), }} > - {hasContent ? ( - <> - - - - ) : undefined} + + + {swapRoutes.length > 2 && } + ); } diff --git a/libs/oeth/swap/src/components/SwapRouteCard.tsx b/libs/oeth/swap/src/components/SwapRouteCard.tsx index ba2c3c5ba..d48213bd8 100644 --- a/libs/oeth/swap/src/components/SwapRouteCard.tsx +++ b/libs/oeth/swap/src/components/SwapRouteCard.tsx @@ -1,26 +1,44 @@ -import { alpha, Box, Card, CardHeader, Stack, Typography } from '@mui/material'; +import { + alpha, + Box, + Card, + CardHeader, + Skeleton, + Stack, + Typography, +} from '@mui/material'; +import Grid2 from '@mui/material/Unstable_Grid2/Grid2'; import { tokens } from '@origin/shared/contracts'; import { usePrices } from '@origin/shared/providers'; -import { currencyFormat, quantityFormat } from '@origin/shared/utils'; +import { + currencyFormat, + formatAmount, + quantityFormat, +} from '@origin/shared/utils'; import { useIntl } from 'react-intl'; import { formatUnits } from 'viem'; import { routeActionLabel, routeActionLogos } from '../constants'; +import type { CardProps } from '@mui/material'; + import type { EstimatedSwapRoute } from '../types'; export type SwapRouteCardProps = { isSelected: boolean; isBest: boolean; + isLoading: boolean; onSelect: (route: EstimatedSwapRoute) => void; route: EstimatedSwapRoute; -}; +} & Omit; export function SwapRouteCard({ isSelected, isBest, + isLoading, onSelect, route, + ...rest }: SwapRouteCardProps) { const intl = useIntl(); const { data: prices } = usePrices(); @@ -35,6 +53,7 @@ export function SwapRouteCard({ return ( `1px solid ${theme.palette.grey[800]}`, borderRadius: 1, + height: 1, ...(isSelected ? { background: `linear-gradient(var(--mui-palette-grey-800), var(--mui-palette-grey-800)) padding-box, @@ -64,6 +84,7 @@ export function SwapRouteCard({ )} 100%) border-box;`, }, }), + ...rest?.sx, }} role="button" onClick={() => onSelect(route)} @@ -71,75 +92,58 @@ export function SwapRouteCard({ - - + + + {isLoading ? ( + + ) : ( + + )} + + - {intl.formatNumber(estimatedAmount, quantityFormat)}  - - ({intl.formatNumber(convertedAmount, currencyFormat)}) - + {isLoading ? ( + + ) : ( + formatAmount(route.estimatedAmount, route.tokenOut.decimals) + )} + + + + {isLoading ? ( + + ) : ( + `(${intl.formatNumber(convertedAmount, currencyFormat)})` + )} + + - {isBest ? ( - theme.shape.borderRadius, - background: (theme) => theme.palette.background.gradient1, - color: 'primary.contrastText', - fontSize: (theme) => theme.typography.pxToRem(12), - top: (theme) => theme.spacing(-3), - right: (theme) => theme.spacing(-2), - paddingInline: 1, - }} - > - {intl.formatMessage({ defaultMessage: 'Best' })} - - ) : undefined} - - - - ({intl.formatNumber(estimatedAmount, quantityFormat)}) - - + {isBest && ( + theme.shape.borderRadius, + background: (theme) => theme.palette.background.gradient1, + color: 'primary.contrastText', + fontSize: (theme) => theme.typography.pxToRem(12), + top: (theme) => theme.spacing(-3), + right: (theme) => theme.spacing(-2), + paddingInline: 1, + }} + > + {intl.formatMessage({ defaultMessage: 'Best' })} + + )} + } > @@ -148,65 +152,47 @@ export function SwapRouteCard({ variant="body2" sx={{ marginBlock: { xs: 1.5, md: 1 } }} > - {intl.formatMessage(routeActionLabel[route.action])} + {isLoading ? ( + + ) : ( + intl.formatMessage(routeActionLabel[route.action]) + )} - {intl.formatMessage({ defaultMessage: 'Rate:' })} - - 1:{route.rate} - + + {intl.formatMessage({ defaultMessage: 'Rate:' })} + + + {isLoading ? ( + + ) : ( + `1:${intl.formatNumber(route.rate, quantityFormat)}` + )} + - - {intl.formatMessage({ - defaultMessage: 'Gas:', - })} - - - ~{intl.formatNumber(gas, currencyFormat)} - + + {intl.formatMessage({ defaultMessage: 'Gas:' })} + + + {isLoading ? ( + + ) : ( + `~${intl.formatNumber(gas, currencyFormat)}` + )} + - {/*route.type === 'redeem' ? ( - - - {intl.formatMessage({ - defaultMessage: 'Wait time:', - })} - - - ~{route.waitTime} - - - ) : undefined */} ); diff --git a/libs/oeth/swap/src/components/TokenSelectModal.tsx b/libs/oeth/swap/src/components/TokenSelectModal.tsx index dd454311c..fee0e5feb 100644 --- a/libs/oeth/swap/src/components/TokenSelectModal.tsx +++ b/libs/oeth/swap/src/components/TokenSelectModal.tsx @@ -142,7 +142,7 @@ function TokenListItem({ token, ...rest }: TokenListItemProps) { {isBalanceLoading ? ( ) : ( - formatAmount(balance.value, balance.decimals) + formatAmount(balance?.value, balance?.decimals) )} diff --git a/libs/oeth/swap/src/hooks.ts b/libs/oeth/swap/src/hooks.ts index 3f4c514e0..62cbcd889 100644 --- a/libs/oeth/swap/src/hooks.ts +++ b/libs/oeth/swap/src/hooks.ts @@ -22,8 +22,6 @@ export const useHandleAmountInChange = () => { setSwapState( produce((state) => { state.amountIn = amount; - state.isAmountOutLoading = amount !== 0n; - state.isPriceOutLoading = amount !== 0n; state.isSwapRoutesLoading = amount !== 0n; }), ); @@ -173,13 +171,19 @@ export const useHandleApprove = () => { const curve = useCurve(); const queryClient = useQueryClient(); const pushNotification = usePushNotification(); - const [{ amountIn, selectedSwapRoute, tokenIn, tokenOut }] = useSwapState(); + const [{ amountIn, selectedSwapRoute, tokenIn, tokenOut }, setSwapState] = + useSwapState(); return useCallback(async () => { if (isNilOrEmpty(selectedSwapRoute)) { return; } + setSwapState( + produce((draft) => { + draft.isApprovalLoading = true; + }), + ); await swapActions[selectedSwapRoute.action].approve({ tokenIn, tokenOut, @@ -198,18 +202,33 @@ export const useHandleApprove = () => { title: intl.formatMessage({ defaultMessage: 'Approval complete' }), severity: 'success', }); + setSwapState( + produce((draft) => { + draft.isApprovalLoading = false; + }), + ); }, onError: () => { pushNotification({ title: intl.formatMessage({ defaultMessage: 'Approval failed' }), severity: 'error', }); + setSwapState( + produce((draft) => { + draft.isApprovalLoading = false; + }), + ); }, onReject: () => { pushNotification({ title: intl.formatMessage({ defaultMessage: 'Approval cancelled' }), severity: 'info', }); + setSwapState( + produce((draft) => { + draft.isApprovalLoading = false; + }), + ); }, }); }, [ @@ -219,6 +238,7 @@ export const useHandleApprove = () => { pushNotification, queryClient, selectedSwapRoute, + setSwapState, tokenIn, tokenOut, ]); @@ -231,6 +251,7 @@ export const useHandleSwap = () => { const pushNotification = usePushNotification(); const [ { amountIn, amountOut, selectedSwapRoute, slippage, tokenIn, tokenOut }, + setSwapState, ] = useSwapState(); return useCallback(async () => { @@ -238,6 +259,11 @@ export const useHandleSwap = () => { return; } + setSwapState( + produce((draft) => { + draft.isSwapLoading = true; + }), + ); await swapActions[selectedSwapRoute.action].swap({ tokenIn, tokenOut, @@ -259,19 +285,33 @@ export const useHandleSwap = () => { title: intl.formatMessage({ defaultMessage: 'Swap complete' }), severity: 'success', }); + setSwapState( + produce((draft) => { + draft.isSwapLoading = false; + }), + ); }, onError: () => { pushNotification({ title: intl.formatMessage({ defaultMessage: 'Swap failed' }), severity: 'error', }); + setSwapState( + produce((draft) => { + draft.isSwapLoading = false; + }), + ); }, onReject: () => { - console.log('REJECT'); pushNotification({ title: intl.formatMessage({ defaultMessage: 'Swap cancelled' }), severity: 'info', }); + setSwapState( + produce((draft) => { + draft.isSwapLoading = false; + }), + ); }, }); }, [ @@ -282,6 +322,7 @@ export const useHandleSwap = () => { pushNotification, queryClient, selectedSwapRoute, + setSwapState, slippage, tokenIn, tokenOut, diff --git a/libs/oeth/swap/src/state.ts b/libs/oeth/swap/src/state.ts index c9b093fb3..54b5d3960 100644 --- a/libs/oeth/swap/src/state.ts +++ b/libs/oeth/swap/src/state.ts @@ -19,15 +19,13 @@ export const { Provider: SwapProvider, useTracked: useSwapState } = tokenIn: tokens.mainnet.ETH, amountOut: 0n, tokenOut: tokens.mainnet.OETH, - isAmountOutLoading: false, - isPriceOutLoading: false, - isBalanceOutLoading: false, swapRoutes: [], selectedSwapRoute: null, + slippage: 0.01, isSwapRoutesLoading: false, isApproved: false, isApprovalLoading: false, - slippage: 0.01, + isSwapLoading: false, }); const { CurveRegistryExchange, OethPoolUnderlyings } = useCurve(); @@ -39,11 +37,10 @@ export const { Provider: SwapProvider, useTracked: useSwapState } = draft.swapRoutes = []; draft.selectedSwapRoute = null; draft.amountOut = 0n; - draft.isAmountOutLoading = false; - draft.isPriceOutLoading = false; draft.isSwapRoutesLoading = false; draft.isApproved = false; draft.isApprovalLoading = false; + draft.isSwapLoading = false; }), ); return; @@ -90,8 +87,6 @@ export const { Provider: SwapProvider, useTracked: useSwapState } = draft.swapRoutes = sortedRoutes; draft.selectedSwapRoute = sortedRoutes[0]; draft.amountOut = sortedRoutes[0].estimatedAmount ?? 0n; - draft.isAmountOutLoading = false; - draft.isPriceOutLoading = false; draft.isSwapRoutesLoading = false; }), ); diff --git a/libs/oeth/swap/src/types.ts b/libs/oeth/swap/src/types.ts index 1e5b638b5..2c479fb78 100644 --- a/libs/oeth/swap/src/types.ts +++ b/libs/oeth/swap/src/types.ts @@ -121,13 +121,11 @@ export type SwapState = { tokenIn: Token; amountOut: bigint; tokenOut: Token; - isAmountOutLoading: boolean; - isPriceOutLoading: boolean; - isBalanceOutLoading: boolean; swapRoutes: EstimatedSwapRoute[]; selectedSwapRoute: EstimatedSwapRoute | null; + slippage: number; isSwapRoutesLoading: boolean; isApproved: boolean; isApprovalLoading: boolean; - slippage: number; + isSwapLoading: boolean; }; diff --git a/libs/oeth/swap/src/views/SwapView.tsx b/libs/oeth/swap/src/views/SwapView.tsx index 6c6a0d47d..c3dc173fe 100644 --- a/libs/oeth/swap/src/views/SwapView.tsx +++ b/libs/oeth/swap/src/views/SwapView.tsx @@ -1,6 +1,14 @@ -import { useMemo, useState } from 'react'; +import { useState } from 'react'; -import { alpha, Box, Button, IconButton, Stack } from '@mui/material'; +import { + alpha, + Box, + Button, + CircularProgress, + Collapse, + IconButton, + Stack, +} from '@mui/material'; import { ApyHeader } from '@origin/oeth/shared'; import { Card, TokenInput } from '@origin/shared/components'; import { ConnectedButton, usePrices } from '@origin/shared/providers'; @@ -11,6 +19,7 @@ import { useAccount, useBalance } from 'wagmi'; import { GasPopover } from '../components/GasPopover'; import { SwapRoute } from '../components/SwapRoute'; import { TokenSelectModal } from '../components/TokenSelectModal'; +import { routeActionLabel } from '../constants'; import { useHandleAmountInChange, useHandleApprove, @@ -52,10 +61,10 @@ function SwapViewWrapped() { amountOut, tokenIn, tokenOut, - isAmountOutLoading, - isPriceOutLoading, - isBalanceOutLoading, selectedSwapRoute, + isSwapLoading, + isSwapRoutesLoading, + isApprovalLoading, }, ] = useSwapState(); const { tokensIn, tokensOut } = useTokenOptions(); @@ -77,16 +86,6 @@ function SwapViewWrapped() { const handleApprove = useHandleApprove(); const handleSwap = useHandleSwap(); - const needsApproval = useMemo( - () => - isConnected && - amountIn > 0n && - !isNilOrEmpty(selectedSwapRoute) && - selectedSwapRoute?.approvedAmount < amountIn && - allowance < amountIn, - [allowance, amountIn, isConnected, selectedSwapRoute], - ); - const handleCloseSelectionModal = () => { setTokenSource(null); }; @@ -95,6 +94,42 @@ function SwapViewWrapped() { handleTokenChange(tokenSource, value); }; + const needsApproval = + isConnected && + amountIn > 0n && + !isBalTokenInLoading && + balTokenIn.value >= amountIn && + !isNilOrEmpty(selectedSwapRoute) && + selectedSwapRoute?.approvedAmount < amountIn && + allowance < amountIn; + + const swapButtonLabel = + amountIn === 0n + ? intl.formatMessage({ defaultMessage: 'Enter an amount' }) + : amountIn > balTokenIn?.value + ? intl.formatMessage({ defaultMessage: 'Insufficient funds' }) + : !isNilOrEmpty(selectedSwapRoute) + ? intl.formatMessage(routeActionLabel[selectedSwapRoute?.action]) + : ''; + + const amountInInputDisabled = isSwapLoading || isApprovalLoading; + + const approveButtonDisabled = + isNilOrEmpty(selectedSwapRoute) || + isApprovalLoading || + amountIn > balTokenIn?.value; + + const swapButtonDisabled = + needsApproval || + isNilOrEmpty(selectedSwapRoute) || + isBalTokenInLoading || + amountIn > balTokenIn?.value || + amountIn === 0n; + + const approveButtonLoading = isSwapRoutesLoading || isApprovalLoading; + + const swapButtonLoading = isSwapRoutesLoading || isSwapLoading; + return ( <> @@ -144,6 +179,7 @@ function SwapViewWrapped() { tokenPriceUsd={prices?.[tokenIn.symbol]} isPriceLoading={isPriceLoading} isConnected={isConnected} + isAmountDisabled={amountInInputDisabled} sx={{ ...commonStyles, backgroundColor: 'grey.900', @@ -175,15 +211,15 @@ function SwapViewWrapped() { { setTokenSource('tokenOut'); }} tokenPriceUsd={prices?.[tokenOut.symbol]} - isPriceLoading={isPriceOutLoading || isPriceLoading} + isPriceLoading={isSwapRoutesLoading || isPriceLoading} inputProps={{ readOnly: true }} isConnected={isConnected} sx={{ @@ -196,13 +232,31 @@ function SwapViewWrapped() { - {needsApproval && ( - - )} - - {intl.formatMessage({ defaultMessage: 'Swap' })} + + + {swapButtonLoading ? ( + + ) : ( + swapButtonLabel + )} ( value={amount} decimals={decimals} onChange={onAmountChange} + disabled={isAmountDisabled} isLoading={isAmountLoading} ref={ref} sx={{ flex: 1 }} From 8139dba431a69f32e0fdab518a1e93627726cf78 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Fri, 15 Sep 2023 23:25:01 +0200 Subject: [PATCH 2/3] fix: oeth - eth approval for curve swap --- libs/oeth/swap/src/actions/swapCurve/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/oeth/swap/src/actions/swapCurve/index.ts b/libs/oeth/swap/src/actions/swapCurve/index.ts index 9599b55fb..798ade3ce 100644 --- a/libs/oeth/swap/src/actions/swapCurve/index.ts +++ b/libs/oeth/swap/src/actions/swapCurve/index.ts @@ -116,7 +116,7 @@ const allowance: Allowance = async ({ tokenIn, tokenOut, curve }) => { return 0n; } - if (isNilOrEmpty(tokenIn.address) || isNilOrEmpty(tokenOut.address)) { + if (isNilOrEmpty(tokenIn.address)) { return maxUint256; } From 560d2eda68ee05ffd57792d2a433a1e88d0bb1e5 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Fri, 15 Sep 2023 23:28:49 +0200 Subject: [PATCH 3/3] fix: lock file --- pnpm-lock.yaml | 202 +------------------------------------------------ 1 file changed, 1 insertion(+), 201 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7d59ca51b..28f6e9b9b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,9 +5,6 @@ settings: excludeLinksFromLockfile: false dependencies: - '@curvefi/api': - specifier: ^2.46.6 - version: 2.46.6 '@emotion/react': specifier: ^11.11.1 version: 11.11.1(@types/react@18.2.21)(react@18.2.0) @@ -280,10 +277,6 @@ packages: resolution: {integrity: sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==} dev: true - /@adraffy/ens-normalize@1.9.2: - resolution: {integrity: sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==} - dev: false - /@adraffy/ens-normalize@1.9.4: resolution: {integrity: sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==} dev: false @@ -1938,20 +1931,6 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true - /@curvefi/api@2.46.6: - resolution: {integrity: sha512-/9JEdwiC0ZAEftMZQOfrEtCPGUlOUVXPQAvPa3DM/KTPe9IXYp7jCGv3aVU9Fd/EJgi2apL9KeaZXh1wyAJqow==} - dependencies: - axios: 0.21.4 - bignumber.js: 9.1.2 - ethcall: 6.0.2(ethers@6.7.1) - ethers: 6.7.1 - memoizee: 0.4.15 - transitivePeerDependencies: - - bufferutil - - debug - - utf-8-validate - dev: false - /@discoveryjs/json-ext@0.5.7: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} @@ -3782,19 +3761,11 @@ packages: '@noble/hashes': 1.3.2 dev: false - /@noble/hashes@1.1.2: - resolution: {integrity: sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==} - dev: false - /@noble/hashes@1.3.2: resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} engines: {node: '>= 16'} dev: false - /@noble/secp256k1@1.7.1: - resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} - dev: false - /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -6913,14 +6884,6 @@ packages: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} dev: true - /@types/node@18.14.2: - resolution: {integrity: sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==} - dev: true - - /@types/node@18.15.13: - resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} - dev: false - /@types/node@20.6.0: resolution: {integrity: sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==} @@ -8085,14 +8048,6 @@ packages: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} dev: true - /abi-coder@5.0.0(ethers@6.7.1): - resolution: {integrity: sha512-Kpyv/AhAaIaVJiJ6S/xqoTsiJrfSMc3QsBCiRDqic3o1CZNKGR3CIeT1K/1VZ7Wk5uSwsOAxQcke1TVUEz+usg==} - peerDependencies: - ethers: ^6.0.0 - dependencies: - ethers: 6.7.1 - dev: false - /abitype@0.8.7(typescript@5.2.2): resolution: {integrity: sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w==} peerDependencies: @@ -8182,10 +8137,6 @@ packages: resolution: {integrity: sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==} dev: false - /aes-js@4.0.0-beta.5: - resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} - dev: false - /agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -8509,14 +8460,6 @@ packages: engines: {node: '>=4'} dev: true - /axios@0.21.4: - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - dependencies: - follow-redirects: 1.15.2 - transitivePeerDependencies: - - debug - dev: false - /axios@1.5.0: resolution: {integrity: sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==} dependencies: @@ -8726,10 +8669,6 @@ packages: bindings: 1.5.0 dev: false - /bignumber.js@9.1.2: - resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} - dev: false - /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} @@ -9460,13 +9399,6 @@ packages: /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - /d@1.0.1: - resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} - dependencies: - es5-ext: 0.10.62 - type: 1.2.0 - dev: false - /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true @@ -10043,24 +9975,6 @@ packages: is-symbol: 1.0.4 dev: true - /es5-ext@0.10.62: - resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} - engines: {node: '>=0.10'} - requiresBuild: true - dependencies: - es6-iterator: 2.0.3 - es6-symbol: 3.1.3 - next-tick: 1.1.0 - dev: false - - /es6-iterator@2.0.3: - resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} - dependencies: - d: 1.0.1 - es5-ext: 0.10.62 - es6-symbol: 3.1.3 - dev: false - /es6-promise@4.2.8: resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} dev: false @@ -10071,22 +9985,6 @@ packages: es6-promise: 4.2.8 dev: false - /es6-symbol@3.1.3: - resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} - dependencies: - d: 1.0.1 - ext: 1.7.0 - dev: false - - /es6-weak-map@2.0.3: - resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} - dependencies: - d: 1.0.1 - es5-ext: 0.10.62 - es6-iterator: 2.0.3 - es6-symbol: 3.1.3 - dev: false - /esbuild-plugin-alias@0.2.1: resolution: {integrity: sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==} dev: true @@ -10580,39 +10478,6 @@ packages: fast-safe-stringify: 2.1.1 dev: false - /ethcall@6.0.2(ethers@6.7.1): - resolution: {integrity: sha512-FyaKLlxtaVt+kRmhzDG3YfW4VxqasxZE2CDSfylMVp8kCxsBikzFE1BO90yAMGdjdwaX0kHlvjWSxKRpiEcI4w==} - peerDependencies: - ethers: ^6.0.0 - dependencies: - '@types/node': 20.6.0 - abi-coder: 5.0.0(ethers@6.7.1) - ethers: 6.7.1 - dev: false - - /ethers@6.7.1: - resolution: {integrity: sha512-qX5kxIFMfg1i+epfgb0xF4WM7IqapIIu50pOJ17aebkxxa4BacW5jFrQRmCJpDEg2ZK2oNtR5QjrQ1WDBF29dA==} - engines: {node: '>=14.0.0'} - dependencies: - '@adraffy/ens-normalize': 1.9.2 - '@noble/hashes': 1.1.2 - '@noble/secp256k1': 1.7.1 - '@types/node': 18.15.13 - aes-js: 4.0.0-beta.5 - tslib: 2.4.0 - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false - - /event-emitter@0.3.5: - resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} - dependencies: - d: 1.0.1 - es5-ext: 0.10.62 - dev: false - /eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -10693,12 +10558,6 @@ packages: - supports-color dev: true - /ext@1.7.0: - resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} - dependencies: - type: 2.7.2 - dev: false - /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: true @@ -11780,10 +11639,6 @@ packages: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: true - /is-promise@2.2.2: - resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} - dev: false - /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -12081,7 +11936,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.14.2 + '@types/node': 20.6.0 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -12559,12 +12414,6 @@ packages: dependencies: yallist: 4.0.0 - /lru-queue@0.1.0: - resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} - dependencies: - es5-ext: 0.10.62 - dev: false - /lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -12655,19 +12504,6 @@ packages: engines: {node: '>= 0.6'} dev: true - /memoizee@0.4.15: - resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} - dependencies: - d: 1.0.1 - es5-ext: 0.10.62 - 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 - dev: false - /memoizerific@1.11.3: resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} dependencies: @@ -12866,10 +12702,6 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: true - /next-tick@1.1.0: - resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - dev: false - /no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: @@ -14939,13 +14771,6 @@ packages: /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - /timers-ext@0.1.7: - resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} - dependencies: - es5-ext: 0.10.62 - next-tick: 1.1.0 - dev: false - /tiny-invariant@1.3.1: resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} dev: true @@ -15160,10 +14985,6 @@ packages: /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - /tslib@2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - dev: false - /tslib@2.4.1: resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} dev: true @@ -15239,14 +15060,6 @@ packages: mime-types: 2.1.35 dev: true - /type@1.2.0: - resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} - dev: false - - /type@2.7.2: - resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} - dev: false - /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} engines: {node: '>= 0.4'} @@ -16213,19 +16026,6 @@ packages: optional: true dev: true - /ws@8.5.0: - resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: false - /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'}