From 3c1144bb34718fc74e33ee8e829cc0f82d9e9516 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Fri, 3 Nov 2023 16:10:17 +0000 Subject: [PATCH 01/27] chore: add PermitUtils type `unsupported` --- libs/permit-utils/src/index.ts | 9 +-------- .../src/lib/checkIsCallDataAValidPermit.ts | 8 ++++++-- libs/permit-utils/src/lib/generatePermitHook.ts | 5 +++++ libs/permit-utils/src/lib/getTokenPermitInfo.ts | 10 ++++++---- libs/permit-utils/src/types.ts | 14 +++++--------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libs/permit-utils/src/index.ts b/libs/permit-utils/src/index.ts index 3edad2af5e..454202edf5 100644 --- a/libs/permit-utils/src/index.ts +++ b/libs/permit-utils/src/index.ts @@ -3,11 +3,4 @@ export { generatePermitHook } from './lib/generatePermitHook' export { getPermitUtilsInstance } from './lib/getPermitUtilsInstance' export { getTokenPermitInfo } from './lib/getTokenPermitInfo' -export type { - PermitHookData, - PermitHookParams, - PermitInfo, - PermitType, - SupportedPermitInfo, - GetTokenPermitIntoResult, -} from './types' +export type { PermitHookData, PermitHookParams, PermitInfo, PermitType, GetTokenPermitIntoResult } from './types' diff --git a/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts b/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts index 7c9c4cd48c..c03145800c 100644 --- a/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts +++ b/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts @@ -1,6 +1,6 @@ import { DAI_PERMIT_SELECTOR, Eip2612PermitUtils, EIP_2612_PERMIT_SELECTOR } from '@1inch/permit-signed-approvals-utils' -import { SupportedPermitInfo } from '../types' +import { PermitInfo } from '../types' import { fixTokenName } from '../utils/fixTokenName' export async function checkIsCallDataAValidPermit( @@ -10,8 +10,12 @@ export async function checkIsCallDataAValidPermit( tokenAddress: string, tokenName: string, callData: string, - { version }: SupportedPermitInfo + { version, type }: PermitInfo ): Promise { + if (type === 'unsupported') { + return false + } + const params = { chainId, tokenName: fixTokenName(tokenName), tokenAddress, callData, version } let recoverPermitOwnerPromise: Promise | undefined = undefined diff --git a/libs/permit-utils/src/lib/generatePermitHook.ts b/libs/permit-utils/src/lib/generatePermitHook.ts index 4299748a92..0e1da7c9fe 100644 --- a/libs/permit-utils/src/lib/generatePermitHook.ts +++ b/libs/permit-utils/src/lib/generatePermitHook.ts @@ -35,9 +35,14 @@ export async function generatePermitHook(params: PermitHookParams): Promise { const { inputToken, spender, chainId, permitInfo, provider, account, eip2162Utils, nonce: preFetchedNonce } = params + const tokenAddress = inputToken.address const tokenName = inputToken.name || tokenAddress + if (permitInfo.type === 'unsupported') { + throw new Error(`Trying to generate permit hook for unsupported token: ${tokenAddress}`) + } + const owner = account || PERMIT_SIGNER.address // Only fetch the nonce in case it wasn't pre-fetched before diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index cb347da253..0717aeaf18 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -6,7 +6,7 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' import { getPermitUtilsInstance } from './getPermitUtilsInstance' import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER, TOKENS_TO_SKIP_VERSION } from '../const' -import { GetTokenPermitInfoParams, GetTokenPermitIntoResult, PermitType } from '../types' +import { GetTokenPermitInfoParams, GetTokenPermitIntoResult, PermitInfo, PermitType } from '../types' import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from '../utils/buildPermitCallData' import { getPermitDeadline } from '../utils/getPermitDeadline' @@ -24,6 +24,8 @@ const DAI_LIKE_PERMIT_PARAMS = { const REQUESTS_CACHE: Record> = {} +const UNSUPPORTED: PermitInfo = { type: 'unsupported' } + export async function getTokenPermitInfo(params: GetTokenPermitInfoParams): Promise { const { tokenAddress, chainId } = params @@ -59,7 +61,7 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) // Here we know it's not supported, return false // See https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L309 // and https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L325 - return false + return UNSUPPORTED } console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${tokenAddress}`, e) @@ -134,7 +136,7 @@ async function estimateTokenPermit(params: EstimateParams): Promise { diff --git a/libs/permit-utils/src/types.ts b/libs/permit-utils/src/types.ts index 054aa5cef4..1e70f0efd9 100644 --- a/libs/permit-utils/src/types.ts +++ b/libs/permit-utils/src/types.ts @@ -2,14 +2,12 @@ import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' import { latest } from '@cowprotocol/app-data' import { JsonRpcProvider } from '@ethersproject/providers' -export type PermitType = 'dai-like' | 'eip-2612' +export type PermitType = 'dai-like' | 'eip-2612' | 'unsupported' -export type SupportedPermitInfo = { +export type PermitInfo = { type: PermitType - version: string | undefined // Some tokens have it different than `1`, and won't work without it + version?: string | undefined // Some tokens have it different than `1`, and won't work without it } -type UnsupportedPermitInfo = false -export type PermitInfo = SupportedPermitInfo | UnsupportedPermitInfo // Local TokenInfo definition to not depend on external libs just for this type TokenInfo = { @@ -21,7 +19,7 @@ export type PermitHookParams = { inputToken: TokenInfo spender: string chainId: number - permitInfo: SupportedPermitInfo + permitInfo: PermitInfo provider: JsonRpcProvider eip2162Utils: Eip2612PermitUtils account?: string | undefined @@ -34,11 +32,9 @@ type FailedToIdentify = { error: string } export type GetTokenPermitIntoResult = // When it's a permittable token: - | SupportedPermitInfo + | PermitInfo // When something failed: | FailedToIdentify - // When it's not permittable: - | UnsupportedPermitInfo type BasePermitCallDataParams = { eip2162Utils: Eip2612PermitUtils From 631e5d15e725d221d2ad8683662d890125e35ad4 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Fri, 3 Nov 2023 16:11:59 +0000 Subject: [PATCH 02/27] chore: apply PermitInfo type to consumers --- .../modules/limitOrders/services/tradeFlow/index.ts | 2 +- .../permit/hooks/useAccountAgnosticPermitHookData.ts | 3 ++- .../src/modules/permit/hooks/useGeneratePermitHook.ts | 2 +- .../src/modules/permit/hooks/useIsTokenPermittable.ts | 10 ++++------ .../src/modules/permit/utils/handlePermit.ts | 2 +- .../src/modules/swap/services/swapFlow/index.ts | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts index e6c7baf500..f041295935 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts @@ -57,7 +57,7 @@ export async function tradeFlow( try { logTradeFlow('LIMIT ORDER FLOW', 'STEP 2: handle permit') - if (permitInfo) beforePermit() + if (permitInfo && permitInfo.type !== 'unsupported') beforePermit() postOrderParams.appData = await handlePermit({ permitInfo, diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts index 580e46f2ee..306b5a2680 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -44,7 +44,8 @@ function useGeneratePermitHookParams(): GeneratePermitHookParams | undefined { const permitInfo = useIsTokenPermittable(inputCurrency, tradeType) return useSafeMemo(() => { - if (!inputCurrency || !('address' in inputCurrency) || !permitInfo) return undefined + if (!inputCurrency || !('address' in inputCurrency) || !permitInfo || permitInfo.type === 'unsupported') + return undefined return { inputToken: { address: inputCurrency.address, name: inputCurrency.name }, diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts index 2a821920e9..7b9a7541ef 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts @@ -38,7 +38,7 @@ export function useGeneratePermitHook(): GeneratePermitHook { async (params: GeneratePermitHookParams): Promise => { const { inputToken, account, permitInfo } = params - if (!provider) { + if (!provider || permitInfo.type === 'unsupported') { return } diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts index 025b281819..c4fd12deca 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts @@ -70,16 +70,14 @@ export function useIsTokenPermittable( } getTokenPermitInfo({ spender, tokenAddress: lowerCaseAddress, tokenName, chainId, provider }).then((result) => { - if (!result) { - // When falsy, we know it doesn't support permit. Cache it. - addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: false }) - } else if ('error' in result) { + + if ('error' in result) { // When error, we don't know. Log and don't cache. console.debug( `useIsTokenPermittable: failed to check whether token ${lowerCaseAddress} is permittable: ${result.error}` ) } else { - // Otherwise, we know it is permittable. Cache it. + // Otherwise, we know it is permittable or not. Cache it. addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: result }) } }) @@ -98,7 +96,7 @@ export function useIsTokenPermittable( ]) if (isNative) { - return false + return { type: 'unsupported' } } return preGeneratedInfo ?? permitInfo diff --git a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts index ce63421a0e..eeb7ed3d45 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts @@ -15,7 +15,7 @@ import { HandlePermitParams } from '../types' export async function handlePermit(params: HandlePermitParams): Promise { const { permitInfo, inputToken, account, appData, generatePermitHook } = params - if (permitInfo && 'address' in inputToken) { + if (permitInfo && permitInfo.type !== 'unsupported' && 'address' in inputToken) { // permitInfo will only be set if there's NOT enough allowance const permitData = await generatePermitHook({ diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts index 48e61f8b67..46a552e6ec 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts @@ -26,7 +26,7 @@ export async function swapFlow( try { logTradeFlow('SWAP FLOW', 'STEP 2: handle permit') - if (input.permitInfo) input.swapConfirmManager.requestPermitSignature() + if (input.permitInfo && input.permitInfo.type !== 'unsupported') input.swapConfirmManager.requestPermitSignature() input.orderParams.appData = await handlePermit({ appData: input.orderParams.appData, From 0652a4853956313757f87a61a0d1f07b5edb7895 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Fri, 3 Nov 2023 16:12:49 +0000 Subject: [PATCH 03/27] feat: add helper method to only check whether token is permittable useTokenSupportsPermit --- .../modules/permit/hooks/useTokenSupportsPermit.ts | 13 +++++++++++++ apps/cowswap-frontend/src/modules/permit/index.ts | 1 + .../src/modules/swap/hooks/useSwapButtonContext.ts | 4 ++-- .../hooks/useTradeFormValidationContext.ts | 4 ++-- 4 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts new file mode 100644 index 0000000000..ca2443dbd4 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts @@ -0,0 +1,13 @@ +import { Currency } from '@uniswap/sdk-core' + +import { Nullish } from 'types' + +import { TradeType } from 'modules/trade' + +import { useIsTokenPermittable } from './useIsTokenPermittable' + +export function useTokenSupportsPermit(token: Nullish, tradeType: Nullish): boolean { + const permitInfo = useIsTokenPermittable(token, tradeType) + + return !!permitInfo && permitInfo.type !== 'unsupported' +} diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts index c7e91b4054..cea0c4a980 100644 --- a/apps/cowswap-frontend/src/modules/permit/index.ts +++ b/apps/cowswap-frontend/src/modules/permit/index.ts @@ -3,6 +3,7 @@ export * from './hooks/useGeneratePermitHook' export * from './hooks/useIsTokenPermittable' export * from './hooks/useOrdersPermitStatus' export * from './hooks/usePermitCompatibleTokens' +export * from './hooks/useTokenSupportsPermit' export * from './types' export * from './updaters/PendingPermitUpdater' export * from './utils/handlePermit' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts index a95c5937d5..f4caabb7fa 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts @@ -15,7 +15,7 @@ import { useGetQuoteAndStatus, useIsBestQuoteLoading } from 'legacy/state/price/ import { Field } from 'legacy/state/types' import { useExpertModeManager } from 'legacy/state/user/hooks' -import { useIsTokenPermittable } from 'modules/permit' +import { useTokenSupportsPermit } from 'modules/permit' import { getSwapButtonState } from 'modules/swap/helpers/getSwapButtonState' import { useEthFlowContext } from 'modules/swap/hooks/useEthFlowContext' import { useHandleSwap } from 'modules/swap/hooks/useHandleSwap' @@ -93,7 +93,7 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext const isSwapUnsupported = useIsTradeUnsupported(currencyIn, currencyOut) const isSmartContractWallet = useIsSmartContractWallet() const isBundlingSupported = useIsBundlingSupported() - const isPermitSupported = !!useIsTokenPermittable(currencyIn, TradeType.SWAP) + const isPermitSupported = useTokenSupportsPermit(currencyIn, TradeType.SWAP) const swapButtonState = getSwapButtonState({ account, diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts index 003bd0cc33..2c469ad357 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts @@ -5,7 +5,7 @@ import { useIsTradeUnsupported } from '@cowprotocol/tokens' import { useGnosisSafeInfo, useIsBundlingSupported, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' import { isUnsupportedTokenInQuote } from 'modules/limitOrders/utils/isUnsupportedTokenInQuote' -import { useIsTokenPermittable } from 'modules/permit' +import { useTokenSupportsPermit } from 'modules/permit' import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' import { useTradeQuote } from 'modules/tradeQuote' @@ -32,7 +32,7 @@ export function useTradeFormValidationContext(): TradeFormValidationCommonContex const isSafeReadonlyUser = gnosisSafeInfo?.isReadOnly || false - const isPermitSupported = !!useIsTokenPermittable(inputCurrency, tradeType) + const isPermitSupported = useTokenSupportsPermit(inputCurrency, tradeType) const commonContext = { account, From 540c1022a2ac7263deab6e886113c60ed672b78f Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Fri, 3 Nov 2023 16:26:34 +0000 Subject: [PATCH 04/27] refactor: rename useIsTokenPermittable to usePermitInfo --- .../limitOrders/hooks/useTradeFlowContext.ts | 4 +-- .../hooks/useAccountAgnosticPermitHookData.ts | 4 +-- ...IsTokenPermittable.ts => usePermitInfo.ts} | 25 ++++++------------- .../permit/hooks/useTokenSupportsPermit.ts | 10 ++++++-- .../src/modules/permit/index.ts | 2 +- .../modules/swap/hooks/useSwapFlowContext.ts | 4 +-- 6 files changed, 23 insertions(+), 26 deletions(-) rename apps/cowswap-frontend/src/modules/permit/hooks/{useIsTokenPermittable.ts => usePermitInfo.ts} (83%) diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts index 488fa09af8..244a10c9ab 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts @@ -15,7 +15,7 @@ import { useAppData } from 'modules/appData' import { useRateImpact } from 'modules/limitOrders/hooks/useRateImpact' import { TradeFlowContext } from 'modules/limitOrders/services/types' import { limitOrdersSettingsAtom } from 'modules/limitOrders/state/limitOrdersSettingsAtom' -import { useGeneratePermitHook, useIsTokenPermittable } from 'modules/permit' +import { useGeneratePermitHook, usePermitInfo } from 'modules/permit' import { useEnoughBalanceAndAllowance } from 'modules/tokens' import { TradeType } from 'modules/trade' import { useTradeQuote } from 'modules/tradeQuote' @@ -34,7 +34,7 @@ export function useTradeFlowContext(): TradeFlowContext | null { const quoteState = useTradeQuote() const rateImpact = useRateImpact() const settingsState = useAtomValue(limitOrdersSettingsAtom) - const permitInfo = useIsTokenPermittable(state.inputCurrency, TradeType.LIMIT_ORDER) + const permitInfo = usePermitInfo(state.inputCurrency, TradeType.LIMIT_ORDER) const checkAllowanceAddress = GP_VAULT_RELAYER[chainId] const { enoughAllowance } = useEnoughBalanceAndAllowance({ diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts index 306b5a2680..e94c468987 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -7,7 +7,7 @@ import { useDerivedTradeState } from 'modules/trade' import { useSafeMemo } from 'common/hooks/useSafeMemo' import { useGeneratePermitHook } from './useGeneratePermitHook' -import { useIsTokenPermittable } from './useIsTokenPermittable' +import { usePermitInfo } from './usePermitInfo' import { GeneratePermitHookParams } from '../types' @@ -41,7 +41,7 @@ function useGeneratePermitHookParams(): GeneratePermitHookParams | undefined { const { state } = useDerivedTradeState() const { inputCurrency, tradeType } = state || {} - const permitInfo = useIsTokenPermittable(inputCurrency, tradeType) + const permitInfo = usePermitInfo(inputCurrency, tradeType) return useSafeMemo(() => { if (!inputCurrency || !('address' in inputCurrency) || !permitInfo || permitInfo.type === 'unsupported') diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts similarity index 83% rename from apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts rename to apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts index c4fd12deca..433b1dde62 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts @@ -22,17 +22,16 @@ import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/permi import { IsTokenPermittableResult } from '../types' /** - * Checks whether the token is permittable, and caches the result on localStorage + * Check whether the token is permittable, and returns the permit info for it + * Tries to find it out from the pre-generated list + * If not found, tries to load the info from chain + * The result will be cached on localStorage if a final conclusion is found * * When it is, returned type is `{type: 'dai'|'permit', gasLimit: number} - * When it is not, returned type is `false` + * When it is not, returned type is `{type: 'unsupported'}` * When it is unknown, returned type is `undefined` - * */ -export function useIsTokenPermittable( - token: Nullish, - tradeType: Nullish -): IsTokenPermittableResult { +export function usePermitInfo(token: Nullish, tradeType: Nullish): IsTokenPermittableResult { const { chainId } = useWalletInfo() const { provider } = useWeb3React() @@ -46,7 +45,7 @@ export function useIsTokenPermittable( const isPermitEnabled = useIsPermitEnabled() && isPermitSupported const addPermitInfo = useAddPermitInfo() - const permitInfo = usePermitInfo(chainId, isPermitEnabled ? lowerCaseAddress : undefined) + const permitInfo = _usePermitInfo(chainId, isPermitEnabled ? lowerCaseAddress : undefined) const { permitInfo: preGeneratedInfo, isLoading: preGeneratedIsLoading } = usePreGeneratedPermitInfoForToken( isPermitEnabled ? token : undefined ) @@ -70,7 +69,6 @@ export function useIsTokenPermittable( } getTokenPermitInfo({ spender, tokenAddress: lowerCaseAddress, tokenName, chainId, provider }).then((result) => { - if ('error' in result) { // When error, we don't know. Log and don't cache. console.debug( @@ -109,14 +107,7 @@ function useAddPermitInfo() { return useSetAtom(addPermitInfoForTokenAtom) } -/** - * Returns whether a token is permittable. - * - * When it is, returned type is `{type: 'dai'|'permit', gasLimit: number}` - * When it is not, returned type is `false` - * When it is unknown, returned type is `undefined` - */ -function usePermitInfo(chainId: SupportedChainId, tokenAddress: string | undefined): IsTokenPermittableResult { +function _usePermitInfo(chainId: SupportedChainId, tokenAddress: string | undefined): IsTokenPermittableResult { const permittableTokens = useAtomValue(permittableTokensAtom) return useMemo(() => { diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts index ca2443dbd4..a007ae299b 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts @@ -4,10 +4,16 @@ import { Nullish } from 'types' import { TradeType } from 'modules/trade' -import { useIsTokenPermittable } from './useIsTokenPermittable' +import { usePermitInfo } from './usePermitInfo' +/** + * Whether the token supports permit for given trade type + * + * @param token + * @param tradeType + */ export function useTokenSupportsPermit(token: Nullish, tradeType: Nullish): boolean { - const permitInfo = useIsTokenPermittable(token, tradeType) + const permitInfo = usePermitInfo(token, tradeType) return !!permitInfo && permitInfo.type !== 'unsupported' } diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts index cea0c4a980..bc55f16c71 100644 --- a/apps/cowswap-frontend/src/modules/permit/index.ts +++ b/apps/cowswap-frontend/src/modules/permit/index.ts @@ -1,6 +1,6 @@ export * from './hooks/useAccountAgnosticPermitHookData' export * from './hooks/useGeneratePermitHook' -export * from './hooks/useIsTokenPermittable' +export * from './hooks/usePermitInfo' export * from './hooks/useOrdersPermitStatus' export * from './hooks/usePermitCompatibleTokens' export * from './hooks/useTokenSupportsPermit' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts index 13bc3ef6b6..c341019305 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts @@ -4,7 +4,7 @@ import { getWrappedToken } from '@cowprotocol/common-utils' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { TradeType as UniTradeType } from '@uniswap/sdk-core' -import { useGeneratePermitHook, useIsTokenPermittable } from 'modules/permit' +import { useGeneratePermitHook, usePermitInfo } from 'modules/permit' import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext' import { SwapFlowContext } from 'modules/swap/services/types' import { useEnoughBalanceAndAllowance } from 'modules/tokens' @@ -14,7 +14,7 @@ export function useSwapFlowContext(): SwapFlowContext | null { const contract = useGP2SettlementContract() const baseProps = useBaseFlowContextSetup() const sellCurrency = baseProps.trade?.inputAmount?.currency - const permitInfo = useIsTokenPermittable(sellCurrency, TradeType.SWAP) + const permitInfo = usePermitInfo(sellCurrency, TradeType.SWAP) const generatePermitHook = useGeneratePermitHook() const checkAllowanceAddress = GP_VAULT_RELAYER[baseProps.chainId || SupportedChainId.MAINNET] From 3656709615d3b5ff818bbba99aba51f93079485b Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Wed, 8 Nov 2023 17:47:26 +0000 Subject: [PATCH 05/27] feat: add utils fn isSupportedPermitInfo --- .../src/modules/limitOrders/services/tradeFlow/index.ts | 3 ++- .../src/modules/permit/hooks/usePermitCompatibleTokens.ts | 5 +++-- .../src/modules/permit/hooks/useTokenSupportsPermit.ts | 3 ++- .../src/modules/permit/utils/handlePermit.ts | 6 ++++-- .../src/modules/swap/services/swapFlow/index.ts | 3 ++- libs/permit-utils/src/index.ts | 1 + libs/permit-utils/src/utils/isSupportedPermitInfo.ts | 5 +++++ 7 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 libs/permit-utils/src/utils/isSupportedPermitInfo.ts diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts index f041295935..7b59c53fd3 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts @@ -1,4 +1,5 @@ import { OrderClass } from '@cowprotocol/cow-sdk' +import { isSupportedPermitInfo } from '@cowprotocol/permit-utils' import { Percent } from '@uniswap/sdk-core' import { PriceImpact } from 'legacy/hooks/usePriceImpact' @@ -57,7 +58,7 @@ export async function tradeFlow( try { logTradeFlow('LIMIT ORDER FLOW', 'STEP 2: handle permit') - if (permitInfo && permitInfo.type !== 'unsupported') beforePermit() + if (isSupportedPermitInfo(permitInfo)) beforePermit() postOrderParams.appData = await handlePermit({ permitInfo, diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/usePermitCompatibleTokens.ts b/apps/cowswap-frontend/src/modules/permit/hooks/usePermitCompatibleTokens.ts index bbcdd4ca2b..2fd0801779 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/usePermitCompatibleTokens.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/usePermitCompatibleTokens.ts @@ -1,6 +1,7 @@ import { useAtomValue } from 'jotai' import { useMemo, useRef } from 'react' +import { isSupportedPermitInfo } from '@cowprotocol/permit-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { useIsPermitEnabled } from 'common/hooks/featureFlags/useIsPermitEnabled' @@ -33,11 +34,11 @@ export function usePermitCompatibleTokens(): PermitCompatibleTokens { const permitCompatibleTokens: PermitCompatibleTokens = {} for (const address of Object.keys(preGeneratedPermitInfoRef.current)) { - permitCompatibleTokens[address.toLowerCase()] = !!preGeneratedPermitInfoRef.current[address] + permitCompatibleTokens[address.toLowerCase()] = isSupportedPermitInfo(preGeneratedPermitInfoRef.current[address]) } for (const address of Object.keys(localPermitInfoRef.current)) { - permitCompatibleTokens[address.toLowerCase()] = !!localPermitInfoRef.current[address] + permitCompatibleTokens[address.toLowerCase()] = isSupportedPermitInfo(localPermitInfoRef.current[address]) } return permitCompatibleTokens diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts index a007ae299b..993ccf4937 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useTokenSupportsPermit.ts @@ -1,3 +1,4 @@ +import { isSupportedPermitInfo } from '@cowprotocol/permit-utils' import { Currency } from '@uniswap/sdk-core' import { Nullish } from 'types' @@ -15,5 +16,5 @@ import { usePermitInfo } from './usePermitInfo' export function useTokenSupportsPermit(token: Nullish, tradeType: Nullish): boolean { const permitInfo = usePermitInfo(token, tradeType) - return !!permitInfo && permitInfo.type !== 'unsupported' + return isSupportedPermitInfo(permitInfo) } diff --git a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts index eeb7ed3d45..fb6fb58d65 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts @@ -1,3 +1,5 @@ +import { isSupportedPermitInfo, PermitInfo } from '@cowprotocol/permit-utils' + import { AppDataInfo, buildAppDataHooks, updateHooksOnAppData } from 'modules/appData' import { HandlePermitParams } from '../types' @@ -15,13 +17,13 @@ import { HandlePermitParams } from '../types' export async function handlePermit(params: HandlePermitParams): Promise { const { permitInfo, inputToken, account, appData, generatePermitHook } = params - if (permitInfo && permitInfo.type !== 'unsupported' && 'address' in inputToken) { + if (isSupportedPermitInfo(permitInfo) && 'address' in inputToken) { // permitInfo will only be set if there's NOT enough allowance const permitData = await generatePermitHook({ inputToken: { address: inputToken.address, name: inputToken.name }, account, - permitInfo, + permitInfo: permitInfo as PermitInfo, }) if (!permitData) { diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts index 46a552e6ec..a329f86e8d 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts @@ -1,3 +1,4 @@ +import { isSupportedPermitInfo } from '@cowprotocol/permit-utils' import { Percent } from '@uniswap/sdk-core' import { PriceImpact } from 'legacy/hooks/usePriceImpact' @@ -26,7 +27,7 @@ export async function swapFlow( try { logTradeFlow('SWAP FLOW', 'STEP 2: handle permit') - if (input.permitInfo && input.permitInfo.type !== 'unsupported') input.swapConfirmManager.requestPermitSignature() + if (isSupportedPermitInfo(input.permitInfo)) input.swapConfirmManager.requestPermitSignature() input.orderParams.appData = await handlePermit({ appData: input.orderParams.appData, diff --git a/libs/permit-utils/src/index.ts b/libs/permit-utils/src/index.ts index 454202edf5..06bb0ccd7e 100644 --- a/libs/permit-utils/src/index.ts +++ b/libs/permit-utils/src/index.ts @@ -2,5 +2,6 @@ export { checkIsCallDataAValidPermit } from './lib/checkIsCallDataAValidPermit' export { generatePermitHook } from './lib/generatePermitHook' export { getPermitUtilsInstance } from './lib/getPermitUtilsInstance' export { getTokenPermitInfo } from './lib/getTokenPermitInfo' +export { isSupportedPermitInfo } from './utils/isSupportedPermitInfo' export type { PermitHookData, PermitHookParams, PermitInfo, PermitType, GetTokenPermitIntoResult } from './types' diff --git a/libs/permit-utils/src/utils/isSupportedPermitInfo.ts b/libs/permit-utils/src/utils/isSupportedPermitInfo.ts new file mode 100644 index 0000000000..8e6af84495 --- /dev/null +++ b/libs/permit-utils/src/utils/isSupportedPermitInfo.ts @@ -0,0 +1,5 @@ +import { PermitInfo } from '../types' + +export function isSupportedPermitInfo(p: PermitInfo | undefined): boolean { + return !!p && p.type !== 'unsupported' +} From 737fe59ddff4b2f29d58413d9e78180674c2a3ca Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Wed, 8 Nov 2023 17:50:24 +0000 Subject: [PATCH 06/27] refactor: move inner private method getContract to external utils fn --- libs/permit-utils/src/utils/PermitProviderConnector.ts | 9 +++------ libs/permit-utils/src/utils/getContract.ts | 7 +++++++ 2 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 libs/permit-utils/src/utils/getContract.ts diff --git a/libs/permit-utils/src/utils/PermitProviderConnector.ts b/libs/permit-utils/src/utils/PermitProviderConnector.ts index fa0715cb9e..a430744194 100644 --- a/libs/permit-utils/src/utils/PermitProviderConnector.ts +++ b/libs/permit-utils/src/utils/PermitProviderConnector.ts @@ -4,18 +4,15 @@ import { AbiInput, AbiItem, EIP712TypedData, ProviderConnector } from '@1inch/pe import { defaultAbiCoder, ParamType } from '@ethersproject/abi' import { TypedDataField } from '@ethersproject/abstract-signer' import { BigNumber } from '@ethersproject/bignumber' -import { Contract, ContractInterface } from '@ethersproject/contracts' import { Wallet } from '@ethersproject/wallet' +import { getContract } from './getContract' + export class PermitProviderConnector implements ProviderConnector { constructor(private provider: JsonRpcProvider, private walletSigner?: Wallet | undefined) {} - private getContract(address: string, abi: ContractInterface, provider: JsonRpcProvider): Contract { - return new Contract(address, abi, provider) - } - contractEncodeABI(abi: AbiItem[], address: string | null, methodName: string, methodParams: unknown[]): string { - const contract = this.getContract(address || '', abi, this.provider) + const contract = getContract(address || '', abi, this.provider) return contract.interface.encodeFunctionData(methodName, methodParams) } diff --git a/libs/permit-utils/src/utils/getContract.ts b/libs/permit-utils/src/utils/getContract.ts new file mode 100644 index 0000000000..498f92b762 --- /dev/null +++ b/libs/permit-utils/src/utils/getContract.ts @@ -0,0 +1,7 @@ +import type { JsonRpcProvider } from '@ethersproject/providers' + +import { Contract, ContractInterface } from '@ethersproject/contracts' + +export function getContract(address: string, abi: ContractInterface, provider: JsonRpcProvider): Contract { + return new Contract(address, abi, provider) +} From dee9e9711ac3cb28eca460ae5193861e449e202d Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Wed, 8 Nov 2023 17:50:53 +0000 Subject: [PATCH 07/27] feat: add minimal erc20 `name` method abi --- libs/permit-utils/src/abi/erc20.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 libs/permit-utils/src/abi/erc20.json diff --git a/libs/permit-utils/src/abi/erc20.json b/libs/permit-utils/src/abi/erc20.json new file mode 100644 index 0000000000..2433c82123 --- /dev/null +++ b/libs/permit-utils/src/abi/erc20.json @@ -0,0 +1,16 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] From 4c8c262bf8f259d987d0234622f34b80f92daa93 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Wed, 8 Nov 2023 17:51:14 +0000 Subject: [PATCH 08/27] feat: add utils fn `getTokenName` --- libs/permit-utils/src/utils/getTokenName.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 libs/permit-utils/src/utils/getTokenName.ts diff --git a/libs/permit-utils/src/utils/getTokenName.ts b/libs/permit-utils/src/utils/getTokenName.ts new file mode 100644 index 0000000000..3581b81bcb --- /dev/null +++ b/libs/permit-utils/src/utils/getTokenName.ts @@ -0,0 +1,14 @@ +import type { JsonRpcProvider } from '@ethersproject/providers' + +import { getAddress } from '@ethersproject/address' + +import { getContract } from './getContract' + +import Erc20Abi from '../abi/erc20.json' + +export async function getTokenName(tokenAddress: string, chainId: number, provider: JsonRpcProvider): Promise { + const formattedAddress = getAddress(tokenAddress) + const erc20Contract = getContract(formattedAddress, Erc20Abi, provider) + + return erc20Contract.callStatic['name']() +} From 4a60c996ed5bcfb527321c40bd92132513c5ed71 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Wed, 8 Nov 2023 17:56:54 +0000 Subject: [PATCH 09/27] feat: fetch token name when fetching permit info --- .../src/lib/getTokenPermitInfo.ts | 27 ++++++++++++++----- libs/permit-utils/src/types.ts | 1 + 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index 0717aeaf18..0ecad2c63f 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -9,6 +9,7 @@ import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER, TOKENS_TO_SK import { GetTokenPermitInfoParams, GetTokenPermitIntoResult, PermitInfo, PermitType } from '../types' import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from '../utils/buildPermitCallData' import { getPermitDeadline } from '../utils/getPermitDeadline' +import { getTokenName } from '../utils/getTokenName' const EIP_2162_PERMIT_PARAMS = { value: DEFAULT_PERMIT_VALUE, @@ -45,12 +46,25 @@ export async function getTokenPermitInfo(params: GetTokenPermitInfoParams): Prom } async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams): Promise { - const { spender, tokenAddress, tokenName, chainId, provider } = params + const { spender, tokenAddress, tokenName: _tokenName, chainId, provider } = params const eip2612PermitUtils = getPermitUtilsInstance(chainId, provider) const owner = PERMIT_SIGNER.address + // TODO: potentially remove the need for the name input + let tokenName = _tokenName + + try { + tokenName = await getTokenName(tokenAddress, chainId, provider) + } catch (e) { + console.debug(`[checkTokenIsPermittable] Couldn't fetch token name from the contract for token ${tokenAddress}`, e) + } + + if (!tokenName) { + throw new Error(`[checkTokenIsPermittable] token name could not be determined for ${tokenAddress}`) + } + let nonce: number try { @@ -58,10 +72,10 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) } catch (e) { if (e === 'nonce not supported' || e.message === 'nonce is NaN') { console.debug(`[checkTokenIsPermittable] Not a permittable token ${tokenAddress}`, e?.message || e) - // Here we know it's not supported, return false + // Here we know it's not supported, return unsupported // See https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L309 // and https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L325 - return UNSUPPORTED + return { ...UNSUPPORTED, name: tokenName } } console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${tokenAddress}`, e) @@ -129,14 +143,14 @@ type EstimateParams = BaseParams & { } async function estimateTokenPermit(params: EstimateParams): Promise { - const { provider, chainId, walletAddress, tokenAddress, type, version } = params + const { provider, chainId, walletAddress, tokenAddress, tokenName, type, version } = params const getCallDataFn = type === 'eip-2612' ? getEip2612CallData : getDaiLikeCallData const data = await getCallDataFn(params) if (!data) { - return UNSUPPORTED + return { ...UNSUPPORTED, name: tokenName } } const estimatedGas = await provider.estimateGas({ @@ -151,8 +165,9 @@ async function estimateTokenPermit(params: EstimateParams): Promise { diff --git a/libs/permit-utils/src/types.ts b/libs/permit-utils/src/types.ts index 1e70f0efd9..755a0cef45 100644 --- a/libs/permit-utils/src/types.ts +++ b/libs/permit-utils/src/types.ts @@ -6,6 +6,7 @@ export type PermitType = 'dai-like' | 'eip-2612' | 'unsupported' export type PermitInfo = { type: PermitType + name?: string version?: string | undefined // Some tokens have it different than `1`, and won't work without it } From b7e7674c1ab00755fa988ccfc49e56c4ac5dafdc Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Wed, 8 Nov 2023 17:57:49 +0000 Subject: [PATCH 10/27] feat: make tokenName optional on GetTokenPermitInfoParams --- apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts | 2 +- libs/permit-utils/src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts b/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts index 433b1dde62..5ed3fab1ea 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts @@ -37,7 +37,7 @@ export function usePermitInfo(token: Nullish, tradeType: Nullish Date: Wed, 8 Nov 2023 17:58:18 +0000 Subject: [PATCH 11/27] feat: migrate preGenerated permit info to new format --- .../permit/hooks/usePreGeneratedPermitInfo.ts | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/usePreGeneratedPermitInfo.ts b/apps/cowswap-frontend/src/modules/permit/hooks/usePreGeneratedPermitInfo.ts index 3ea379ee01..856515fa8e 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/usePreGeneratedPermitInfo.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/usePreGeneratedPermitInfo.ts @@ -21,9 +21,33 @@ export function usePreGeneratedPermitInfo(): { const { data, isLoading } = useSWR( url, - (url: string): Promise> => fetch(url).then((r) => r.json()), + (url: string): Promise> => + fetch(url) + .then((r) => r.json()) + .then(migrateData), { ...SWR_NO_REFRESH_OPTIONS, fallbackData: {} } ) return { allPermitInfo: data, isLoading } } + +type OldPermitInfo = PermitInfo | false + +const UNSUPPORTED: PermitInfo = { type: 'unsupported' } + +/** + * Handles data migration from former way of storing unsupported tokens to the new one + */ +function migrateData(data: Record): Record { + const migrated: Record = {} + + for (const [k, v] of Object.entries(data)) { + if (v === false) { + migrated[k] = UNSUPPORTED + } else { + migrated[k] = v + } + } + + return migrated +} From 7c76c9508156c321217344e4e8199615ac413030 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Thu, 9 Nov 2023 14:19:52 +0000 Subject: [PATCH 12/27] chore: more tokenName optional changes --- .../permit/hooks/useCheckHasValidPendingPermit.ts | 2 +- .../src/lib/checkIsCallDataAValidPermit.ts | 11 +++++++++-- libs/permit-utils/src/lib/generatePermitHook.ts | 6 +++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts index b32c0410ad..045e31ad8f 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts @@ -64,7 +64,7 @@ async function checkHasValidPendingPermit( const eip2162Utils = getPermitUtilsInstance(chainId, provider, order.owner) const tokenAddress = order.inputToken.address - const tokenName = order.inputToken.name || tokenAddress + const tokenName = order.inputToken.name const checkedHooks = await Promise.all( preHooks.map(({ callData }) => diff --git a/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts b/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts index c03145800c..f249bfcfd1 100644 --- a/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts +++ b/libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts @@ -8,14 +8,21 @@ export async function checkIsCallDataAValidPermit( chainId: number, eip2162Utils: Eip2612PermitUtils, tokenAddress: string, - tokenName: string, + _tokenName: string | undefined, callData: string, - { version, type }: PermitInfo + { version, type, name }: PermitInfo ): Promise { + // TODO: take name only from PermitInfo + const tokenName = name || _tokenName + if (type === 'unsupported') { return false } + if (!tokenName) { + throw new Error(`No token name for ${tokenAddress}`) + } + const params = { chainId, tokenName: fixTokenName(tokenName), tokenAddress, callData, version } let recoverPermitOwnerPromise: Promise | undefined = undefined diff --git a/libs/permit-utils/src/lib/generatePermitHook.ts b/libs/permit-utils/src/lib/generatePermitHook.ts index 0e1da7c9fe..f7ecf08e2a 100644 --- a/libs/permit-utils/src/lib/generatePermitHook.ts +++ b/libs/permit-utils/src/lib/generatePermitHook.ts @@ -37,12 +37,16 @@ async function generatePermitHookRaw(params: PermitHookParams): Promise Date: Thu, 9 Nov 2023 14:20:47 +0000 Subject: [PATCH 13/27] chore: add TODOs --- libs/permit-utils/src/lib/generatePermitHook.ts | 1 + libs/permit-utils/src/types.ts | 2 ++ libs/permit-utils/src/utils/fixTokenName.ts | 1 + 3 files changed, 4 insertions(+) diff --git a/libs/permit-utils/src/lib/generatePermitHook.ts b/libs/permit-utils/src/lib/generatePermitHook.ts index f7ecf08e2a..f80caf1d0c 100644 --- a/libs/permit-utils/src/lib/generatePermitHook.ts +++ b/libs/permit-utils/src/lib/generatePermitHook.ts @@ -37,6 +37,7 @@ async function generatePermitHookRaw(params: PermitHookParams): Promise Date: Thu, 9 Nov 2023 14:33:20 +0000 Subject: [PATCH 14/27] refactor: return error rather than throwing --- libs/permit-utils/src/lib/getTokenPermitInfo.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index 0ecad2c63f..b8f846a946 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -62,7 +62,8 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) } if (!tokenName) { - throw new Error(`[checkTokenIsPermittable] token name could not be determined for ${tokenAddress}`) + const error = `Token name could not be determined for ${tokenAddress}` + return { error } } let nonce: number From 629fac918f5de37e3c7174096892583db3691099 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Thu, 9 Nov 2023 18:20:00 +0000 Subject: [PATCH 15/27] chore: bump permit-utils package version --- libs/permit-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/permit-utils/package.json b/libs/permit-utils/package.json index c9f38ccce8..7ac447baca 100644 --- a/libs/permit-utils/package.json +++ b/libs/permit-utils/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/permit-utils", - "version": "0.0.1-RC.1", + "version": "0.0.1-RC.2", "type": "module", "dependencies": { "ethers": "^5.7.2", From 4d2d666a4e2da9634372c9461d4f0bc941c61402 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Thu, 9 Nov 2023 18:29:41 +0000 Subject: [PATCH 16/27] chore: bump permittableTokens atom version to v2 --- .../src/modules/permit/state/permittableTokensAtom.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts b/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts index aeebdf1716..c3b0727ffb 100644 --- a/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts +++ b/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts @@ -9,10 +9,9 @@ import { AddPermitTokenParams, PermittableTokens } from '../types' * Atom that stores the permittable tokens info for each chain on localStorage. * It's meant to be shared across different tabs, thus no special storage handling. * - * Contains either the permit info with `type` and `gasLimit` when supported or - * `false` when not supported + * Contains either the permit info for every token checked locally */ -export const permittableTokensAtom = atomWithStorage('permittableTokens:v1', { +export const permittableTokensAtom = atomWithStorage('permittableTokens:v2', { [SupportedChainId.MAINNET]: {}, [SupportedChainId.GOERLI]: {}, [SupportedChainId.GNOSIS_CHAIN]: {}, From 39db8a668092a8e694c5001e4349988bcd5365c1 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Thu, 9 Nov 2023 18:39:23 +0000 Subject: [PATCH 17/27] refactor: use isSupportedPermitInfo in a few places --- .../permit/hooks/useAccountAgnosticPermitHookData.ts | 4 ++-- .../src/modules/permit/hooks/useGeneratePermitHook.ts | 9 +++++++-- libs/permit-utils/src/lib/generatePermitHook.ts | 3 ++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts index e94c468987..d1451c5091 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' -import { PermitHookData } from '@cowprotocol/permit-utils' +import { isSupportedPermitInfo, PermitHookData } from '@cowprotocol/permit-utils' import { useDerivedTradeState } from 'modules/trade' @@ -44,7 +44,7 @@ function useGeneratePermitHookParams(): GeneratePermitHookParams | undefined { const permitInfo = usePermitInfo(inputCurrency, tradeType) return useSafeMemo(() => { - if (!inputCurrency || !('address' in inputCurrency) || !permitInfo || permitInfo.type === 'unsupported') + if (!inputCurrency || !('address' in inputCurrency) || !permitInfo || !isSupportedPermitInfo(permitInfo)) return undefined return { diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts index 7b9a7541ef..2110d9f934 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts @@ -2,7 +2,12 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useCallback } from 'react' import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' -import { generatePermitHook, getPermitUtilsInstance, PermitHookData } from '@cowprotocol/permit-utils' +import { + generatePermitHook, + getPermitUtilsInstance, + isSupportedPermitInfo, + PermitHookData, +} from '@cowprotocol/permit-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' @@ -38,7 +43,7 @@ export function useGeneratePermitHook(): GeneratePermitHook { async (params: GeneratePermitHookParams): Promise => { const { inputToken, account, permitInfo } = params - if (!provider || permitInfo.type === 'unsupported') { + if (!provider || !isSupportedPermitInfo(permitInfo)) { return } diff --git a/libs/permit-utils/src/lib/generatePermitHook.ts b/libs/permit-utils/src/lib/generatePermitHook.ts index f80caf1d0c..d8e36c8ab9 100644 --- a/libs/permit-utils/src/lib/generatePermitHook.ts +++ b/libs/permit-utils/src/lib/generatePermitHook.ts @@ -4,6 +4,7 @@ import { DEFAULT_PERMIT_GAS_LIMIT, DEFAULT_PERMIT_VALUE, PERMIT_SIGNER } from '. import { PermitHookData, PermitHookParams } from '../types' import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from '../utils/buildPermitCallData' import { getPermitDeadline } from '../utils/getPermitDeadline' +import { isSupportedPermitInfo } from '../utils/isSupportedPermitInfo' const REQUESTS_CACHE: { [permitKey: string]: Promise } = {} @@ -40,7 +41,7 @@ async function generatePermitHookRaw(params: PermitHookParams): Promise Date: Tue, 14 Nov 2023 11:06:26 +0000 Subject: [PATCH 18/27] chore: do a type guard in the helper fn so there's no need for casting --- .../cowswap-frontend/src/modules/permit/utils/handlePermit.ts | 4 ++-- libs/permit-utils/src/utils/isSupportedPermitInfo.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts index fb6fb58d65..be16388c94 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts @@ -1,4 +1,4 @@ -import { isSupportedPermitInfo, PermitInfo } from '@cowprotocol/permit-utils' +import { isSupportedPermitInfo } from '@cowprotocol/permit-utils' import { AppDataInfo, buildAppDataHooks, updateHooksOnAppData } from 'modules/appData' @@ -23,7 +23,7 @@ export async function handlePermit(params: HandlePermitParams): Promise Date: Tue, 14 Nov 2023 15:25:40 +0000 Subject: [PATCH 19/27] chore: return error when name fetching fails due to network issues --- libs/permit-utils/src/lib/getTokenPermitInfo.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index b8f846a946..b2f6995909 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -58,6 +58,10 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) try { tokenName = await getTokenName(tokenAddress, chainId, provider) } catch (e) { + if (e?.error?.serverError?.code === 'ETIMEDOUT' && !tokenName) { + // Network issue or another temporary failure, return error + return { error: `Failed to fetch token name from contract. RPC connection error` } + } console.debug(`[checkTokenIsPermittable] Couldn't fetch token name from the contract for token ${tokenAddress}`, e) } From d70baf1a91a40d5b786fe62de93a59623ddedf0e Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 14 Nov 2023 15:26:47 +0000 Subject: [PATCH 20/27] chore: identify earlier when token is not dai-like and return received error --- libs/permit-utils/src/lib/getTokenPermitInfo.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index b2f6995909..e8800999ad 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -122,6 +122,12 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) // Not eip-2612, try dai-like console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${tokenAddress}`, e) try { + const isDaiLike = await isDaiLikeTypeHash(tokenAddress, eip2612PermitUtils) + + if (!isDaiLike) { + return { error: e.message || e.toString() } + } + return await estimateTokenPermit({ ...baseParams, type: 'dai-like', provider }) } catch (e) { // Not dai-like either, return error @@ -194,6 +200,12 @@ async function getEip2612CallData(params: BaseParams): Promise { }) } +async function isDaiLikeTypeHash(tokenAddress: string, eip2612PermitUtils: Eip2612PermitUtils): Promise { + const permitTypeHash = await eip2612PermitUtils.getPermitTypeHash(tokenAddress) + + return permitTypeHash === DAI_LIKE_PERMIT_TYPEHASH +} + async function getDaiLikeCallData(params: BaseParams): Promise { const { eip2612PermitUtils, tokenAddress, walletAddress, spender, nonce, chainId, tokenName, version } = params From 7dfb0cdcb132ff695c698f4ad0e6a65c113e479d Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 14 Nov 2023 15:27:11 +0000 Subject: [PATCH 21/27] chore: only log debug msg if not dai-like --- libs/permit-utils/src/lib/getTokenPermitInfo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index e8800999ad..d55e6707bf 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -120,11 +120,11 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) return await estimateTokenPermit({ ...baseParams, type: 'eip-2612', provider }) } catch (e) { // Not eip-2612, try dai-like - console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${tokenAddress}`, e) try { const isDaiLike = await isDaiLikeTypeHash(tokenAddress, eip2612PermitUtils) if (!isDaiLike) { + console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${tokenAddress}`, e) return { error: e.message || e.toString() } } From 72f95b703cec1e89bdc865516f7ff6ebce6d55de Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 14 Nov 2023 15:27:48 +0000 Subject: [PATCH 22/27] chore: mark some known error types as permanent errors --- libs/permit-utils/src/lib/getTokenPermitInfo.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index d55e6707bf..519ec16d52 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -125,6 +125,15 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) if (!isDaiLike) { console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${tokenAddress}`, e) + + // These might be supported, as they have nonces, but we don't know why the permit call fails + // TODO: further investigate this kind of token + // For now mark them as unsupported and don't check it again + if (/invalid signature/.test(e) || e?.code === 'UNPREDICTABLE_GAS_LIMIT') { + return { ...UNSUPPORTED, name: tokenName } + } + + // Maybe a temporary failure return { error: e.message || e.toString() } } From f79e97f52cf6bfd684fbaaa0cd89902fc27cf86c Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 14 Nov 2023 15:46:00 +0000 Subject: [PATCH 23/27] chore: log also tokenName when possible --- .../src/lib/getTokenPermitInfo.ts | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index 519ec16d52..6edb2ccb67 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -62,7 +62,10 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) // Network issue or another temporary failure, return error return { error: `Failed to fetch token name from contract. RPC connection error` } } - console.debug(`[checkTokenIsPermittable] Couldn't fetch token name from the contract for token ${tokenAddress}`, e) + console.debug( + `[checkTokenIsPermittable] Couldn't fetch token name from the contract for token ${tokenAddress}, using provided '${tokenName}'`, + e + ) } if (!tokenName) { @@ -76,13 +79,13 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) nonce = await eip2612PermitUtils.getTokenNonce(tokenAddress, owner) } catch (e) { if (e === 'nonce not supported' || e.message === 'nonce is NaN') { - console.debug(`[checkTokenIsPermittable] Not a permittable token ${tokenAddress}`, e?.message || e) + console.debug(`[checkTokenIsPermittable] Not a permittable token ${tokenAddress} - ${tokenName}`, e?.message || e) // Here we know it's not supported, return unsupported // See https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L309 // and https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L325 return { ...UNSUPPORTED, name: tokenName } } - console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${tokenAddress}`, e) + console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${tokenAddress} - ${tokenName}`, e) // Otherwise, it might have been a network issue or another temporary failure, return error return { error: e.message || e.toString() } @@ -100,7 +103,7 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) version = await eip2612PermitUtils.getTokenVersion(tokenAddress) } catch (e) { // Not a problem, we can (try to) continue without it, and will default to `1` (part of the 1inch lib) - console.debug(`[checkTokenIsPermittable] Failed to get version for ${tokenAddress}`, e) + console.debug(`[checkTokenIsPermittable] Failed to get version for ${tokenAddress} - ${tokenName}`, e) } } @@ -124,23 +127,32 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) const isDaiLike = await isDaiLikeTypeHash(tokenAddress, eip2612PermitUtils) if (!isDaiLike) { - console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${tokenAddress}`, e) - // These might be supported, as they have nonces, but we don't know why the permit call fails // TODO: further investigate this kind of token // For now mark them as unsupported and don't check it again if (/invalid signature/.test(e) || e?.code === 'UNPREDICTABLE_GAS_LIMIT') { + console.debug( + `[checkTokenIsPermittable] Token ${tokenAddress} - ${tokenName} might be permittable, but it's not supported for now. Reason:`, + e?.reason + ) return { ...UNSUPPORTED, name: tokenName } } // Maybe a temporary failure + console.debug( + `[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${tokenAddress} - ${tokenName}`, + e + ) return { error: e.message || e.toString() } } return await estimateTokenPermit({ ...baseParams, type: 'dai-like', provider }) } catch (e) { // Not dai-like either, return error - console.debug(`[checkTokenIsPermittable] Failed to estimate dai-like permit for ${tokenAddress}`, e) + console.debug( + `[checkTokenIsPermittable] Failed to estimate dai-like permit for ${tokenAddress} - ${tokenName}`, + e + ) return { error: e.message || e.toString() } } } From 4b25698ee0de85e27aad0313ed9dc6188c318927 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Tue, 14 Nov 2023 16:56:49 +0000 Subject: [PATCH 24/27] chore: use a regex to catch connection issues --- libs/permit-utils/src/lib/getTokenPermitInfo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/permit-utils/src/lib/getTokenPermitInfo.ts b/libs/permit-utils/src/lib/getTokenPermitInfo.ts index 6edb2ccb67..6ef486b717 100644 --- a/libs/permit-utils/src/lib/getTokenPermitInfo.ts +++ b/libs/permit-utils/src/lib/getTokenPermitInfo.ts @@ -58,7 +58,7 @@ async function actuallyCheckTokenIsPermittable(params: GetTokenPermitInfoParams) try { tokenName = await getTokenName(tokenAddress, chainId, provider) } catch (e) { - if (e?.error?.serverError?.code === 'ETIMEDOUT' && !tokenName) { + if (/ETIMEDOUT/.test(e) && !tokenName) { // Network issue or another temporary failure, return error return { error: `Failed to fetch token name from contract. RPC connection error` } } From 77471bfe13081d60185498c19a79e9c4fb85ca8d Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Thu, 16 Nov 2023 10:13:39 +0000 Subject: [PATCH 25/27] chore: use const for default obj return to avoid re-renders --- .../src/modules/permit/hooks/usePermitInfo.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts b/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts index 5ed3fab1ea..636b006b00 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/usePermitInfo.ts @@ -4,7 +4,7 @@ import { useEffect, useMemo } from 'react' import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' import { getIsNativeToken, getWrappedToken } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { getTokenPermitInfo } from '@cowprotocol/permit-utils' +import { getTokenPermitInfo, PermitInfo } from '@cowprotocol/permit-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' @@ -21,6 +21,8 @@ import { ORDER_TYPE_SUPPORTS_PERMIT } from '../const' import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/permittableTokensAtom' import { IsTokenPermittableResult } from '../types' +const UNSUPPORTED: PermitInfo = { type: 'unsupported', name: 'native' } + /** * Check whether the token is permittable, and returns the permit info for it * Tries to find it out from the pre-generated list @@ -94,7 +96,7 @@ export function usePermitInfo(token: Nullish, tradeType: Nullish Date: Fri, 17 Nov 2023 09:13:26 +0000 Subject: [PATCH 26/27] refactor: remove redundant check. It's covered by isSupportedPermitInfo --- .../modules/permit/hooks/useAccountAgnosticPermitHookData.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts index d1451c5091..a4e2c94754 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -44,8 +44,7 @@ function useGeneratePermitHookParams(): GeneratePermitHookParams | undefined { const permitInfo = usePermitInfo(inputCurrency, tradeType) return useSafeMemo(() => { - if (!inputCurrency || !('address' in inputCurrency) || !permitInfo || !isSupportedPermitInfo(permitInfo)) - return undefined + if (!inputCurrency || !('address' in inputCurrency) || !isSupportedPermitInfo(permitInfo)) return undefined return { inputToken: { address: inputCurrency.address, name: inputCurrency.name }, From 35fbc52848c7c871415e7e1ae195dda7129e054c Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Fri, 17 Nov 2023 09:14:36 +0000 Subject: [PATCH 27/27] chore: set permit-utils version to 0.0.1 --- libs/permit-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/permit-utils/package.json b/libs/permit-utils/package.json index 7ac447baca..4a27ce06db 100644 --- a/libs/permit-utils/package.json +++ b/libs/permit-utils/package.json @@ -1,6 +1,6 @@ { "name": "@cowprotocol/permit-utils", - "version": "0.0.1-RC.2", + "version": "0.0.1", "type": "module", "dependencies": { "ethers": "^5.7.2",