diff --git a/apps/evm/package.json b/apps/evm/package.json index f94437dcff..ff2656f74b 100644 --- a/apps/evm/package.json +++ b/apps/evm/package.json @@ -90,7 +90,6 @@ "@types/lodash.once": "4.1.9", "@types/lodash.zip": "4.2.9", "@types/node": "20", - "@types/numeral": "2.0.2", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", "@types/react-slider": "1.3.1", diff --git a/apps/evm/src/lib/hooks/useSlippageTolerance.ts b/apps/evm/src/lib/hooks/useSlippageTolerance.ts index 9ca85d4ac8..40d04f7383 100644 --- a/apps/evm/src/lib/hooks/useSlippageTolerance.ts +++ b/apps/evm/src/lib/hooks/useSlippageTolerance.ts @@ -1,11 +1,11 @@ 'use client' -import { useLocalStorage } from '@sushiswap/hooks' +import { SlippageToleranceStorageKey, useLocalStorage } from '@sushiswap/hooks' import { useMemo } from 'react' import { Percent } from 'sushi/math' export const useSlippageTolerance = ( - key: string | undefined = 'swapSlippage', + key: SlippageToleranceStorageKey = SlippageToleranceStorageKey.Swap, ) => { const [slippageTolerance, setSlippageTolerance] = useLocalStorage< number | string diff --git a/apps/evm/src/ui/pool/AddSectionReviewModalConcentrated.tsx b/apps/evm/src/ui/pool/AddSectionReviewModalConcentrated.tsx index b450ecafe1..b66b9e1831 100644 --- a/apps/evm/src/ui/pool/AddSectionReviewModalConcentrated.tsx +++ b/apps/evm/src/ui/pool/AddSectionReviewModalConcentrated.tsx @@ -1,3 +1,5 @@ +import { CogIcon } from '@heroicons/react-v1/outline' +import { SlippageToleranceStorageKey, TTLStorageKey } from '@sushiswap/hooks' import { Button, Currency, @@ -10,11 +12,15 @@ import { DialogReview, DialogTitle, Dots, + IconButton, List, + SettingsModule, + SettingsOverlay, } from '@sushiswap/ui' import { createErrorToast, createToast } from '@sushiswap/ui/components/toast' import { UseCallParameters, + getDefaultTTL, getV3NonFungiblePositionManagerContractConfig, useAccount, useCall, @@ -32,7 +38,6 @@ import { SushiSwapV3FeeAmount, isSushiSwapV3ChainId } from 'sushi/config' import { Amount, Type, tryParseAmount } from 'sushi/currency' import { NonfungiblePositionManager, Position } from 'sushi/pool' import { Hex, SendTransactionReturnType, UserRejectedRequestError } from 'viem' - import { useConcentratedDerivedMintInfo } from './ConcentratedLiquidityProvider' interface AddSectionReviewModalConcentratedProps @@ -74,8 +79,13 @@ export const AddSectionReviewModalConcentrated: FC< successLink, }) => { const { address, chain } = useAccount() - const { data: deadline } = useTransactionDeadline({ chainId }) - const [slippageTolerance] = useSlippageTolerance('addLiquidity') + const { data: deadline } = useTransactionDeadline({ + storageKey: TTLStorageKey.AddLiquidity, + chainId, + }) + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.AddLiquidity, + ) const { [Bound.LOWER]: priceLower, [Bound.UPPER]: priceUpper } = pricesAtTicks const client = usePublicClient() @@ -245,15 +255,41 @@ export const AddSectionReviewModalConcentrated: FC< <> {children} - - - {token0?.symbol}/{token1?.symbol} - - - {' '} - {noLiquidity ? 'Create liquidity pool' : 'Add liquidity'} - - +
+ + + {token0?.symbol}/{token1?.symbol} + + + {' '} + {noLiquidity ? 'Create liquidity pool' : 'Add liquidity'} + + + + + +
diff --git a/apps/evm/src/ui/pool/AddSectionReviewModalLegacy.tsx b/apps/evm/src/ui/pool/AddSectionReviewModalLegacy.tsx index 844ebc2dee..92ce624e84 100644 --- a/apps/evm/src/ui/pool/AddSectionReviewModalLegacy.tsx +++ b/apps/evm/src/ui/pool/AddSectionReviewModalLegacy.tsx @@ -1,3 +1,5 @@ +import { CogIcon } from '@heroicons/react-v1/outline' +import { SlippageToleranceStorageKey, TTLStorageKey } from '@sushiswap/hooks' import { DialogConfirm, DialogContent, @@ -8,6 +10,9 @@ import { DialogReview, DialogTitle, DialogTrigger, + IconButton, + SettingsModule, + SettingsOverlay, } from '@sushiswap/ui' import { Button } from '@sushiswap/ui/components/button' import { Dots } from '@sushiswap/ui/components/dots' @@ -15,6 +20,7 @@ import { createErrorToast, createToast } from '@sushiswap/ui/components/toast' import { SushiSwapV2PoolState, UseSimulateContractParameters, + getDefaultTTL, getSushiSwapRouterContractConfig, useAccount, usePublicClient, @@ -34,7 +40,6 @@ import { BentoBoxChainId } from 'sushi/config' import { Amount, Type } from 'sushi/currency' import { ZERO } from 'sushi/math' import { Address, UserRejectedRequestError } from 'viem' - import { AddSectionReviewModal } from './AddSectionReviewModal' interface UseAddSushiSwapV2 { @@ -285,10 +290,15 @@ export const AddSectionReviewModalLegacy: FC = children, onSuccess: _onSuccess, }) => { - const { data: deadline } = useTransactionDeadline({ chainId }) + const { data: deadline } = useTransactionDeadline({ + storageKey: TTLStorageKey.AddLiquidity, + chainId, + }) const { address } = useAccount() const { approved } = useApproved(APPROVE_TAG_ADD_LEGACY) - const [slippageTolerance] = useSlippageTolerance('addLiquidity') + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.AddLiquidity, + ) const client = usePublicClient() const onSuccess = useCallback( @@ -390,12 +400,38 @@ export const AddSectionReviewModalLegacy: FC = <> {children} - - Add liquidity - - Please review your entered details. - - +
+ + Add liquidity + + Please review your entered details. + + + + + +
[token0, token1], [token0, token1]) const { data: rebases } = useBentoBoxTotals({ chainId, currencies: tokens }) const contract = useTridentRouterContract(chainId) - const [slippageTolerance] = useSlippageTolerance('addLiquidity') + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.AddLiquidity, + ) const [minAmount0, minAmount1] = useMemo(() => { return [ input0 diff --git a/apps/evm/src/ui/pool/AddSectionWidget.tsx b/apps/evm/src/ui/pool/AddSectionWidget.tsx index f6e5c726b0..ed21f098a6 100644 --- a/apps/evm/src/ui/pool/AddSectionWidget.tsx +++ b/apps/evm/src/ui/pool/AddSectionWidget.tsx @@ -1,5 +1,6 @@ import { CogIcon } from '@heroicons/react-v1/outline' import { PlusIcon } from '@heroicons/react-v1/solid' +import { SlippageToleranceStorageKey, TTLStorageKey } from '@sushiswap/hooks' import { WidgetAction, WidgetDescription, @@ -12,6 +13,7 @@ import { SettingsOverlay, } from '@sushiswap/ui/components/settings' import { Widget, WidgetHeader } from '@sushiswap/ui/components/widget' +import { getDefaultTTL } from '@sushiswap/wagmi' import { Web3Input } from '@sushiswap/wagmi/components/web3-input' import React, { FC, ReactNode } from 'react' import { ChainId } from 'sushi/chain' @@ -54,14 +56,19 @@ export const AddSectionWidget: FC = ({ ('0') - const [slippageTolerance] = useSlippageTolerance('removeLiquidity') - const { data: deadline } = useTransactionDeadline({ chainId }) + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.RemoveLiquidity, + ) + const { data: deadline } = useTransactionDeadline({ + storageKey: TTLStorageKey.RemoveLiquidity, + chainId, + }) const debouncedValue = useDebounce(value, 300) const _onChange = useCallback( @@ -334,12 +344,20 @@ export const ConcentratedLiquidityRemoveWidget: FC<
- - - {token0?.symbol}/{token1?.symbol} - - Remove Liquidity - +
+ + + {token0?.symbol}/{token1?.symbol} + + Remove Liquidity + + + + +
diff --git a/apps/evm/src/ui/pool/MigrateTab.tsx b/apps/evm/src/ui/pool/MigrateTab.tsx index 2b2491fb95..fe2c9a02cc 100644 --- a/apps/evm/src/ui/pool/MigrateTab.tsx +++ b/apps/evm/src/ui/pool/MigrateTab.tsx @@ -1,7 +1,9 @@ 'use client' +import { CogIcon } from '@heroicons/react-v1/outline' import { SwitchHorizontalIcon } from '@heroicons/react-v1/solid' import { Pool } from '@sushiswap/client' +import { SlippageToleranceStorageKey, TTLStorageKey } from '@sushiswap/hooks' import { Card, CardContent, @@ -24,14 +26,18 @@ import { DialogTitle, DialogTrigger, Dots, + IconButton, List, Message, Separator, + SettingsModule, + SettingsOverlay, } from '@sushiswap/ui' import { Button } from '@sushiswap/ui/components/button' import { V3MigrateChainId, V3MigrateContractConfig, + getDefaultTTL, getMasterChefContractConfig, useAccount, useMasterChefWithdraw, @@ -196,7 +202,9 @@ export const MigrateTab: FC<{ pool: Pool }> = withCheckerRoot(({ pool }) => { ) const [invertPrice, setInvertPrice] = useState(false) const [invertTokens, setInvertTokens] = useState(false) - const [slippageTolerance] = useSlippageTolerance('addLiquidity') + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.AddLiquidity, + ) const { data: { token0: _token0, token1: _token1, liquidityToken }, @@ -459,6 +467,7 @@ export const MigrateTab: FC<{ pool: Pool }> = withCheckerRoot(({ pool }) => { const { approved: approvedMigrate } = useApproved(APPROVE_TAG_MIGRATE) const { data: deadline } = useTransactionDeadline({ + storageKey: TTLStorageKey.AddLiquidity, chainId: pool.chainId as ChainId, }) @@ -718,9 +727,39 @@ export const MigrateTab: FC<{ pool: Pool }> = withCheckerRoot(({ pool }) => { - - Migrate Liquidity - +
+ + Migrate Liquidity + + + + +
{token0?.symbol}/{token1?.symbol} • SushiSwap V3 • {feeAmount / 10000}% diff --git a/apps/evm/src/ui/pool/PositionView.tsx b/apps/evm/src/ui/pool/PositionView.tsx index f596969930..39ed693143 100644 --- a/apps/evm/src/ui/pool/PositionView.tsx +++ b/apps/evm/src/ui/pool/PositionView.tsx @@ -1,6 +1,7 @@ 'use client' import { CogIcon } from '@heroicons/react-v1/outline' +import { SlippageToleranceStorageKey, TTLStorageKey } from '@sushiswap/hooks' import { useAngleRewards } from '@sushiswap/react-query' import { Card, @@ -30,9 +31,10 @@ import { classNames, } from '@sushiswap/ui' import { Button } from '@sushiswap/ui/components/button' -import { FormattedPrice } from '@sushiswap/ui/components/formatted-price' +import { FormattedNumber } from '@sushiswap/ui/components/formatted-number' import { SkeletonText } from '@sushiswap/ui/components/skeleton' import { + getDefaultTTL, useAccount, useConcentratedLiquidityPositionsFromTokenId, useConcentratedPositionInfo, @@ -238,14 +240,20 @@ const Component: FC<{ id: string }> = ({ id }) => { = ({ id }) => { title={ <> 1 {unwrapToken(currencyBase)?.symbol} ={' '} - = ({ id }) => { '0' ) : ( <> - = ({ id }) => { '∞' ) : ( <> - > = {fullRange ? ( '0' ) : ( - > = {fullRange ? ( '∞' ) : ( - > =
Current:{' '} - = const client = usePublicClient() const { address, chain } = useAccount() const { data: deadline } = useTransactionDeadline({ + storageKey: TTLStorageKey.RemoveLiquidity, chainId: _pool.chainId as ChainId, }) const contract = useSushiSwapRouterContract( _pool.chainId as SushiSwapV2ChainId, ) - const [slippageTolerance] = useSlippageTolerance('removeLiquidity') + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.RemoveLiquidity, + ) const [percentage, setPercentage] = useState('0') const percentToRemove = useMemo( diff --git a/apps/evm/src/ui/pool/RemoveSectionTrident.tsx b/apps/evm/src/ui/pool/RemoveSectionTrident.tsx index 304c196660..ad2e0cc2e5 100644 --- a/apps/evm/src/ui/pool/RemoveSectionTrident.tsx +++ b/apps/evm/src/ui/pool/RemoveSectionTrident.tsx @@ -1,7 +1,7 @@ 'use client' import { Pool, Protocol } from '@sushiswap/client' -import { useIsMounted } from '@sushiswap/hooks' +import { SlippageToleranceStorageKey, useIsMounted } from '@sushiswap/hooks' import { Button } from '@sushiswap/ui/components/button' import { Dots } from '@sushiswap/ui/components/dots' import { createToast } from '@sushiswap/ui/components/toast' @@ -67,7 +67,9 @@ export const RemoveSectionTrident: FC = const { signature } = useSignature(APPROVE_TAG_REMOVE_TRIDENT) const { setSignature } = useApprovedActions(APPROVE_TAG_REMOVE_TRIDENT) const contract = useTridentRouterContract(_pool.chainId as TridentChainId) - const [slippageTolerance] = useSlippageTolerance('removeLiquidity') + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.RemoveLiquidity, + ) const [percentage, setPercentage] = useState('0') const percentToRemove = useMemo( diff --git a/apps/evm/src/ui/pool/RemoveSectionWidget.tsx b/apps/evm/src/ui/pool/RemoveSectionWidget.tsx index 74b5231ed0..61a69612fb 100644 --- a/apps/evm/src/ui/pool/RemoveSectionWidget.tsx +++ b/apps/evm/src/ui/pool/RemoveSectionWidget.tsx @@ -27,6 +27,8 @@ import { ChainId } from 'sushi/chain' import { Amount, Type } from 'sushi/currency' import { ZERO } from 'sushi/math' +import { SlippageToleranceStorageKey, TTLStorageKey } from '@sushiswap/hooks' +import { getDefaultTTL } from '@sushiswap/wagmi' import { usePoolPosition } from './PoolPositionProvider' interface RemoveSectionWidgetProps { @@ -42,6 +44,7 @@ interface RemoveSectionWidgetProps { } export const RemoveSectionWidget: FC = ({ + chainId, percentage, setPercentage, token0Minimum, @@ -61,12 +64,19 @@ export const RemoveSectionWidget: FC = ({ = const client = usePublicClient() const { address, chain } = useAccount() - const [slippageTolerance] = useSlippageTolerance('addSteerLiquidity') + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.AddSteerLiquidity, + ) const { approved } = useApproved(APPROVE_TAG_STEER) const { data: accountPosition } = useSteerAccountPosition({ diff --git a/apps/evm/src/ui/pool/Steer/SteerLiquidityManagement/Remove/SteerPositionRemove.tsx b/apps/evm/src/ui/pool/Steer/SteerLiquidityManagement/Remove/SteerPositionRemove.tsx index fcc4dd405d..66ab09a73d 100644 --- a/apps/evm/src/ui/pool/Steer/SteerLiquidityManagement/Remove/SteerPositionRemove.tsx +++ b/apps/evm/src/ui/pool/Steer/SteerLiquidityManagement/Remove/SteerPositionRemove.tsx @@ -2,7 +2,11 @@ import { CogIcon } from '@heroicons/react-v1/solid' import { SteerVault } from '@sushiswap/client' -import { useDebounce, useSlippageTolerance } from '@sushiswap/hooks' +import { + SlippageToleranceStorageKey, + useDebounce, + useSlippageTolerance, +} from '@sushiswap/hooks' import { isSteerChainId } from '@sushiswap/steer-sdk' import { steerMultiPositionManager } from '@sushiswap/steer-sdk/abi' import { @@ -50,7 +54,9 @@ export const SteerPositionRemove: FC = ({ const client = usePublicClient() const { address: account, chain } = useAccount() const [value, setValue] = useState('0') - const [slippageTolerance] = useSlippageTolerance('removeSteerLiquidity') + const [slippageTolerance] = useSlippageTolerance( + SlippageToleranceStorageKey.RemoveSteerLiquidity, + ) const debouncedValue = useDebounce(value, 300) const slippagePercent = useMemo(() => { @@ -241,7 +247,7 @@ export const SteerPositionRemove: FC = ({ Minimum price - {' '} + {' '} {vault.token0.symbol}/{vault.token1.symbol} Maximum price - {' '} + {' '} {vault.token0.symbol}/{vault.token1.symbol} diff --git a/apps/evm/src/ui/pool/columns.tsx b/apps/evm/src/ui/pool/columns.tsx index 1cbc41544f..059819c2c4 100644 --- a/apps/evm/src/ui/pool/columns.tsx +++ b/apps/evm/src/ui/pool/columns.tsx @@ -1,6 +1,7 @@ import { Pool, Protocol } from '@sushiswap/client' import { AngleRewardsPool } from '@sushiswap/react-query' import { + FormattedNumber, NetworkIcon, Tooltip, TooltipContent, @@ -485,14 +486,20 @@ export const TX_AMOUNT_IN_V2_COLUMN = ( cell: ({ row }) => { switch (row.original.type) { case TransactionType.Swap: - return `${row.original.amountIn.toPrecision(2)} ${ - row.original.tokenIn.symbol - }` + return ( + + {' '} + {row.original.tokenIn.symbol} + + ) case TransactionType.Mint: case TransactionType.Burn: - return `${row.original.amount0.toPrecision(6)} ${ - row.original.pool.token0.symbol - }` + return ( + + {' '} + {row.original.pool.token0.symbol} + + ) } }, meta: { @@ -508,14 +515,22 @@ export const TX_AMOUNT_OUT_V2_COLUMN = ( cell: ({ row }) => { switch (row.original.type) { case TransactionType.Swap: - return `${Math.abs(row.original.amountOut).toFixed(2)} ${ - row.original.tokenOut.symbol - }` + return ( + + {' '} + {row.original.tokenOut.symbol} + + ) case TransactionType.Mint: case TransactionType.Burn: - return `${row.original.amount1.toFixed(2)} ${ - row.original.pool.token1.symbol - }` + return ( + + {' '} + {row.original.pool.token1.symbol} + + ) } }, meta: { @@ -580,12 +595,22 @@ export const TX_AMOUNT_IN_V3_COLUMN = ( ? [row.pool.token0, row.pool.token1] : [row.pool.token1, row.pool.token0] - return `${Math.abs(amounts[0]).toPrecision(6)} ${tokens[0].symbol}` + return ( + + {' '} + {tokens[0].symbol} + + ) } case TransactionTypeV3.Mint: case TransactionTypeV3.Burn: case TransactionTypeV3.Collect: - return `${row.amount0.toPrecision(6)} ${row.pool.token0.symbol}` + return ( + + {' '} + {row.pool.token0.symbol} + + ) } }, meta: { @@ -611,12 +636,22 @@ export const TX_AMOUNT_OUT_V3_COLUMN = ( ? [row.pool.token0, row.pool.token1] : [row.pool.token1, row.pool.token0] - return `${Math.abs(amounts[1]).toFixed(2)} ${tokens[1].symbol}` + return ( + + {' '} + {tokens[1].symbol} + + ) } case TransactionTypeV3.Mint: case TransactionTypeV3.Burn: case TransactionTypeV3.Collect: - return `${row.amount1.toFixed(2)} ${row.pool.token1.symbol}` + return ( + + {' '} + {row.pool.token1.symbol} + + ) } }, meta: { diff --git a/apps/evm/src/ui/swap/cross-chain/cross-chain-swap-token-not-found-dialog.tsx b/apps/evm/src/ui/swap/cross-chain/cross-chain-swap-token-not-found-dialog.tsx index 6aae8bc65c..127faef1f6 100644 --- a/apps/evm/src/ui/swap/cross-chain/cross-chain-swap-token-not-found-dialog.tsx +++ b/apps/evm/src/ui/swap/cross-chain/cross-chain-swap-token-not-found-dialog.tsx @@ -9,17 +9,18 @@ import { DialogFooter, DialogHeader, DialogTitle, + Message, + NetworkIcon, } from '@sushiswap/ui' import { Button } from '@sushiswap/ui/components/button' -import { GoPlusLabsIcon } from '@sushiswap/ui/components/icons' +import { Icon } from '@sushiswap/ui/components/currency/Icon' import { List } from '@sushiswap/ui/components/list' -import { useTokenWithCache } from '@sushiswap/wagmi' +import { TokenSecurityView, useTokenWithCache } from '@sushiswap/wagmi' import React, { useCallback, useMemo } from 'react' import { Chain } from 'sushi/chain' -import { defaultQuoteCurrency } from 'sushi/config' +import { defaultQuoteCurrency, isTokenSecurityChainId } from 'sushi/config' import { Native, Token } from 'sushi/currency' import { shortenAddress } from 'sushi/format' - import { useDerivedStateCrossChainSwap } from './derivedstate-cross-chain-swap-provider' export const CrossChainSwapTokenNotFoundDialog = () => { @@ -57,7 +58,7 @@ export const CrossChainSwapTokenNotFoundDialog = () => { const onImport = useCallback( ([token0, token1]: (Token | undefined)[]) => { - const _tokens = [] + const _tokens: Token[] = [] if (tokenFrom?.status !== 'APPROVED' && token0) _tokens.push(token0) if (tokenTo?.status !== 'APPROVED' && token1) _tokens.push(token1) @@ -82,7 +83,10 @@ export const CrossChainSwapTokenNotFoundDialog = () => { ) }, [chainId0, chainId1, setTokens]) - const { data: tokenSecurity } = useTokenSecurity({ + const { + data: tokenSecurityResponse, + isInitialLoading: tokenSecurityLoading, + } = useTokenSecurity({ currencies: useMemo( () => [ ...(token0NotInList && tokenFrom?.token ? [tokenFrom.token] : []), @@ -97,13 +101,18 @@ export const CrossChainSwapTokenNotFoundDialog = () => { ), }) - const isNotHoneyPot = Boolean( - !tokenFromLoading && - !tokenToLoading && - (token0NotInList || token1NotInList), + const honeypot = Boolean( + (tokenFrom?.token && + tokenSecurityResponse?.[tokenFrom?.token?.address]?.is_honeypot) || + (tokenTo?.token && + tokenSecurityResponse?.[tokenTo?.token?.address]?.is_honeypot), ) - if (!tokenSecurity) return null + if ( + (isTokenSecurityChainId(chainId0) || isTokenSecurityChainId(chainId1)) && + tokenSecurityLoading + ) + return null return ( { !tokenToLoading && (token0NotInList || token1NotInList), )} + onOpenChange={(open) => !open && reset()} > - + - {isNotHoneyPot ? ( - <> - - Unknown token{tokenFrom?.token && tokenTo?.token ? 's' : ''} - - - Anyone can create a token, including creating fake versions of - existing tokens that claim to represent projects. If you - purchase this token, you may not be able to sell it back. - - - ) : ( - <> - - Honeypot token{tokenSecurity.honeypots.length > 1 ? 's' : ''}{' '} - detected - - - {tokenSecurity.honeypots.length > 1 - ? 'These tokens have been identified as potential honeypot scams and are not supported. Do not interact with these tokens to safeguard your assets.' - : 'This token has been identified as a potential honeypot scam and is not supported. Do not interact with this token to safeguard your assets.'}{' '} - Click{' '} - - here - {' '} - to learn more about honepot scams. - - - )} - -
- {isNotHoneyPot ? ( - <> - {token0 && token0NotInList && !tokenFrom?.token && ( - - - Token {tokenFrom?.token && tokenTo?.token ? '1' : ''} - - -

- Could not retrieve token info for{' '} - - {shortenAddress(token0.wrapped.address)} - {' '} - are you sure this token is on {Chain.from(chainId0)?.name} - ? -

-
-
- )} - {token1 && token1NotInList && !tokenTo?.token && ( - - - Token {tokenFrom?.token && tokenTo?.token ? '2' : ''} - - -

- Could not retrieve token info for{' '} - - {shortenAddress(token1.wrapped.address)} - {' '} - are you sure this token is on {Chain.from(chainId1)?.name} - ? -

-
-
- )} - {token0NotInList && tokenFrom?.token && ( - - - Token {tokenFrom.token && tokenTo?.token ? '1' : ''} - - - - {tokenFrom.token.name} - - - {tokenFrom.token.symbol} - - - - {shortenAddress(tokenFrom.token.address)} - - - - - )} - {token1NotInList && tokenTo?.token && ( - - - Token {tokenFrom?.token && tokenTo?.token ? '2' : ''} - - - - {tokenTo.token.name} - - - {tokenTo.token.symbol} - - - - {shortenAddress(tokenTo.token.address)} - - - - - )} - - {tokenSecurity?.isSupported && ( -
- - Honeypot detection powered by GoPlus - - + +
+ {token0 && token0NotInList ? ( +
+ +
- )} - - ) : ( - <> - - ) : ( + {!honeypot && + ((token0NotInList && tokenFrom?.token) || + (token1NotInList && tokenTo?.token)) ? ( + + ) : ( +
- ) - ) : ( - + + Sushi does not support honetpot tokens. This token contract + cannot be imported! + +
)} diff --git a/apps/evm/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx b/apps/evm/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx index a7b2ca5060..6e3a01734b 100644 --- a/apps/evm/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx +++ b/apps/evm/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx @@ -94,7 +94,7 @@ const DerivedstateSimpleSwapProvider: FC = // This handles the case where some params might not be provided by the user const defaultedParams = useMemo(() => { const params = new URLSearchParams(searchParams) - if (!params.has('chainId')) + if (!params.has('chainId') || !params.get('chainId')) params.set( 'chainId', (isSupportedChainId(_chainId) diff --git a/apps/evm/src/ui/swap/simple/simple-swap-header.tsx b/apps/evm/src/ui/swap/simple/simple-swap-header.tsx index 4ebe23bf05..c5519cec74 100644 --- a/apps/evm/src/ui/swap/simple/simple-swap-header.tsx +++ b/apps/evm/src/ui/swap/simple/simple-swap-header.tsx @@ -4,7 +4,7 @@ import { ArrowTrendingUpIcon } from '@heroicons/react/20/solid' import { usePrices } from '@sushiswap/react-query' import { Button, - FormattedPrice, + FormattedNumber, SkeletonText, typographyVariants, } from '@sushiswap/ui' @@ -75,7 +75,7 @@ export const SimpleSwapHeader = () => { ({formatUSD(invert ? token0FiatPrice : token1FiatPrice)}) {' '} = - {' '} + {' '} {invert ? token1.symbol : token0.symbol}{' '} ({formatUSD(invert ? token1FiatPrice : token0FiatPrice)}) diff --git a/apps/evm/src/ui/swap/simple/simple-swap-token-not-found-dialog.tsx b/apps/evm/src/ui/swap/simple/simple-swap-token-not-found-dialog.tsx index 1483af5f77..427d21322f 100644 --- a/apps/evm/src/ui/swap/simple/simple-swap-token-not-found-dialog.tsx +++ b/apps/evm/src/ui/swap/simple/simple-swap-token-not-found-dialog.tsx @@ -10,13 +10,13 @@ import { DialogFooter, DialogHeader, DialogTitle, - GoPlusLabsIcon, List, + Message, } from '@sushiswap/ui' -import { useTokenWithCache } from '@sushiswap/wagmi' +import { TokenSecurityView, useTokenWithCache } from '@sushiswap/wagmi' import React, { useCallback, useMemo } from 'react' import { Chain } from 'sushi/chain' -import { defaultQuoteCurrency } from 'sushi/config' +import { defaultQuoteCurrency, isTokenSecurityChainId } from 'sushi/config' import { Native, Token } from 'sushi/currency' import { shortenAddress } from 'sushi/format' @@ -57,7 +57,7 @@ export const SimpleSwapTokenNotFoundDialog = () => { const onImport = useCallback( ([token0, token1]: (Token | undefined)[]) => { - const _tokens = [] + const _tokens: Token[] = [] if (tokenFrom?.status !== 'APPROVED' && token0) _tokens.push(token0) if (tokenTo?.status !== 'APPROVED' && token1) _tokens.push(token1) @@ -82,7 +82,10 @@ export const SimpleSwapTokenNotFoundDialog = () => { ) }, [chainId, setTokens]) - const { data: tokenSecurity } = useTokenSecurity({ + const { + data: tokenSecurityResponse, + isInitialLoading: tokenSecurityLoading, + } = useTokenSecurity({ currencies: useMemo( () => [ ...(token0NotInList && tokenFrom?.token ? [tokenFrom.token] : []), @@ -97,13 +100,14 @@ export const SimpleSwapTokenNotFoundDialog = () => { ), }) - const isNotHoneyPot = Boolean( - !tokenFromLoading && - !tokenToLoading && - (token0NotInList || token1NotInList), + const honeypot = Boolean( + (tokenFrom?.token && + tokenSecurityResponse?.[tokenFrom?.token?.address]?.is_honeypot) || + (tokenTo?.token && + tokenSecurityResponse?.[tokenTo?.token?.address]?.is_honeypot), ) - if (!tokenSecurity) return null + if (isTokenSecurityChainId(chainId) && tokenSecurityLoading) return null return ( { !tokenToLoading && (token0NotInList || token1NotInList), )} + onOpenChange={(open) => !open && reset()} > - + - {isNotHoneyPot ? ( - <> - - Unknown token{tokenFrom?.token && tokenTo?.token ? 's' : ''} - - - Anyone can create a token, including creating fake versions of - existing tokens that claim to represent projects. If you - purchase this token, you may not be able to sell it back. - - - ) : ( - <> - - Honeypot token{tokenSecurity.honeypots.length > 1 ? 's' : ''}{' '} - detected - - - {tokenSecurity.honeypots.length > 1 - ? 'These tokens have been identified as potential honeypot scams and are not supported. Do not interact with these tokens to safeguard your assets.' - : 'This token has been identified as a potential honeypot scam and is not supported. Do not interact with this token to safeguard your assets.'}{' '} - Click{' '} - - here - {' '} - to learn more about honepot scams. - - - )} + + Unknown token + {(token0NotInList || !tokenFrom?.token) && + (token1NotInList || !tokenTo?.token) + ? 's' + : ''} + + + Anyone can create a token, including creating fake versions of + existing tokens that claim to represent projects. If you purchase + this token, you may not be able to sell it back. +
- {isNotHoneyPot ? ( - <> - {token0 && token0NotInList && !tokenFrom?.token && ( - - - Token {tokenFrom?.token && tokenTo?.token ? '1' : ''} - - -

- Could not retrieve token info for{' '} - - {shortenAddress(token0.wrapped.address)} - {' '} - are you sure this token is on {Chain.from(chainId)?.name}? -

-
-
- )} - {token1 && token1NotInList && !tokenTo?.token && ( - - - Token {tokenFrom?.token && tokenTo?.token ? '2' : ''} - - -

- Could not retrieve token info for{' '} - - {shortenAddress(token1.wrapped.address)} - {' '} - are you sure this token is on {Chain.from(chainId)?.name}? -

-
-
- )} - {token0NotInList && tokenFrom?.token && ( - - - Token {tokenFrom.token && tokenTo?.token ? '1' : ''} - - - - {tokenFrom.token.name} - - - {tokenFrom.token.symbol} - - - - {shortenAddress(tokenFrom.token.address)} - - - - - )} - {token1NotInList && tokenTo?.token && ( - - - Token {tokenFrom?.token && tokenTo?.token ? '2' : ''} - - - - {tokenTo.token.name} - - - {tokenTo.token.symbol} - - - - {shortenAddress(tokenTo.token.address)} - - - - - )} - - {tokenSecurity?.isSupported && ( -
- - Honeypot detection powered by GoPlus - - -
- )} - - ) : ( - <> -
- {isNotHoneyPot ? ( - (token0NotInList && tokenFrom?.token) || - (token1NotInList && tokenTo?.token) ? ( - - ) : ( + {!honeypot && + ((token0NotInList && tokenFrom?.token) || + (token1NotInList && tokenTo?.token)) ? ( + + ) : ( +
- ) - ) : ( - + + Sushi does not support honetpot tokens. This token contract + cannot be imported! + +
)}
diff --git a/config/graph/src/index.ts b/config/graph/src/index.ts index 0871d0cefe..aab7a325dd 100644 --- a/config/graph/src/index.ts +++ b/config/graph/src/index.ts @@ -343,7 +343,7 @@ export const SUSHISWAP_SUBGRAPH_URL: Record = { export const SUSHISWAP_V3_SUBGRAPH_URL: Record = { [ChainId.ARBITRUM_NOVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-arbitrum-nova/gn`, - [ChainId.ARBITRUM]: `${GRAPH_HOST}/sushi-v3/v3-arbitrum`, + [ChainId.ARBITRUM]: `${STUDIO_HOST}/v3-arbitrum/v0.0.1`, [ChainId.AVALANCHE]: `${GRAPH_HOST}/sushi-v3/v3-avalanche`, [ChainId.BSC]: `${GRAPH_HOST}/sushi-v3/v3-bsc`, [ChainId.BOBA]: `${GRAPH_HOST}/sushi-v3/v3-boba`, diff --git a/flake.lock b/flake.lock index 4006f34939..89f23ddbe0 100644 --- a/flake.lock +++ b/flake.lock @@ -18,34 +18,16 @@ "type": "github" } }, - "flake-utils_10": { - "inputs": { - "systems": "systems_7" - }, - "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_11": { + "flake-utils_2": { "inputs": { - "systems": "systems_8" + "systems": "systems_2" }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -54,7 +36,7 @@ "type": "github" } }, - "flake-utils_12": { + "flake-utils_3": { "locked": { "lastModified": 1644229661, "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", @@ -69,45 +51,9 @@ "type": "github" } }, - "flake-utils_13": { - "inputs": { - "systems": "systems_9" - }, - "locked": { - "lastModified": 1687171271, - "narHash": "sha256-BJlq+ozK2B1sJDQXS3tzJM5a+oVZmi1q0FlBK/Xqv7M=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "abfb11bd1aec8ced1c9bb9adfe68018230f4fb3c", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_14": { - "inputs": { - "systems": "systems_10" - }, - "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_15": { + "flake-utils_4": { "inputs": { - "systems": "systems_11" + "systems": "systems_3" }, "locked": { "lastModified": 1705309234, @@ -123,9 +69,9 @@ "type": "github" } }, - "flake-utils_16": { + "flake-utils_5": { "inputs": { - "systems": "systems_12" + "systems": "systems_4" }, "locked": { "lastModified": 1705309234, @@ -141,954 +87,190 @@ "type": "github" } }, - "flake-utils_17": { + "foundry": { "inputs": { - "systems": "systems_13" + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "lastModified": 1714727549, + "narHash": "sha256-CWXRTxxcgMfQubJugpeg3yVWIfm70MYTtgaKWKgD60U=", + "owner": "shazow", + "repo": "foundry.nix", + "rev": "47cf189ec395eda4b3e0623179d1075c8027ca97", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "shazow", + "ref": "monthly", + "repo": "foundry.nix", "type": "github" } }, - "flake-utils_18": { - "inputs": { - "systems": "systems_14" - }, + "nixpkgs": { "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "lastModified": 1666753130, + "narHash": "sha256-Wff1dGPFSneXJLI2c0kkdWTgxnQ416KE6X4KnFkgPYQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f540aeda6f677354f1e7144ab04352f61aaa0118", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" + "id": "nixpkgs", + "type": "indirect" } }, - "flake-utils_19": { - "inputs": { - "systems": "systems_15" - }, + "nixpkgs_2": { "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "lastModified": 1714764285, + "narHash": "sha256-oeevp27kMeDjKdxaTyXyS14TLjJrpJhXp7UVEUdYqYs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d121ce778b2609ae9e749a711295ffca013a82c4", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nixos", + "repo": "nixpkgs", "type": "github" } }, - "flake-utils_2": { - "inputs": { - "systems": "systems_2" - }, + "nixpkgs_3": { "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "lastModified": 1706487304, + "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", "type": "github" } }, - "flake-utils_3": { + "nixpkgs_4": { "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1708564076, + "narHash": "sha256-KKkqoxlgx9n3nwST7O2kM8tliDOijiSSNaWuSkiozdQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "98b00b6947a9214381112bdb6f89c25498db4959", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", "type": "github" } }, - "flake-utils_4": { + "rainix": { "inputs": { - "systems": "systems_3" + "flake-utils": "flake-utils_2", + "foundry": "foundry", + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay", + "solc": "solc" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "lastModified": 1714764843, + "narHash": "sha256-7ae0pHvjlInc1V3QxjW5iNhXAYerO1/fhLgzQnPNPjE=", + "owner": "rainprotocol", + "repo": "rainix", + "rev": "f3bdb28f353f8cba28b2bba86f79c362dd65ee53", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "rainprotocol", + "repo": "rainix", "type": "github" } }, - "flake-utils_5": { + "root": { "inputs": { - "systems": "systems_4" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" + "flake-utils": "flake-utils", + "rainix": "rainix" } }, - "flake-utils_6": { + "rust-overlay": { + "inputs": { + "flake-utils": "flake-utils_4", + "nixpkgs": "nixpkgs_3" + }, "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1714702555, + "narHash": "sha256-/NoUbE5S5xpK1FU3nlHhQ/tL126+JcisXdzy3Ng4pDU=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "7f0e3ef7b7fbed78e12e5100851175d28af4b7c6", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "oxalica", + "repo": "rust-overlay", "type": "github" } }, - "flake-utils_7": { + "solc": { "inputs": { - "systems": "systems_5" + "flake-utils": "flake-utils_5", + "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "lastModified": 1711538161, + "narHash": "sha256-rETVdEIQ2PyEcNgzXXFSiYAYl0koCeGDIWp9XYBTxoQ=", + "owner": "hellwolf", + "repo": "solc.nix", + "rev": "a995838545a7383a0b37776e969743b1346d5479", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hellwolf", + "repo": "solc.nix", "type": "github" } }, - "flake-utils_8": { - "inputs": { - "systems": "systems_6" - }, + "systems": { "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, - "flake-utils_9": { + "systems_2": { "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, - "foundry": { - "inputs": { - "flake-utils": "flake-utils_3", - "nixpkgs": "nixpkgs" - }, + "systems_3": { "locked": { - "lastModified": 1712135466, - "narHash": "sha256-+xFfYk17EI0zZTGmhh3MyeSpl7RVohoVp/4HaSvGj4I=", - "owner": "shazow", - "repo": "foundry.nix", - "rev": "ece7c960a440c6725a7a5576d1f49a5fabde3747", - "type": "github" - }, - "original": { - "owner": "shazow", - "ref": "monthly", - "repo": "foundry.nix", - "type": "github" - } - }, - "foundry_2": { - "inputs": { - "flake-utils": "flake-utils_6", - "nixpkgs": "nixpkgs_3" - }, - "locked": { - "lastModified": 1709457044, - "narHash": "sha256-1SktmSjTjC1rhJwQ+kvqUeExKogNzserFGuoGwOerHw=", - "owner": "shazow", - "repo": "foundry.nix", - "rev": "592e8ca2e82a2c3a8d0d4dcc7f7c5b8c3842efcd", - "type": "github" - }, - "original": { - "owner": "shazow", - "ref": "monthly", - "repo": "foundry.nix", - "type": "github" - } - }, - "foundry_3": { - "inputs": { - "flake-utils": "flake-utils_9", - "nixpkgs": "nixpkgs_5" - }, - "locked": { - "lastModified": 1705216422, - "narHash": "sha256-kIAi+aqJoOVhpQP5DWRDdNsrfBMn+GsCwiuwJhG4w/g=", - "owner": "shazow", - "repo": "foundry.nix", - "rev": "9ecf12199280f738eaaad2d1224e54403dbdf426", - "type": "github" - }, - "original": { - "owner": "shazow", - "repo": "foundry.nix", - "rev": "9ecf12199280f738eaaad2d1224e54403dbdf426", - "type": "github" - } - }, - "foundry_4": { - "inputs": { - "flake-utils": "flake-utils_12", - "nixpkgs": "nixpkgs_7" - }, - "locked": { - "lastModified": 1705216422, - "narHash": "sha256-kIAi+aqJoOVhpQP5DWRDdNsrfBMn+GsCwiuwJhG4w/g=", - "owner": "shazow", - "repo": "foundry.nix", - "rev": "9ecf12199280f738eaaad2d1224e54403dbdf426", - "type": "github" - }, - "original": { - "owner": "shazow", - "repo": "foundry.nix", - "rev": "9ecf12199280f738eaaad2d1224e54403dbdf426", - "type": "github" - } - }, - "naersk": { - "inputs": { - "nixpkgs": "nixpkgs_9" - }, - "locked": { - "lastModified": 1686572087, - "narHash": "sha256-jXTut7ZSYqLEgm/nTk7TuVL2ExahTip605bLINklAnQ=", - "owner": "nix-community", - "repo": "naersk", - "rev": "8507af04eb40c5520bd35d9ce6f9d2342cea5ad1", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "naersk", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1666753130, - "narHash": "sha256-Wff1dGPFSneXJLI2c0kkdWTgxnQ416KE6X4KnFkgPYQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "f540aeda6f677354f1e7144ab04352f61aaa0118", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs_10": { - "locked": { - "lastModified": 1687518131, - "narHash": "sha256-KirltRIc4SFfk8bTNudIqgKAALH5oqpW3PefmkfWK5M=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "3d8a93602bc54ece7a4e689d9aea1a574e2bbc24", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_11": { - "locked": { - "lastModified": 1681358109, - "narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_12": { - "locked": { - "lastModified": 1706487304, - "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_13": { - "locked": { - "lastModified": 1706487304, - "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_14": { - "locked": { - "lastModified": 1708564076, - "narHash": "sha256-KKkqoxlgx9n3nwST7O2kM8tliDOijiSSNaWuSkiozdQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "98b00b6947a9214381112bdb6f89c25498db4959", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_15": { - "locked": { - "lastModified": 1706487304, - "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_16": { - "locked": { - "lastModified": 1708564076, - "narHash": "sha256-KKkqoxlgx9n3nwST7O2kM8tliDOijiSSNaWuSkiozdQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "98b00b6947a9214381112bdb6f89c25498db4959", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1712609864, - "narHash": "sha256-c0U5x9ucCKHZHqaJIy4eB0FTFNWbLLF9PyNsVDDj75w=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "902522b1a069597be55bc1547fadaaeb62111019", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixpkgs", - "rev": "902522b1a069597be55bc1547fadaaeb62111019", - "type": "github" - } - }, - "nixpkgs_3": { - "locked": { - "lastModified": 1666753130, - "narHash": "sha256-Wff1dGPFSneXJLI2c0kkdWTgxnQ416KE6X4KnFkgPYQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "f540aeda6f677354f1e7144ab04352f61aaa0118", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs_4": { - "locked": { - "lastModified": 1712609864, - "narHash": "sha256-c0U5x9ucCKHZHqaJIy4eB0FTFNWbLLF9PyNsVDDj75w=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "902522b1a069597be55bc1547fadaaeb62111019", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixpkgs", - "rev": "902522b1a069597be55bc1547fadaaeb62111019", - "type": "github" - } - }, - "nixpkgs_5": { - "locked": { - "lastModified": 1666753130, - "narHash": "sha256-Wff1dGPFSneXJLI2c0kkdWTgxnQ416KE6X4KnFkgPYQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "f540aeda6f677354f1e7144ab04352f61aaa0118", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs_6": { - "locked": { - "lastModified": 1706634492, - "narHash": "sha256-9wg1OQET7oCzzMsktGufJmfr2ylecL8T8YYqQo+qNSc=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "dad88c029e2644adfde882f73e9338fd39058a3f", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixpkgs", - "rev": "dad88c029e2644adfde882f73e9338fd39058a3f", - "type": "github" - } - }, - "nixpkgs_7": { - "locked": { - "lastModified": 1666753130, - "narHash": "sha256-Wff1dGPFSneXJLI2c0kkdWTgxnQ416KE6X4KnFkgPYQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "f540aeda6f677354f1e7144ab04352f61aaa0118", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs_8": { - "locked": { - "lastModified": 1706634492, - "narHash": "sha256-9wg1OQET7oCzzMsktGufJmfr2ylecL8T8YYqQo+qNSc=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "dad88c029e2644adfde882f73e9338fd39058a3f", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixpkgs", - "rev": "dad88c029e2644adfde882f73e9338fd39058a3f", - "type": "github" - } - }, - "nixpkgs_9": { - "locked": { - "lastModified": 1687518131, - "narHash": "sha256-KirltRIc4SFfk8bTNudIqgKAALH5oqpW3PefmkfWK5M=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "3d8a93602bc54ece7a4e689d9aea1a574e2bbc24", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "rain": { - "inputs": { - "flake-utils": "flake-utils_4", - "rainix": "rainix_2" - }, - "locked": { - "lastModified": 1713982615, - "narHash": "sha256-LEmo3vlyIOr3W7J9sl1iXpBBWcys4D+MVG3NJRfZj+c=", - "owner": "rainlanguage", - "repo": "rain.cli", - "rev": "63c9af98671604a54c7e319ff9b3f2978a57d5b8", - "type": "github" - }, - "original": { - "owner": "rainlanguage", - "repo": "rain.cli", - "type": "github" - } - }, - "rain_2": { - "inputs": { - "flake-utils": "flake-utils_7", - "rainix": "rainix_3" - }, - "locked": { - "lastModified": 1709330445, - "narHash": "sha256-fNBo/pmPOkTbkKZRFnxR6QBQEk1QSL13iIdfPQN6jpg=", - "owner": "rainlanguage", - "repo": "rain.cli", - "rev": "0f882121f9f26208c1ae062c368ee817b2ca1363", - "type": "github" - }, - "original": { - "owner": "rainlanguage", - "repo": "rain.cli", - "type": "github" - } - }, - "rain_3": { - "inputs": { - "flake-utils": "flake-utils_10", - "rainix": "rainix_4" - }, - "locked": { - "lastModified": 1706637129, - "narHash": "sha256-dMyuaMux2bVChGb0DA1lyYw+SxyEz41CshmZsqGZwqM=", - "owner": "rainlanguage", - "repo": "rain.cli", - "rev": "da5bb3446ea008cf9537c537ad30d4ef16f5d36f", - "type": "github" - }, - "original": { - "owner": "rainlanguage", - "repo": "rain.cli", - "type": "github" - } - }, - "rain_4": { - "inputs": { - "flake-utils": "flake-utils_13", - "naersk": "naersk", - "nixpkgs": "nixpkgs_10" - }, - "locked": { - "lastModified": 1700476138, - "narHash": "sha256-cpKb/QMQQgoV4xiEI/TSEW48v/8MxvGA9Q9BK75DnH4=", - "owner": "rainprotocol", - "repo": "rain.cli", - "rev": "6a912680be6d967fd6114aafab793ebe8503d27b", - "type": "github" - }, - "original": { - "owner": "rainprotocol", - "repo": "rain.cli", - "type": "github" - } - }, - "rainix": { - "inputs": { - "flake-utils": "flake-utils_2", - "foundry": "foundry", - "nixpkgs": "nixpkgs_2", - "rain": "rain", - "rust-overlay": "rust-overlay_4", - "solc": "solc_2" - }, - "locked": { - "lastModified": 1714161679, - "narHash": "sha256-9My5dH9pJoQMS4mkyk0cgu3FV64DkoHJOOHugGTDVgc=", - "owner": "rainprotocol", - "repo": "rainix", - "rev": "38bdeda14882f6af40170be2079cd0286ba17bb7", - "type": "github" - }, - "original": { - "owner": "rainprotocol", - "repo": "rainix", - "type": "github" - } - }, - "rainix_2": { - "inputs": { - "flake-utils": "flake-utils_5", - "foundry": "foundry_2", - "nixpkgs": "nixpkgs_4", - "rain": "rain_2", - "rust-overlay": "rust-overlay_3", - "solc": "solc" - }, - "locked": { - "lastModified": 1713900533, - "narHash": "sha256-8FUM4l4Quwnl+uwGwsH68MwbPMKwVXoerEcGx7sgK5U=", - "owner": "rainprotocol", - "repo": "rainix", - "rev": "6097a125b4ab515e650a6f35d6018744c4ac3bc4", - "type": "github" - }, - "original": { - "owner": "rainprotocol", - "repo": "rainix", - "rev": "6097a125b4ab515e650a6f35d6018744c4ac3bc4", - "type": "github" - } - }, - "rainix_3": { - "inputs": { - "flake-utils": "flake-utils_8", - "foundry": "foundry_3", - "nixpkgs": "nixpkgs_6", - "rain": "rain_3", - "rust-overlay": "rust-overlay_2" - }, - "locked": { - "lastModified": 1707160817, - "narHash": "sha256-ZLJ3/YlQqnrsFFc4BdO3d4QulAPnUjZYs9cJ+9+6FBo=", - "owner": "rainprotocol", - "repo": "rainix", - "rev": "10cbcbe44d597b6e4618af28fb7977a79e241342", - "type": "github" - }, - "original": { - "owner": "rainprotocol", - "repo": "rainix", - "type": "github" - } - }, - "rainix_4": { - "inputs": { - "flake-utils": "flake-utils_11", - "foundry": "foundry_4", - "nixpkgs": "nixpkgs_8", - "rain": "rain_4", - "rust-overlay": "rust-overlay" - }, - "locked": { - "lastModified": 1706636911, - "narHash": "sha256-jcplLR2rPxwnNNPnBgHeFkCSsaPu5uwaBl5zLnpJVWo=", - "owner": "rainprotocol", - "repo": "rainix", - "rev": "f68a83772f51d5230b61919322a2ffd6092b1107", - "type": "github" - }, - "original": { - "owner": "rainprotocol", - "repo": "rainix", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "rainix": "rainix" - } - }, - "rust-overlay": { - "inputs": { - "flake-utils": "flake-utils_14", - "nixpkgs": "nixpkgs_11" - }, - "locked": { - "lastModified": 1706580650, - "narHash": "sha256-e6q4Pn1dp3NoQJdMYdyNdDHU5IRBW9i3bHSJ3jThEL0=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "39e20b3c02caa91c9970beef325a04975d83d77f", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "rust-overlay_2": { - "inputs": { - "flake-utils": "flake-utils_15", - "nixpkgs": "nixpkgs_12" - }, - "locked": { - "lastModified": 1706634984, - "narHash": "sha256-xn7lGPE8gRGBe3Lt8ESoN/uUHm7IrbiV7siupwjHX1o=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "883b84c426107a8ec020e7124f263d7c35a5bb9f", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "rust-overlay_3": { - "inputs": { - "flake-utils": "flake-utils_16", - "nixpkgs": "nixpkgs_13" - }, - "locked": { - "lastModified": 1711851236, - "narHash": "sha256-EJ03x3N9ihhonAttkaCrqxb0djDq3URCuDpmVPbNZhA=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "f258266af947599e8069df1c2e933189270f143a", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "rust-overlay_4": { - "inputs": { - "flake-utils": "flake-utils_18", - "nixpkgs": "nixpkgs_15" - }, - "locked": { - "lastModified": 1713924823, - "narHash": "sha256-kOeyS3GFwgnKvzuBMmFqEAX0xwZ7Nj4/5tXuvpZ0d4U=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "8a2edac3ae926a2a6ce60f4595dcc4540fc8cad4", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "solc": { - "inputs": { - "flake-utils": "flake-utils_17", - "nixpkgs": "nixpkgs_14" - }, - "locked": { - "lastModified": 1711538161, - "narHash": "sha256-rETVdEIQ2PyEcNgzXXFSiYAYl0koCeGDIWp9XYBTxoQ=", - "owner": "hellwolf", - "repo": "solc.nix", - "rev": "a995838545a7383a0b37776e969743b1346d5479", - "type": "github" - }, - "original": { - "owner": "hellwolf", - "repo": "solc.nix", - "type": "github" - } - }, - "solc_2": { - "inputs": { - "flake-utils": "flake-utils_19", - "nixpkgs": "nixpkgs_16" - }, - "locked": { - "lastModified": 1711538161, - "narHash": "sha256-rETVdEIQ2PyEcNgzXXFSiYAYl0koCeGDIWp9XYBTxoQ=", - "owner": "hellwolf", - "repo": "solc.nix", - "rev": "a995838545a7383a0b37776e969743b1346d5479", - "type": "github" - }, - "original": { - "owner": "hellwolf", - "repo": "solc.nix", - "type": "github" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_10": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_11": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_12": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_13": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_14": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_15": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_3": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { @@ -1111,81 +293,6 @@ "repo": "default", "type": "github" } - }, - "systems_5": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_6": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_7": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_8": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_9": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/packages/graph-client/package.json b/packages/graph-client/package.json index af55f31cf9..7a34af28b2 100644 --- a/packages/graph-client/package.json +++ b/packages/graph-client/package.json @@ -60,7 +60,6 @@ "@sushiswap/typescript-config": "workspace:*", "@types/jest": "29.5.5", "@types/node": "20", - "@types/numeral": "2.0.2", "@wagmi/core": "2.6.17", "graphql": "16.6.0", "jest": "29.7.0", diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index 9a50aec626..91fdaf0de2 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -16,4 +16,5 @@ export * from './useOnClickOutside' export * from './usePinnedTokens' export * from './usePrevious' export * from './useSlippageTolerance' +export * from './useTTL' export * from './useWindowSize' diff --git a/packages/hooks/src/useSlippageTolerance.ts b/packages/hooks/src/useSlippageTolerance.ts index 5772a39fd9..108cf9a0f0 100644 --- a/packages/hooks/src/useSlippageTolerance.ts +++ b/packages/hooks/src/useSlippageTolerance.ts @@ -2,5 +2,15 @@ import { useLocalStorage } from './useLocalStorage' -export const useSlippageTolerance = (key?: string, defaultValue?: string) => - useLocalStorage(key || 'swapSlippage', defaultValue || '0.1') +export enum SlippageToleranceStorageKey { + Swap = 'slippage-swap', + AddLiquidity = 'slippage-add-liquidity', + RemoveLiquidity = 'slippage-remove-liquidity', + AddSteerLiquidity = 'slippage-add-steer-liquidity', + RemoveSteerLiquidity = 'slippage-remove-steer-liquidity', +} + +export const useSlippageTolerance = ( + key: SlippageToleranceStorageKey = SlippageToleranceStorageKey.Swap, + defaultValue?: string, +) => useLocalStorage(key, defaultValue || '0.1') diff --git a/packages/hooks/src/useTTL.ts b/packages/hooks/src/useTTL.ts new file mode 100644 index 0000000000..4072f9ae7b --- /dev/null +++ b/packages/hooks/src/useTTL.ts @@ -0,0 +1,10 @@ +import { useLocalStorage } from './useLocalStorage' + +export enum TTLStorageKey { + AddLiquidity = 'ttl-add-liquidity', + RemoveLiquidity = 'ttl-remove-liquidity', +} + +export const useTTL = (key: TTLStorageKey) => { + return useLocalStorage(key, 0) +} diff --git a/packages/react-query/package.json b/packages/react-query/package.json index 3e8c861f93..2235894d7a 100644 --- a/packages/react-query/package.json +++ b/packages/react-query/package.json @@ -43,8 +43,6 @@ "test": "jest --passWithNoTests" }, "dependencies": { - "@sushiswap/client": "workspace:*", - "@sushiswap/database": "workspace:*", "@sushiswap/dexie": "workspace:*", "@sushiswap/hooks": "workspace:*", "@tanstack/react-query": "4.28.0", @@ -56,6 +54,8 @@ }, "devDependencies": { "@sentry/nextjs": "7.101.1", + "@sushiswap/client": "workspace:*", + "@sushiswap/database": "workspace:*", "@sushiswap/jest-config": "workspace:*", "@tsconfig/esm": "1.0.4", "@tsconfig/strictest": "2.0.2", @@ -73,6 +73,7 @@ }, "peerDependencies": { "@sentry/nextjs": "7.101.1", + "@sushiswap/client": "*", "next": "14.1.0", "react": "18.2.0", "react-dom": "18.2.0", @@ -81,6 +82,9 @@ "wagmi": "2.5.20" }, "peerDependenciesMeta": { + "@sushiswap/client": { + "optional": true + }, "react": { "optional": false }, diff --git a/packages/react-query/src/hooks/tokens/useTokenSecurity.ts b/packages/react-query/src/hooks/tokens/useTokenSecurity.ts index 3eec562725..3075c85011 100644 --- a/packages/react-query/src/hooks/tokens/useTokenSecurity.ts +++ b/packages/react-query/src/hooks/tokens/useTokenSecurity.ts @@ -1,35 +1,142 @@ -import { useQuery } from '@tanstack/react-query' -import { ChainId } from 'sushi/chain' +import { type UseQueryOptions, useQuery } from '@tanstack/react-query' +import { isTokenSecurityChainId } from 'sushi/config' import { Token } from 'sushi/currency' +import { z } from 'zod' -const SUPPORTED_CHAINS: ChainId[] = [ - ChainId.AVALANCHE, - ChainId.FANTOM, - ChainId.GNOSIS, - ChainId.HARMONY, - ChainId.ETHEREUM, - ChainId.HECO, - ChainId.ARBITRUM, - ChainId.OPTIMISM, -] +const bit = z.optional(z.enum(['0', '1']).transform((val) => val !== '0')) -interface TokenSecurity { - buy_tax: string - sell_tax: string - cannot_buy: string - cannot_sell_all: string - slippage_modifiable: string - is_honeypot: string - transfer_pausable: string - is_blacklisted: string - is_whitelisted: string +const tokenSecuritySchema = z + .object({ + is_open_source: bit, + is_proxy: bit, + is_mintable: bit, + can_take_back_ownership: bit, + owner_change_balance: bit, + hidden_owner: bit, + selfdestruct: bit, + external_call: bit, + gas_abuse: bit, + buy_tax: z.optional( + z.preprocess( + (val) => (val === '' ? undefined : val !== '0'), + z.optional(z.boolean()), + ), + ), + sell_tax: z.optional( + z.preprocess( + (val) => (val === '' ? undefined : val !== '0'), + z.optional(z.boolean()), + ), + ), + cannot_buy: bit, + cannot_sell_all: bit, + slippage_modifiable: bit, + is_honeypot: bit, + transfer_pausable: bit, + is_blacklisted: bit, + is_whitelisted: bit, + is_anti_whale: bit, + trading_cooldown: bit, + is_true_token: bit, + is_airdrop_scam: bit, + trust_list: bit, + }) + .transform(({ cannot_buy, is_true_token, cannot_sell_all, ...data }) => ({ + ...data, + is_buyable: typeof cannot_buy !== 'undefined' ? !cannot_buy : undefined, + is_fake_token: + typeof is_true_token !== 'undefined' ? !is_true_token : undefined, + is_sell_limit: cannot_sell_all, + })) + +export type TokenSecurity = z.infer + +export type TokenSecurityResponse = Record + +type GoPlusAPIResponse = Record> + +export const TokenSecurityLabel: Record = { + is_open_source: 'Contract Verified', + is_proxy: 'Proxy Contract', + is_mintable: 'Mintable', + can_take_back_ownership: 'Reclaimable Ownership', + owner_change_balance: 'Balance Modifiable', + hidden_owner: 'Hidden Owner', + selfdestruct: 'Includes selfdestruct()', + external_call: 'Includes External Call', + gas_abuse: 'Abuses Gas', + buy_tax: 'Buy Tax', + sell_tax: 'Sell Tax', + is_buyable: 'Buyable', + is_sell_limit: 'Sell Limit', + slippage_modifiable: 'Slippage Modifiable', + is_honeypot: 'Honeypot', + transfer_pausable: 'Transfer Pausable', + is_blacklisted: 'Includes Blacklist', + is_whitelisted: 'Includes Whitelist', + is_anti_whale: 'Anti-whale Mechanism', + trading_cooldown: 'Trading Cooldown', + is_fake_token: 'Fake Token', + is_airdrop_scam: 'Airdrop Scam', + trust_list: 'Trusted', +} + +export const TokenSecurityMessage: Record = { + //Contract Security + is_open_source: + 'Whether or not this token contract is open source. You can check the contract code for details. Unsourced token contracts are likely to have malicious functions to defraud their users of their assets.', + is_proxy: + 'Whether or not there is a proxy in the contract. The proxy contract means contract owner can modifiy the function of the token and possibly effect the price.', + is_mintable: + 'Whether or not this contract contains a visible mint function. Hidden mint functions may increase the amount of tokens in circulation and effect the price of the token.', + can_take_back_ownership: + 'Whether or not this contract contains a function that allows the project owner to regain ownership even after relinquishing it.', + owner_change_balance: + 'Whether or not the contract owner is found to have the authority to modify the balance of tokens at other addresses.', + hidden_owner: + 'Whether or not a hidden owner address was found for the token. For contract with a hidden owner, developer can still manipulate the contract even if the ownership has been abandoned.', + selfdestruct: + 'If a self-destruct function exists and is triggered, the contract will be destroyed, all functions will be unavailable, and all related assets will be erased.', + external_call: + 'External calls would cause this token contract to be highly dependent on other contracts, which may be a potential risk.', + gas_abuse: + 'Indicates whether any gas abuse activity has been detected in this contract.', + //Trading security + buy_tax: + 'Whether or not this token contract includes a buy tax. A buy tax will cause the actual token value received to be less than the amount paid. An excessive buy tax may lead to heavy losses.', + sell_tax: + 'Whether or not this token contract includes a sell tax. A sell tax will cause the actual value received when selling a token to be less than expected, and too much sell tax may lead to large losses.', + is_buyable: + 'Whether or not this token can be purchased directly by users. Generally, these unbuyable tokens would be found in Reward Tokens. Such tokens are issued as rewards for some on-chain applications.', + is_sell_limit: + 'Whether or not a user can sell all of their tokens in a single sale.', + slippage_modifiable: + 'Whether or not the contract owner can modify the buy tax or sell tax of the token. This may cause some losses, especially since some contracts have unlimited modifiable tax rates, which would make the token untradeable.', + is_honeypot: + "Whether or not the token is a honeypot, meaning that the token maybe cannot be sold because of the token contract's function, or the token contains malicious code.", + transfer_pausable: + "Indicating the contract owner's ability to suspend trading, preventing users from selling, except for those with special authority.", + is_blacklisted: + 'Whether or not a blacklist function is included. If there is a blacklist, some addresses may not be able to trade normally (honeypot risk).', + is_whitelisted: + 'Whether or not a whitelist function is included. If there is a whitelist, some addresses may not be able to trade normally (honeypot risk).', + is_anti_whale: + 'Whether the contract has the function to limit the maximum amount of transactions or the maximum token position for a single address.', + trading_cooldown: + 'Whether the contract has a trading-cool-down mechanism that can limit the minimum time between two transactions.', + //Info security + is_fake_token: 'Whether or not this token is fake or real.', + is_airdrop_scam: 'Whether or not this token is an airdrop scam', + trust_list: 'Whether or not this token is a famous and trustworthy one.', } const fetchTokenSecurityQueryFn = async (currencies: (Token | undefined)[]) => { const supportedCurrencies = currencies.filter( - (currency) => currency && SUPPORTED_CHAINS.includes(currency.chainId), + (currency) => currency && isTokenSecurityChainId(currency.chainId), ) as Token[] + if (supportedCurrencies.length === 0) return {} as TokenSecurityResponse + const tokenSecurity = await Promise.all( supportedCurrencies.map((currency) => fetch( @@ -37,37 +144,27 @@ const fetchTokenSecurityQueryFn = async (currencies: (Token | undefined)[]) => { ) .then( (response) => - response.json() as Promise<{ - result?: Record - }>, + response.json() as Promise<{ result?: GoPlusAPIResponse }>, ) - .then((data) => data?.result?.[currency.address.toLowerCase()]), + .then((data) => data?.result?.[currency.address.toLowerCase()]) + .then((tokenSecurityResponse) => + tokenSecuritySchema.parse(tokenSecurityResponse), + ), ), ) - const honeypots = tokenSecurity.reduce((acc, cur, i) => { - const isHoneypot = cur?.is_honeypot === '1' - const supportedCurrencyAddress = supportedCurrencies?.[i]?.address - if (isHoneypot && typeof supportedCurrencyAddress === 'string') { - acc.push(supportedCurrencyAddress) - return acc - } - return acc - }, [] as string[]) - - return { - tokenSecurity, - honeypots, - isSupported: supportedCurrencies.length > 0, - } + return supportedCurrencies.reduce((prev, cur, i) => { + prev[cur.address] = tokenSecurity[i] as TokenSecurity + return prev + }, {} as TokenSecurityResponse) } export const useTokenSecurity = ({ currencies, enabled = true, -}: { + ...rest +}: UseQueryOptions>> & { currencies: (Token | undefined)[] - enabled?: boolean }) => { return useQuery({ queryKey: ['useTokenSecurity', currencies?.map((currency) => currency?.id)], @@ -76,5 +173,6 @@ export const useTokenSecurity = ({ keepPreviousData: true, staleTime: 900000, // 15 mins cacheTime: 86400000, // 24hs + ...rest, }) } diff --git a/packages/sushi/package.json b/packages/sushi/package.json index eb1fed84c2..13d5264f0d 100644 --- a/packages/sushi/package.json +++ b/packages/sushi/package.json @@ -203,7 +203,7 @@ "decimal.js-light": "2.5.1", "lodash.flatmap": "4.5.0", "memoize-fs": "github:rouzwelt/memoize-fs#e5fcc9f6effc4ad087514372a53a49d380520ad5", - "numeral": "2.0.6", + "numbro": "2.5.0", "seedrandom": "3.0.5", "serialijse": "0.3.0", "tiny-invariant": "1.3.1", @@ -217,7 +217,6 @@ "@tsconfig/strictest": "2.0.2", "@types/big.js": "6.2.0", "@types/lodash.flatmap": "4.5.9", - "@types/numeral": "2.0.3", "@types/seedrandom": "3.0.1", "@wagmi/core": "2.6.17", "ts-node": "10.9.2", diff --git a/packages/sushi/src/config/index.ts b/packages/sushi/src/config/index.ts index b54597f82e..f2cfb5d1df 100644 --- a/packages/sushi/src/config/index.ts +++ b/packages/sushi/src/config/index.ts @@ -17,6 +17,7 @@ export * from './stargate.js' export * from './sushiswap-v2.js' export * from './sushiswap-v3.js' export * from './sushixswap.js' +export * from './token-security.js' export * from './trident.js' export * from './uniswap-v2.js' export * from './uniswap-v3.js' diff --git a/packages/sushi/src/config/token-security.ts b/packages/sushi/src/config/token-security.ts new file mode 100644 index 0000000000..4bce5552b2 --- /dev/null +++ b/packages/sushi/src/config/token-security.ts @@ -0,0 +1,28 @@ +import { ChainId } from '../chain' + +const SUPPORTED_CHAIN_IDS = [ + ChainId.AVALANCHE, + ChainId.BSC, + ChainId.FANTOM, + ChainId.GNOSIS, + ChainId.HARMONY, + ChainId.ETHEREUM, + ChainId.HECO, + ChainId.ARBITRUM, + ChainId.OPTIMISM, + ChainId.ZKSYNC_ERA, + ChainId.LINEA, + ChainId.BASE, + ChainId.POLYGON, + ChainId.SCROLL, + ChainId.BLAST, +] as const + +export const TokenSecurityChainIds = SUPPORTED_CHAIN_IDS + +export type TokenSecurityChainId = (typeof SUPPORTED_CHAIN_IDS)[number] + +export const isTokenSecurityChainId = ( + chainId: ChainId, +): chainId is TokenSecurityChainId => + SUPPORTED_CHAIN_IDS.includes(chainId as TokenSecurityChainId) diff --git a/packages/sushi/src/format/number.ts b/packages/sushi/src/format/number.ts index d54ee469a0..6713155398 100644 --- a/packages/sushi/src/format/number.ts +++ b/packages/sushi/src/format/number.ts @@ -1,7 +1,19 @@ -import numeral from 'numeral' +import numeral from 'numbro' -export const formatNumber = (value: any) => { - return numeral(value).format('(0.00a)') +export const formatNumber = (value: any, inputString = '0.[00]a') => { + if (typeof value === 'string') value = Number(value) + + let negative = false + if (value < 0) { + negative = true + value = Math.abs(value) + } + + if (value === 0) return '0.00' + if (value < 0.0001) return numeral(value).format('0.[000000]a') + if (value < 0.001) return numeral(value).format('0.[0000]a') + if (value < 0.01) return numeral(value).format('0.[000]a') + return `${negative ? '-' : ''}${numeral(value).format(inputString)}` } /** diff --git a/packages/sushi/src/format/percent.ts b/packages/sushi/src/format/percent.ts index a396009bee..bdcf5b3385 100644 --- a/packages/sushi/src/format/percent.ts +++ b/packages/sushi/src/format/percent.ts @@ -1,4 +1,4 @@ -import numeral from 'numeral' +import numeral from 'numbro' export const formatPercent = (value: any) => { let negative = false diff --git a/packages/sushi/src/format/price.ts b/packages/sushi/src/format/price.ts index 4c611d97be..02d13ec1cb 100644 --- a/packages/sushi/src/format/price.ts +++ b/packages/sushi/src/format/price.ts @@ -1,4 +1,4 @@ -import numeral from 'numeral' +import numeral from 'numbro' export const formatUSD = ( value: string | number, diff --git a/packages/sushi/test/tines/snapshots/report b/packages/sushi/test/tines/snapshots/report index f8d28db60a..306557668b 100644 --- a/packages/sushi/test/tines/snapshots/report +++ b/packages/sushi/test/tines/snapshots/report @@ -1,42 +1,191 @@ 1:"bridge-1": 5528.94 -> 5528.94 (0%) avg:0% 2:"bridge-2": 7663 -> 7663 (0%) avg:0% -151:"top20-150": 0 -> 0 (0%) avg:0% -152:"top20-151": 481 -> 481 (0%) avg:0% 3:"bridge-3": 11953.94 -> 11953.94 (0%) avg:0% 4:"bridge-4": 5496.94 -> 5496.94 (0%) avg:0% 5:"bridge-5-1": 4260.964 -> 4260.964 (0%) avg:0% +2:"top20-1": 1.1195509365387262e+37 -> 1.1195509365387262e+37 (0%) avg:0% 6:"bridge-5-2": 5473.94 -> 5473.94 (0%) avg:0% 7:"bridge-5-3": 5501.94 -> 5501.94 (0%) avg:0% 8:"bridge-5-5": 5528.94 -> 5528.94 (0%) avg:0% 9:"bridge-5-10": 5528.94 -> 5528.94 (0%) avg:0% 10:"bridge-5-30": 5528.94 -> 5528.94 (0%) avg:0% 11:"bridge-5-100": 5528.94 -> 5528.94 (0%) avg:0% +3:"top20-2": 96249232830474440000 -> 96249232830474440000 (0%) avg:0% +4:"top20-3": 467011582838851800000 -> 467011582838851800000 (0%) avg:0% +5:"top20-4": 14263706377454.916 -> 14263706377454.916 (0%) avg:0% 12:"bridge-5-300": 5528.94 -> 5528.94 (0%) avg:0% -153:"top20-152": 0 -> 0 (0%) avg:0% -154:"top20-153": 1.3468577317796694e+32 -> 1.3468577317796694e+32 (0%) avg:0% +6:"top20-5": 111208992328025 -> 111208992328025 (0%) avg:0% +7:"top20-6": 184056193599 -> 184056193599 (0%) avg:0% 13:"bridge-5-1000": 5528.94 -> 5528.94 (0%) avg:0% -155:"top20-154": 7978807883992.964 -> 7978807883992.964 (0%) avg:0% +8:"top20-7": 1.949010266471403e+21 -> 1.949010266471403e+21 (0%) avg:0% 14:"bridge-6": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% -156:"top20-155": 75460.9999999988 -> 75460.9999999988 (0%) avg:0% 15:"bridge-7-1": 567.9947198349995 -> 567.9947198349995 (0%) avg:0% 16:"bridge-7-2": 567.9947198349995 -> 567.9947198349995 (0%) avg:0% 17:"bridge-7-3": 569.9929597799993 -> 569.9929597799993 (0%) avg:0% -157:"top20-156": 1433531033857000200 -> 1433531033857000200 (0%) avg:0% +9:"top20-8": 5147698251 -> 5147698251 (0%) avg:0% 18:"bridge-7-5": 577.9911997249991 -> 577.9911997249991 (0%) avg:0% 19:"bridge-7-10": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% 20:"bridge-7-30": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% -158:"top20-157": 5729885219 -> 5729885219 (0%) avg:0% +10:"top20-9": 2.3146866045567974e+29 -> 2.3146866045567974e+29 (0%) avg:0% +11:"top20-10": 2.000939725061475e+25 -> 2.000939725061475e+25 (0%) avg:0% 21:"bridge-7-100": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% +12:"top20-11": 0 -> 0 (0%) avg:0% +22:"bridge-7-300": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% +13:"top20-12": 5.998729978399937e+23 -> 5.998729978399937e+23 (0%) avg:0% +14:"top20-13": 14.999999999999975 -> 14.999999999999975 (0%) avg:0% +15:"top20-14": 242561332730 -> 242561332730 (0%) avg:0% +16:"top20-15": 20057219983855420 -> 20057219983855420 (0%) avg:0% +17:"top20-16": 1371193183.507006 -> 1371193183.507006 (0%) avg:0% +18:"top20-17": 618784869519468900000 -> 618784869519468900000 (0%) avg:0% +19:"top20-18": 13965130914 -> 13965130914 (0%) avg:0% +23:"bridge-7-1000": 578.9911997249991 -> 578.9911997249991 (0%) avg:0% +20:"top20-19": 1719221840266011.2 -> 1719221840266011.2 (0%) avg:0% +21:"top20-20": 1.1539072915253164e+27 -> 1.1539072915253164e+27 (0%) avg:0% +22:"top20-21": 1.4857010533172297e+22 -> 1.4857010533172297e+22 (0%) avg:0% +23:"top20-22": 13216695381.96823 -> 13216695381.96823 (0%) avg:0% +24:"top20-23": 71.99999999995467 -> 71.99999999995467 (0%) avg:0% +25:"top20-24": 4.257526126994545e+23 -> 4.257526126994545e+23 (0%) avg:0% +26:"top20-25": 9.20707200216008e+22 -> 9.20707200216008e+22 (0%) avg:0% +27:"top20-26": 119377775 -> 119377775 (0%) avg:0% +28:"top20-27": 4.5396775085904846e+33 -> 4.5396775085904846e+33 (0%) avg:0% +29:"top20-28": 224764614280864 -> 224764614280864 (0%) avg:0% +30:"top20-29": 137910092016871140 -> 137910092016871140 (0%) avg:0% +31:"top20-30": 38414127759.999916 -> 38414127759.999916 (0%) avg:0% +32:"top20-31": 3.9150404497784796e+29 -> 3.9150404497784796e+29 (0%) avg:0% +33:"top20-32": 44939721212060795000 -> 44939721212060795000 (0%) avg:0% +34:"top20-33": 1.4260244914513205e+22 -> 1.4260244914513205e+22 (0%) avg:0% +35:"top20-34": 1.5495747386928312e+21 -> 1.5495747386928312e+21 (0%) avg:0% +36:"top20-35": 943239170088233300000 -> 943239170088233300000 (0%) avg:0% +37:"top20-36": 6121749117436.458 -> 6121749117436.458 (0%) avg:0% +38:"top20-37": 696747 -> 696747 (0%) avg:0% +39:"top20-38": 0 -> 0 (0%) avg:0% +40:"top20-39": 2.3426635283232224e+24 -> 2.3426635283232224e+24 (0%) avg:0% +41:"top20-40": 48254932363.26666 -> 48254932363.26666 (0%) avg:0% +42:"top20-41": 37860138974211.35 -> 37860138974211.35 (0%) avg:0% +43:"top20-42": 6.848076980412381e+22 -> 6.848076980412381e+22 (0%) avg:0% +44:"top20-43": 4320914881 -> 4320914881 (0%) avg:0% +45:"top20-44": 30713427089 -> 30713427089 (0%) avg:0% +46:"top20-45": 198661729955810 -> 198661729955810 (0%) avg:0% +47:"top20-46": 4003462547412852.5 -> 4003462547412852.5 (0%) avg:0% +48:"top20-47": 121585 -> 121585 (0%) avg:0% +49:"top20-48": 0 -> 0 (0%) avg:0% +50:"top20-49": 5.999999999999976 -> 5.999999999999976 (0%) avg:0% +51:"top20-50": 968129348392.8033 -> 968129348392.8033 (0%) avg:0% +52:"top20-51": 17468164450890598000 -> 17468164450890598000 (0%) avg:0% +53:"top20-52": 3370 -> 3370 (0%) avg:0% +54:"top20-53": 2.8669052288613494e+26 -> 2.8669052288613494e+26 (0%) avg:0% +55:"top20-54": 212397690771150670000 -> 212397690771150670000 (0%) avg:0% +56:"top20-55": 114722123950.99864 -> 114722123950.99864 (0%) avg:0% +57:"top20-56": 6237611807.9999895 -> 6237611807.9999895 (0%) avg:0% +58:"top20-57": 173 -> 173 (0%) avg:0% +59:"top20-58": 8.653786678134718e+34 -> 8.653786678134718e+34 (0%) avg:0% +60:"top20-59": 584843.9943957697 -> 584843.9943957697 (0%) avg:0% +61:"top20-60": 83746.99999922093 -> 83746.99999922093 (0%) avg:0% +62:"top20-61": 1.2108029911483686e+28 -> 1.2108029911483686e+28 (0%) avg:0% +63:"top20-62": 1.1321762736810075e+23 -> 1.1321762736810075e+23 (0%) avg:0% +64:"top20-63": 18624850720 -> 18624850720 (0%) avg:0% +65:"top20-64": 6558802213825504000 -> 6558802213825504000 (0%) avg:0% +66:"top20-65": 3006323408104.839 -> 3006323408104.839 (0%) avg:0% +67:"top20-66": 7.25699759360167e+33 -> 7.25699759360167e+33 (0%) avg:0% +68:"top20-67": 26997497976784.977 -> 26997497976784.977 (0%) avg:0% +69:"top20-68": 2.271898658800524e+29 -> 2.271898658800524e+29 (0%) avg:0% +70:"top20-69": 3320690.9992622463 -> 3320690.9992622463 (0%) avg:0% +71:"top20-70": 12137990973481046000 -> 12137990973481046000 (0%) avg:0% +72:"top20-71": 4.2988353121158716e+26 -> 4.2988353121158716e+26 (0%) avg:0% +73:"top20-72": 6.3575495792381146e+28 -> 6.3575495792381146e+28 (0%) avg:0% +74:"top20-73": 1.2313497939167126e+26 -> 1.2313497939167126e+26 (0%) avg:0% +75:"top20-74": 27707599790097 -> 27707599790097 (0%) avg:0% +76:"top20-75": 7124308 -> 7124308 (0%) avg:0% +77:"top20-76": 0 -> 0 (0%) avg:0% +78:"top20-77": 117608543724585440000 -> 117608543724585440000 (0%) avg:0% +79:"top20-78": 274576852204457 -> 274576852204457 (0%) avg:0% +80:"top20-79": 4.1679251723404575e+23 -> 4.1679251723404575e+23 (0%) avg:0% +81:"top20-80": 1.169123327125618e+23 -> 1.169123327125618e+23 (0%) avg:0% +82:"top20-81": 1.256638691159724e+26 -> 1.256638691159724e+26 (0%) avg:0% +83:"top20-82": 0 -> 0 (0%) avg:0% +84:"top20-83": 2.0149283251435153e+32 -> 2.0149283251435153e+32 (0%) avg:0% +85:"top20-84": 6.510078466693012e+35 -> 6.510078466693012e+35 (0%) avg:0% +86:"top20-85": 0 -> 0 (0%) avg:0% +87:"top20-86": 541712645104171 -> 541712645104171 (0%) avg:0% +88:"top20-87": 2935458414464351700 -> 2935458414464351700 (0%) avg:0% +89:"top20-88": 1672225 -> 1672225 (0%) avg:0% +90:"top20-89": 0 -> 0 (0%) avg:0% +91:"top20-90": 0 -> 0 (0%) avg:0% +92:"top20-91": 98143784 -> 98143784 (0%) avg:0% +93:"top20-92": 8692029076033.435 -> 8692029076033.435 (0%) avg:0% +94:"top20-93": 51562257056054440 -> 51562257056054440 (0%) avg:0% +95:"top20-94": 25641964396823.965 -> 25641964396823.965 (0%) avg:0% +96:"top20-95": 526418678128563400 -> 526418678128563400 (0%) avg:0% +97:"top20-96": 42011945995000000 -> 42011945995000000 (0%) avg:0% +98:"top20-97": 0 -> 0 (0%) avg:0% +99:"top20-98": 578210769514157600 -> 578210769514157600 (0%) avg:0% +100:"top20-99": 23757288573225 -> 23757288573225 (0%) avg:0% +101:"top20-100": 3519054200.963973 -> 3519054200.963973 (0%) avg:0% +102:"top20-101": 1.2366902841804613e+26 -> 1.2366902841804613e+26 (0%) avg:0% +103:"top20-102": 3.0616038596056797e+32 -> 3.0616038596056797e+32 (0%) avg:0% +104:"top20-103": 398198791124206 -> 398198791124206 (0%) avg:0% +105:"top20-104": 3434281999000000 -> 3434281999000000 (0%) avg:0% +106:"top20-105": 436386366610963040000 -> 436386366610963040000 (0%) avg:0% +107:"top20-106": 7814 -> 7814 (0%) avg:0% +108:"top20-107": 4.387432445585929e+34 -> 4.387432445585929e+34 (0%) avg:0% +109:"top20-108": 0 -> 0 (0%) avg:0% +110:"top20-109": 0 -> 0 (0%) avg:0% +111:"top20-110": 180771390372608.16 -> 180771390372608.16 (0%) avg:0% +112:"top20-111": 1.53356324718735e+23 -> 1.53356324718735e+23 (0%) avg:0% +113:"top20-112": 0 -> 0 (0%) avg:0% +114:"top20-113": 441807728976948040000 -> 441807728976948040000 (0%) avg:0% +115:"top20-114": 5.872905678780656e+30 -> 5.872905678780656e+30 (0%) avg:0% +116:"top20-115": 1.9999999999999998 -> 1.9999999999999998 (0%) avg:0% +117:"top20-116": 0 -> 0 (0%) avg:0% +118:"top20-117": 103625.91934739704 -> 103625.91934739704 (0%) avg:0% +119:"top20-118": 3994 -> 3994 (0%) avg:0% +120:"top20-119": 5481554822 -> 5481554822 (0%) avg:0% +121:"top20-120": 2148662632935361000 -> 2148662632935361000 (0%) avg:0% +122:"top20-121": 780768139203693200000 -> 780768139203693200000 (0%) avg:0% +123:"top20-122": 0 -> 0 (0%) avg:0% +124:"top20-123": 74390557839848180 -> 74390557839848180 (0%) avg:0% +125:"top20-124": 5.2767009412144705e+23 -> 5.2767009412144705e+23 (0%) avg:0% +126:"top20-125": 12999322599.999998 -> 12999322599.999998 (0%) avg:0% +127:"top20-126": 1.166563599584172e+25 -> 1.166563599584172e+25 (0%) avg:0% +128:"top20-127": 0 -> 0 (0%) avg:0% +129:"top20-128": 2.381239814048817e+29 -> 2.381239814048817e+29 (0%) avg:0% +130:"top20-129": 1.773617547666896e+21 -> 1.773617547666896e+21 (0%) avg:0% +131:"top20-130": 1043374941775 -> 1043374941775 (0%) avg:0% +132:"top20-131": 3 -> 3 (0%) avg:0% +133:"top20-132": 3523544256 -> 3523544256 (0%) avg:0% +134:"top20-133": 30660569440069612 -> 30660569440069612 (0%) avg:0% +135:"top20-134": 0 -> 0 (0%) avg:0% +136:"top20-135": 46215289309 -> 46215289309 (0%) avg:0% +137:"top20-136": 157666012290841060 -> 157666012290841060 (0%) avg:0% +138:"top20-137": 0 -> 0 (0%) avg:0% +139:"top20-138": 94486154517 -> 94486154517 (0%) avg:0% +140:"top20-139": 5381047.578903644 -> 5381047.578903644 (0%) avg:0% +141:"top20-140": 2904868891031402 -> 2904868891031402 (0%) avg:0% +142:"top20-141": 349815735970433660000 -> 349815735970433660000 (0%) avg:0% +143:"top20-142": 1.61321284630438e+29 -> 1.61321284630438e+29 (0%) avg:0% +144:"top20-143": 0 -> 0 (0%) avg:0% +145:"top20-144": 1.8715935050611244e+27 -> 1.8715935050611244e+27 (0%) avg:0% +146:"top20-145": 2329.999987331977 -> 2329.999987331977 (0%) avg:0% +147:"top20-146": 1.5754421469670991e+28 -> 1.5754421469670991e+28 (0%) avg:0% +148:"top20-147": 2.6838048385825768e+32 -> 2.6838048385825768e+32 (0%) avg:0% +149:"top20-148": 2.7141809250137436e+32 -> 2.7141809250137436e+32 (0%) avg:0% +150:"top20-149": 17399664148369718 -> 17399664148369718 (0%) avg:0% +151:"top20-150": 0 -> 0 (0%) avg:0% +152:"top20-151": 481 -> 481 (0%) avg:0% +153:"top20-152": 0 -> 0 (0%) avg:0% +154:"top20-153": 1.3468577317796694e+32 -> 1.3468577317796694e+32 (0%) avg:0% +155:"top20-154": 7978807883992.964 -> 7978807883992.964 (0%) avg:0% +156:"top20-155": 75460.9999999988 -> 75460.9999999988 (0%) avg:0% +157:"top20-156": 1433531033857000200 -> 1433531033857000200 (0%) avg:0% +158:"top20-157": 5729885219 -> 5729885219 (0%) avg:0% 159:"top20-158": 3.5295876698920206e+21 -> 3.5295876698920206e+21 (0%) avg:0% 160:"top20-159": 2752089826200724500 -> 2752089826200724500 (0%) avg:0% 161:"top20-160": 1.3721043284746797e+27 -> 1.3721043284746797e+27 (0%) avg:0% 162:"top20-161": 2628873 -> 2628873 (0%) avg:0% -22:"bridge-7-300": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% 163:"top20-162": 0 -> 0 (0%) avg:0% 164:"top20-163": 7.139942836800165e+35 -> 7.139942836800165e+35 (0%) avg:0% 165:"top20-164": 588671138.9993676 -> 588671138.9993676 (0%) avg:0% 166:"top20-165": 141491517.99997458 -> 141491517.99997458 (0%) avg:0% -23:"bridge-7-1000": 578.9911997249991 -> 578.9911997249991 (0%) avg:0% 167:"top20-166": 9.906334905865037e+36 -> 9.906334905865037e+36 (0%) avg:0% 168:"top20-167": 6.127970056928261e+23 -> 6.127970056928261e+23 (0%) avg:0% 169:"top20-168": 0 -> 0 (0%) avg:0% diff --git a/packages/ui/src/components/formatted-price.tsx b/packages/ui/src/components/formatted-number.tsx similarity index 78% rename from packages/ui/src/components/formatted-price.tsx rename to packages/ui/src/components/formatted-number.tsx index 5232394308..1585a803b2 100644 --- a/packages/ui/src/components/formatted-price.tsx +++ b/packages/ui/src/components/formatted-number.tsx @@ -1,11 +1,11 @@ import React from 'react' -import { withoutScientificNotation } from 'sushi' +import { formatNumber, withoutScientificNotation } from 'sushi' -interface FormattedPriceProps { +interface FormattedNumberProps { number: string | undefined } -const FormattedPrice: React.FC = ({ number }) => { +const FormattedNumber: React.FC = ({ number }) => { if (typeof number === 'undefined') return undefined const numberStr = withoutScientificNotation(number) @@ -28,7 +28,7 @@ const FormattedPrice: React.FC = ({ number }) => { zeroGroups[0].length === fractionalPart.length ) { // If no zero groups found or less than or equal to 4 zeros, return regular rendering - return {numberStr} + return {formatNumber(numberStr)} } const zeroCount = zeroGroups[0].length @@ -42,4 +42,4 @@ const FormattedPrice: React.FC = ({ number }) => { ) } -export { FormattedPrice } +export { FormattedNumber } diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts index 4ecf40307e..5ed9d3e9fc 100644 --- a/packages/ui/src/components/index.ts +++ b/packages/ui/src/components/index.ts @@ -23,7 +23,7 @@ export * from './dots' export * from './dropdown-menu' export * from './dropzone' export * from './explainer' -export * from './formatted-price' +export * from './formatted-number' export * from './form' export * from './global-footer' export * from './hover-card' diff --git a/packages/ui/src/components/list/ListControl.tsx b/packages/ui/src/components/list/ListControl.tsx index e9c3dd84f6..7f0ea04423 100644 --- a/packages/ui/src/components/list/ListControl.tsx +++ b/packages/ui/src/components/list/ListControl.tsx @@ -12,7 +12,7 @@ export const ListControl: FC = ({ children, className }) => { return ( diff --git a/packages/ui/src/components/list/ListItem.tsx b/packages/ui/src/components/list/ListItem.tsx index c67166d329..1ab6d82c52 100644 --- a/packages/ui/src/components/list/ListItem.tsx +++ b/packages/ui/src/components/list/ListItem.tsx @@ -53,7 +53,7 @@ export const ListItem: ListItemComponent = ({ className={classNames( className, subtitle ? 'items-start' : 'items-center', - 'relative flex gap-4 px-4 py-3 w-full cursor-pointer', + 'relative flex gap-4 px-3 py-3 w-full cursor-pointer', )} > {loading ? ( diff --git a/packages/ui/src/components/list/ListKeyValue.tsx b/packages/ui/src/components/list/ListKeyValue.tsx index d3fd274d20..9774a1368b 100644 --- a/packages/ui/src/components/list/ListKeyValue.tsx +++ b/packages/ui/src/components/list/ListKeyValue.tsx @@ -31,7 +31,7 @@ export const ListKeyValue: FC = ({ }) => { if (skeleton) { return ( -
+
{subtitle && } @@ -48,21 +48,17 @@ export const ListKeyValue: FC = ({ className={classNames( className, flex ? 'flex justify-between items-center' : 'grid grid-cols-2', - 'gap-2 py-3 px-4', + 'gap-2 py-3 px-3 rounded-lg', )} >
- - {title} - + {title} {subtitle && ( {subtitle} )}
-
- - {children} - +
+ {children}
) diff --git a/packages/ui/src/components/list/ListMenuItem.tsx b/packages/ui/src/components/list/ListMenuItem.tsx index 98fdc48767..653f5fa039 100644 --- a/packages/ui/src/components/list/ListMenuItem.tsx +++ b/packages/ui/src/components/list/ListMenuItem.tsx @@ -68,7 +68,7 @@ export const ListMenuItem: ListMenuItemComponent = ({ className, disabled ? 'opacity-40 !pointer-events-none cursor-default' : '', subtitle ? 'items-start' : 'items-center', - 'hover:bg-muted relative flex gap-4 px-4 py-3 w-full cursor-pointer rounded-xl', + 'hover:bg-muted relative flex gap-4 px-3 py-3 w-full cursor-pointer rounded-xl', )} > {Icon && ( diff --git a/packages/ui/src/components/settings/SlippageTolerance.tsx b/packages/ui/src/components/settings/SlippageTolerance.tsx index ec95f97945..67047cf716 100644 --- a/packages/ui/src/components/settings/SlippageTolerance.tsx +++ b/packages/ui/src/components/settings/SlippageTolerance.tsx @@ -1,6 +1,9 @@ import { RadioGroup } from '@headlessui/react' import { InformationCircleIcon } from '@heroicons/react/20/solid' -import { useSlippageTolerance } from '@sushiswap/hooks' +import { + SlippageToleranceStorageKey, + useSlippageTolerance, +} from '@sushiswap/hooks' import classNames from 'classnames' import React, { FC, useCallback } from 'react' @@ -23,7 +26,7 @@ const TABS = ['0.1', '0.5', '1.0'] export const SlippageTolerance: FC<{ options?: { - storageKey?: string + storageKey?: SlippageToleranceStorageKey defaultValue?: string title?: string } diff --git a/packages/ui/src/components/settings/TransactionDeadline.tsx b/packages/ui/src/components/settings/TransactionDeadline.tsx new file mode 100644 index 0000000000..f08e01ddf5 --- /dev/null +++ b/packages/ui/src/components/settings/TransactionDeadline.tsx @@ -0,0 +1,68 @@ +import { InformationCircleIcon } from '@heroicons/react/20/solid' +import { TTLStorageKey, useTTL } from '@sushiswap/hooks' +import classNames from 'classnames' +import React, { FC, useCallback } from 'react' + +import { CardDescription, CardHeader, CardTitle } from '../card' +import { + HoverCard, + HoverCardContent, + HoverCardPrimitive, + HoverCardTrigger, +} from '../hover-card' +import { Label } from '../label' +import { TextField } from '../text-field' + +export const TransactionDeadline: FC<{ + options: { + storageKey: TTLStorageKey + defaultValue?: string + title?: string + } + className?: string +}> = ({ options, className }) => { + const [ttl, setTTL] = useTTL(options.storageKey) + + const onChange = useCallback( + (value: string) => { + setTTL(Number(value)) + }, + [setTTL], + ) + + return ( + +
+
+
+ +
+ +
+
+
+ ) +} diff --git a/packages/ui/src/components/settings/index.tsx b/packages/ui/src/components/settings/index.tsx index 24d0807c4e..a84319e1c7 100644 --- a/packages/ui/src/components/settings/index.tsx +++ b/packages/ui/src/components/settings/index.tsx @@ -1,7 +1,11 @@ 'use client' import { Cog6ToothIcon, XMarkIcon } from '@heroicons/react/24/outline' -import { useSlippageTolerance } from '@sushiswap/hooks' +import { + SlippageToleranceStorageKey, + TTLStorageKey, + useSlippageTolerance, +} from '@sushiswap/hooks' import React, { FC, ReactNode, useState } from 'react' import { Button } from '../button' @@ -23,12 +27,14 @@ import { import { CarbonOffset } from './CarbonOffset' import { ExpertMode } from './ExpertMode' import { SlippageTolerance } from './SlippageTolerance' +import { TransactionDeadline } from './TransactionDeadline' export enum SettingsModule { CarbonOffset = 'CarbonOffset', CustomTokens = 'CustomTokens', SlippageTolerance = 'SlippageTolerance', ExpertMode = 'ExpertMode', + TransactionDeadline = 'TransactionDeadline', } interface SettingsOverlayProps { @@ -37,7 +43,12 @@ interface SettingsOverlayProps { externalModules?: FC[] options?: { slippageTolerance?: { - storageKey?: string + storageKey?: SlippageToleranceStorageKey + defaultValue?: string + title?: string + } + transactionDeadline?: { + storageKey: TTLStorageKey defaultValue?: string title?: string } @@ -118,6 +129,10 @@ export const SettingsOverlay: FC = ({ {modules.includes(SettingsModule.CarbonOffset) && ( )} + {modules.includes(SettingsModule.TransactionDeadline) && + options?.transactionDeadline && ( + + )} {externalModules?.map((Module, index) => ( diff --git a/packages/wagmi/src/components/index.ts b/packages/wagmi/src/components/index.ts index 0c73716e77..dcf07ae0ef 100644 --- a/packages/wagmi/src/components/index.ts +++ b/packages/wagmi/src/components/index.ts @@ -1,6 +1,7 @@ export * from './connect-button' export * from './network-check' export * from './sanctioned-address-dialog' +export * from './token-security-view' export * from './user-profile' export * from './wagmi-store-version-check' export * from './wagmi-header-components' diff --git a/packages/wagmi/src/components/token-security-view.tsx b/packages/wagmi/src/components/token-security-view.tsx new file mode 100644 index 0000000000..687ca13b75 --- /dev/null +++ b/packages/wagmi/src/components/token-security-view.tsx @@ -0,0 +1,183 @@ +import { + ExclamationTriangleIcon, + HandThumbUpIcon, +} from '@heroicons/react/24/solid' +import { + TokenSecurity, + TokenSecurityLabel, + TokenSecurityMessage, + TokenSecurityResponse, +} from '@sushiswap/react-query' +import { + Button, + Explainer, + GoPlusLabsIcon, + List, + SelectIcon, + classNames, +} from '@sushiswap/ui' +import { useMemo, useState } from 'react' +import { Token } from 'sushi/currency' + +const isTokenSecurityIssue = { + // Contract security + is_open_source: (value: TokenSecurity['is_open_source']) => value === false, + is_proxy: (value: TokenSecurity['is_proxy']) => value === true, + is_mintable: (value: TokenSecurity['is_mintable']) => value === true, + can_take_back_ownership: (value: TokenSecurity['can_take_back_ownership']) => + value === true, + owner_change_balance: (value: TokenSecurity['owner_change_balance']) => + value === true, + gas_abuse: (value: TokenSecurity['gas_abuse']) => value === true, + // Trading security + buy_tax: (value: TokenSecurity['buy_tax']) => value === true, + sell_tax: (value: TokenSecurity['sell_tax']) => value === true, + is_buyable: (value: TokenSecurity['is_buyable']) => value === false, + is_sell_limit: (value: TokenSecurity['is_sell_limit']) => value === true, + slippage_modifiable: (value: TokenSecurity['slippage_modifiable']) => + value === true, + is_honeypot: (value: TokenSecurity['is_honeypot']) => value === true, + transfer_pausable: (value: TokenSecurity['transfer_pausable']) => + value === true, + is_blacklisted: (value: TokenSecurity['is_blacklisted']) => value === true, + is_whitelisted: (value: TokenSecurity['is_whitelisted']) => value === true, + is_anti_whale: (value: TokenSecurity['is_anti_whale']) => value === true, + trading_cooldown: (value: TokenSecurity['trading_cooldown']) => + value === true, + // Info security + is_fake_token: (value: TokenSecurity['is_fake_token']) => value === true, + is_airdrop_scam: (value: TokenSecurity['is_airdrop_scam']) => value === true, +} as Record< + keyof TokenSecurity, + (value: TokenSecurity[keyof TokenSecurity]) => boolean +> + +export const TokenSecurityView = ({ + tokenSecurityResponse, + token, +}: { + tokenSecurityResponse: TokenSecurityResponse | undefined + token: Token +}) => { + const [showMore, setShowMore] = useState(false) + + const { tokenSecurity, issues, nonIssues } = useMemo(() => { + const tokenSecurity = tokenSecurityResponse?.[token.address] + const issues: (keyof TokenSecurity)[] = [] + const nonIssues: (keyof TokenSecurity)[] = [] + + for (const [_key, value] of Object.entries(tokenSecurity || {})) { + const key = _key as keyof TokenSecurity + if (key in isTokenSecurityIssue && isTokenSecurityIssue[key](value)) + issues.push(key) + else nonIssues.push(key) + } + + return { tokenSecurity, issues, nonIssues } + }, [tokenSecurityResponse, token]) + + return ( + + + + powered by GoPlus + +
+ } + value={ +
0 + ? 'bg-yellow/20 text-yellow' + : 'bg-green/20 text-green', + )} + > + {Number(issues?.length) > 0 ? ( + + ) : ( + + )} + {`${Number(issues?.length)} issue${ + Number(issues?.length) !== 1 ? 's' : '' + } found`} +
+ } + /> + {issues.map((key) => ( + + {TokenSecurityLabel[key]} + {TokenSecurityMessage[key]} +
+ } + > +
+
+ {tokenSecurity?.[key] === undefined + ? 'Unknown' + : tokenSecurity[key] + ? 'Yes' + : 'No'} +
+ +
+ + ))} + {showMore + ? nonIssues.map((key) => ( + + {TokenSecurityLabel[key]} + {TokenSecurityMessage[key]} +
+ } + > +
+ {tokenSecurity?.[key] ? 'Yes' : 'No'} + +
+ + )) + : null} +
+ +
+ + + ) +} diff --git a/packages/wagmi/src/components/token-selector/TokenSelector.tsx b/packages/wagmi/src/components/token-selector/TokenSelector.tsx index 632d1c4608..1bb31d73e9 100644 --- a/packages/wagmi/src/components/token-selector/TokenSelector.tsx +++ b/packages/wagmi/src/components/token-selector/TokenSelector.tsx @@ -292,7 +292,7 @@ export const TokenSelector: FC = ({ ] && !tokenMap?.[`${queryToken.wrapped.address}`] && ( queryToken && handleImport(queryToken)} /> )} diff --git a/packages/wagmi/src/components/token-selector/TokenSelectorImportRow.tsx b/packages/wagmi/src/components/token-selector/TokenSelectorImportRow.tsx index d02363d87a..3eee3b2f53 100644 --- a/packages/wagmi/src/components/token-selector/TokenSelectorImportRow.tsx +++ b/packages/wagmi/src/components/token-selector/TokenSelectorImportRow.tsx @@ -7,193 +7,157 @@ import { DialogHeader, DialogTitle, DialogTrigger, - GoPlusLabsIcon, - LinkExternal, + Message, } from '@sushiswap/ui' import { Button } from '@sushiswap/ui/components/button' import { Icon } from '@sushiswap/ui/components/currency/Icon' import { List } from '@sushiswap/ui/components/list/List' -import React, { FC, ReactNode, useCallback, useState } from 'react' +import { FC, useCallback, useState } from 'react' import { Chain } from 'sushi/chain' import { Token } from 'sushi/currency' import { shortenAddress } from 'sushi/format' +import { isTokenSecurityChainId } from 'sushi/config' +import { TokenSecurityView } from '../token-security-view' + interface TokenSelectorImportRow { - currencies: (Token | undefined)[] + currency: Token onImport(): void } export const TokenSelectorImportRow: FC = ({ - currencies, + currency, onImport, }) => { const [open, setOpen] = useState(false) - const { data: tokenSecurity } = useTokenSecurity({ - currencies, + + const { + data: tokenSecurityResponse, + isInitialLoading: tokenSecurityLoading, + } = useTokenSecurity({ + currencies: [currency], enabled: open, }) const onClick = useCallback(() => { - if (!tokenSecurity?.honeypots || tokenSecurity.honeypots.length === 0) { - onImport() + onImport() - setTimeout(() => { - setOpen(false) - }, 250) - } else { + setTimeout(() => { setOpen(false) - } - }, [onImport, tokenSecurity]) + }, 250) + }, [onImport]) + + const honeypot = Boolean( + currency && tokenSecurityResponse?.[currency.address]?.is_honeypot, + ) return ( - + !open && setOpen(false)}>
- {currencies[0] ? ( -
-
- -
-
- - {currencies[0].symbol} - - - {currencies[0].name} - -
+
+
+
- ) : null} - +
+ + {currency.symbol} + + + {currency.name} + +
+
- +
- - - {!tokenSecurity?.honeypots || tokenSecurity.honeypots.length === 0 ? ( - <> - Import token - - Trade at your own risk!{' '} - {currencies.length > 1 - ? "These tokens don't" - : "This token doesn't"}{' '} - appear on the active token list(s). Anyone can create a token, - including creating fake versions of existing tokens that claim - to represent projects. - - - ) : ( - <> - Not supported! - - {tokenSecurity.honeypots.length > 1 - ? 'These tokens have been identified as potential honeypot scams and are not supported. Do not interact with these tokens to safeguard your assets.' - : 'This token has been identified as a potential honeypot scam and is not supported. Do not interact with this token to safeguard your assets.'}{' '} - - - - )} - -
- {!tokenSecurity?.honeypots || tokenSecurity.honeypots.length === 0 ? ( - + {!isTokenSecurityChainId(currency.chainId) || !tokenSecurityLoading ? ( + + + Import token + + Anyone can create a token, including creating fake versions of + existing tokens that claim to represent projects. If you purchase + this token, you may not be able to sell it back. + + +
+ - {currencies.reduce((acc, cur) => { - if (cur) { - acc.push( -
- - -
, - ) + + Name + } - - return acc - }, [])} -
-
- ) : ( - - - {tokenSecurity.honeypots.reduce((acc, cur) => { - const currency = currencies.find( - (currency) => currency?.address === cur, - ) - if (currency) { - acc.push( -
- -
- - {currency.symbol} - - - {shortenAddress(currency.address)} - -
-
, - ) + > + {currency.name} + + + Symbol + } - - return acc - }, [])} + > + {currency.symbol} + + + Address + + } + > + + {shortenAddress(currency.address)} + +
- )} -
- -
- - {tokenSecurity?.isSupported ? ( -
- - Honeypot detection powered by GoPlus - - -
+ {isTokenSecurityChainId(currency.chainId) ? ( + ) : null}
-
-
+ +
+ {!honeypot ? ( + + ) : ( +
+ + + + + Sushi does not support honetpot tokens. This token contract + cannot be imported! + +
+ )} +
+
+ + ) : null}
) } diff --git a/packages/wagmi/src/hooks/utils/hooks/useTransactionDeadline.ts b/packages/wagmi/src/hooks/utils/hooks/useTransactionDeadline.ts index c596197d12..dce1c96283 100644 --- a/packages/wagmi/src/hooks/utils/hooks/useTransactionDeadline.ts +++ b/packages/wagmi/src/hooks/utils/hooks/useTransactionDeadline.ts @@ -1,43 +1,45 @@ -import { ChainId, chainsL2 } from 'sushi/chain' - +import { TTLStorageKey, useTTL } from '@sushiswap/hooks' import { useQuery } from '@tanstack/react-query' -import { useCurrentBlockTimestamp } from '../..' +import { ChainId, chainsL2 } from 'sushi/chain' +import { useCurrentBlockTimestamp } from '../../block' -const L2_DEADLINE_FROM_NOW = 60n * 5n +const L2_TTL = 5n const TTL = 30n +export const getDefaultTTL = (chainId: ChainId) => { + return Object.keys(chainsL2).includes(chainId.toString()) ? L2_TTL : TTL +} + interface UseTransactionDeadline { chainId: ChainId enabled?: boolean + storageKey: TTLStorageKey } export const useTransactionDeadline = ({ chainId, enabled = true, + storageKey, }: UseTransactionDeadline) => { const { data: currentBlockTimestampQuery } = useCurrentBlockTimestamp( chainId, enabled, ) + const [_ttl] = useTTL(storageKey) + // currentBlockTimestampQuery is excluded from the dependencies array by design, // deadline should be updated every 60s, not on every block return useQuery({ - queryKey: ['useTransactionDeadline'], + queryKey: ['useTransactionDeadline', _ttl], queryFn: () => { const blockTimestamp = currentBlockTimestampQuery let data = undefined - if ( - blockTimestamp && - chainId && - Object.keys(chainsL2).includes(chainId.toString()) - ) { - data = blockTimestamp + L2_DEADLINE_FROM_NOW - } + const ttl = _ttl > 0 ? BigInt(_ttl) : getDefaultTTL(chainId) if (blockTimestamp) { - data = blockTimestamp + TTL * 60n + data = blockTimestamp + ttl * 60n } return data diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 792cdf3a24..2988565ef7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -708,9 +708,6 @@ importers: '@types/node': specifier: '20' version: 20.10.0 - '@types/numeral': - specifier: 2.0.2 - version: 2.0.2 '@types/react': specifier: 18.2.14 version: 18.2.14 @@ -1576,9 +1573,6 @@ importers: '@types/node': specifier: '20' version: 20.10.0 - '@types/numeral': - specifier: 2.0.2 - version: 2.0.2 '@wagmi/core': specifier: 2.6.17 version: 2.6.17(@types/react@18.2.14)(react@18.2.0)(typescript@5.2.2)(viem@2.8.14)(zod@3.21.4) @@ -1652,12 +1646,6 @@ importers: packages/react-query: dependencies: - '@sushiswap/client': - specifier: workspace:* - version: link:../client - '@sushiswap/database': - specifier: workspace:* - version: link:../database '@sushiswap/dexie': specifier: workspace:* version: link:../dexie @@ -1686,6 +1674,12 @@ importers: '@sentry/nextjs': specifier: 7.101.1 version: 7.101.1(next@14.1.0)(react@18.2.0) + '@sushiswap/client': + specifier: workspace:* + version: link:../client + '@sushiswap/database': + specifier: workspace:* + version: link:../database '@sushiswap/jest-config': specifier: workspace:* version: link:../../config/jest @@ -1823,9 +1817,9 @@ importers: memoize-fs: specifier: github:rouzwelt/memoize-fs#e5fcc9f6effc4ad087514372a53a49d380520ad5 version: github.com/rouzwelt/memoize-fs/e5fcc9f6effc4ad087514372a53a49d380520ad5 - numeral: - specifier: 2.0.6 - version: 2.0.6 + numbro: + specifier: 2.5.0 + version: 2.5.0 seedrandom: specifier: 3.0.5 version: 3.0.5 @@ -1860,9 +1854,6 @@ importers: '@types/lodash.flatmap': specifier: 4.5.9 version: 4.5.9 - '@types/numeral': - specifier: 2.0.3 - version: 2.0.3 '@types/seedrandom': specifier: 3.0.1 version: 3.0.1 @@ -18160,14 +18151,6 @@ packages: /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - /@types/numeral@2.0.2: - resolution: {integrity: sha512-A8F30k2gYJ/6e07spSCPpkuZu79LCnkPTvqmIWQzNGcrzwFKpVOydG41lNt5wZXjSI149qjyzC2L1+F2PD/NUA==} - dev: true - - /@types/numeral@2.0.3: - resolution: {integrity: sha512-37VDYvFbx/I+Ve1kwcDUq5+qvgNl+uy9YUZhBMJ6YWHBtr2+d6CAgdn4R81NqBlZbTpvLxJOTUhwbki7+90+qQ==} - dev: true - /@types/parse-json@4.0.2: resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -33746,8 +33729,10 @@ packages: bn.js: 4.11.6 strip-hex-prefix: 1.0.0 - /numeral@2.0.6: - resolution: {integrity: sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==} + /numbro@2.5.0: + resolution: {integrity: sha512-xDcctDimhzko/e+y+Q2/8i3qNC9Svw1QgOkSkQoO0kIPI473tR9QRbo2KP88Ty9p8WbPy+3OpTaAIzehtuHq+A==} + dependencies: + bignumber.js: 9.1.1 dev: false /nwsapi@2.2.7: