diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts
deleted file mode 100644
index f62a4120e4..0000000000
--- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { useMemo } from 'react'
-
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-
-import { BalancesAndAllowances } from 'modules/tokens'
-
-import { ParsedOrder } from 'utils/orderUtils/parseOrder'
-
-import { OrdersTableList } from './useOrdersTableList'
-
-import { getOrderParams } from '../../../utils/getOrderParams'
-import { isParsedOrder } from '../../../utils/orderTableGroupUtils'
-
-export function useGetOrdersToCheckPendingPermit(
- ordersList: OrdersTableList,
- chainId: SupportedChainId,
- balancesAndAllowances: BalancesAndAllowances
-) {
- return useMemo(() => {
- // Pick only the pending orders
- return ordersList.pending.reduce((acc: ParsedOrder[], item) => {
- // Only do it for regular orders (not TWAP)
- if (isParsedOrder(item)) {
- const { hasEnoughAllowance } = getOrderParams(chainId, balancesAndAllowances, item)
-
- // Only if the order has not enough allowance
- if (hasEnoughAllowance === false) {
- acc.push(item)
- }
- }
- return acc
- }, [])
- }, [balancesAndAllowances, chainId, ordersList.pending])
-}
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx
index 229753b6db..509dd0ff75 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx
@@ -12,7 +12,7 @@ import { Order } from 'legacy/state/orders/actions'
import { useInjectedWidgetParams } from 'modules/injectedWidget'
import { pendingOrdersPricesAtom } from 'modules/orders/state/pendingOrdersPricesAtom'
import { useGetSpotPrice } from 'modules/orders/state/spotPricesAtom'
-import { PendingPermitUpdater, useGetOrdersPermitStatus } from 'modules/permit'
+import { BalancesAndAllowances } from 'modules/tokens'
import { useCancelOrder } from 'common/hooks/useCancelOrder'
import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity'
@@ -21,12 +21,10 @@ import { useNavigate } from 'common/hooks/useNavigate'
import { CancellableOrder } from 'common/utils/isOrderCancellable'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
-import { useGetOrdersToCheckPendingPermit } from './hooks/useGetOrdersToCheckPendingPermit'
import { OrdersTableList, useOrdersTableList } from './hooks/useOrdersTableList'
import { useOrdersTableTokenApprove } from './hooks/useOrdersTableTokenApprove'
import { useValidatePageUrlParams } from './hooks/useValidatePageUrlParams'
-import { BalancesAndAllowances } from '../../../tokens'
import { OPEN_TAB, ORDERS_TABLE_TABS } from '../../const/tabs'
import { OrdersTableContainer } from '../../pure/OrdersTableContainer'
import { OrderActions } from '../../pure/OrdersTableContainer/types'
@@ -81,7 +79,6 @@ export function OrdersTableWidget({
const getSpotPrice = useGetSpotPrice()
const selectReceiptOrder = useSelectReceiptOrder()
const isSafeViaWc = useIsSafeViaWc()
- const ordersPermitStatus = useGetOrdersPermitStatus()
const injectedWidgetParams = useInjectedWidgetParams()
const { currentTabId, currentPageNumber } = useMemo(() => {
@@ -163,11 +160,8 @@ export function OrdersTableWidget({
useValidatePageUrlParams(orders.length, currentTabId, currentPageNumber)
- const ordersToCheckPendingPermit = useGetOrdersToCheckPendingPermit(ordersList, chainId, balancesAndAllowances)
-
return (
<>
-
{children}
{isOpenOrdersTab && orders.length && }
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx
index 97cc538512..8bd52a248f 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx
@@ -143,7 +143,6 @@ export interface OrderRowProps {
orderParams: OrderParams
onClick: Command
orderActions: OrderActions
- hasValidPendingPermit?: boolean | undefined
children?: JSX.Element
}
@@ -160,7 +159,6 @@ export function OrderRow({
prices,
spotPrice,
children,
- hasValidPendingPermit,
}: OrderRowProps) {
const { buyAmount, rateInfoParams, hasEnoughAllowance, hasEnoughBalance, chainId } = orderParams
const { creationTime, expirationTime, status } = order
@@ -173,10 +171,10 @@ export function OrderRow({
}, [orderActions, order])
const alternativeOrderModalContext = useMemo(
() => orderActions.getAlternativeOrderModalContext(order),
- [order, orderActions]
+ [order, orderActions],
)
- const withAllowanceWarning = hasEnoughAllowance === false && hasValidPendingPermit === false
+ const withAllowanceWarning = hasEnoughAllowance === false
const withWarning =
(hasEnoughBalance === false || withAllowanceWarning) &&
// show the warning only for pending and scheduled orders
@@ -401,7 +399,7 @@ export function OrderRow({
function usePricesDifference(
prices: OrderRowProps['prices'],
spotPrice: OrderRowProps['spotPrice'],
- isInverted: boolean
+ isInverted: boolean,
): PriceDifference {
const { estimatedExecutionPrice } = prices || {}
@@ -415,13 +413,13 @@ function usePricesDifference(
*/
function useFeeAmountDifference(
{ inputCurrencyAmount }: OrderRowProps['orderParams']['rateInfoParams'],
- prices: OrderRowProps['prices']
+ prices: OrderRowProps['prices'],
): Percent | undefined {
const { feeAmount } = prices || {}
return useSafeMemo(
() => calculatePercentageInRelationToReference({ value: feeAmount, reference: inputCurrencyAmount }),
- [feeAmount, inputCurrencyAmount]
+ [feeAmount, inputCurrencyAmount],
)
}
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx
index c11b087065..d2051d80d7 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx
@@ -13,7 +13,6 @@ import styled from 'styled-components/macro'
import { PendingOrdersPrices } from 'modules/orders/state/pendingOrdersPricesAtom'
import { SpotPricesKeyParams } from 'modules/orders/state/spotPricesAtom'
-import { OrdersPermitStatus } from 'modules/permit'
import { BalancesAndAllowances } from 'modules/tokens'
import { ordersTableFeatures } from 'common/constants/featureFlags'
@@ -200,7 +199,6 @@ export interface OrdersTableProps {
balancesAndAllowances: BalancesAndAllowances
getSpotPrice: (params: SpotPricesKeyParams) => Price | null
orderActions: OrderActions
- ordersPermitStatus: OrdersPermitStatus
}
export function OrdersTable({
@@ -214,7 +212,6 @@ export function OrdersTable({
getSpotPrice,
orderActions,
currentPageNumber,
- ordersPermitStatus,
}: OrdersTableProps) {
const buildOrdersTableUrl = useGetBuildOrdersTableUrl()
const [isRateInverted, setIsRateInverted] = useState(false)
@@ -234,11 +231,14 @@ export function OrdersTable({
const selectedOrdersMap = useMemo(() => {
if (!selectedOrders) return {}
- return selectedOrders.reduce((acc, val) => {
- acc[val.id] = true
+ return selectedOrders.reduce(
+ (acc, val) => {
+ acc[val.id] = true
- return acc
- }, {} as { [key: string]: true })
+ return acc
+ },
+ {} as { [key: string]: true },
+ )
}, [selectedOrders])
// Explainer banner for orders
@@ -258,7 +258,7 @@ export function OrdersTable({
const cancellableOrders = useMemo(
() => ordersPage.filter((item) => isOrderOffChainCancellable(getParsedOrderFromTableItem(item))),
- [ordersPage]
+ [ordersPage],
)
const allOrdersSelected = useMemo(() => {
@@ -294,7 +294,7 @@ export function OrdersTable({
type="checkbox"
onChange={(event) =>
orderActions.toggleOrdersForCancellation(
- event.target.checked ? tableItemsToOrders(ordersPage) : []
+ event.target.checked ? tableItemsToOrders(ordersPage) : [],
)
}
/>
@@ -408,8 +408,6 @@ export function OrdersTable({
const orderParams = getOrderParams(chainId, balancesAndAllowances, order)
- const hasValidPendingPermit = ordersPermitStatus[order.id]
-
return (
orderActions.selectReceiptOrder(order)}
- hasValidPendingPermit={hasValidPendingPermit}
/>
)
} else {
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx
index ac58ea8d83..831a9a3420 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx
@@ -74,7 +74,6 @@ export default (
getSpotPrice={() => null}
orderActions={orderActions}
orderType={TabOrderTypes.LIMIT}
- ordersPermitStatus={{}}
injectedWidgetParams={{}}
/>
)
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx
index eaa804284d..69cd2c3c78 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx
@@ -197,7 +197,6 @@ export function OrdersTableContainer({
children,
orderType,
pendingActivities,
- ordersPermitStatus,
injectedWidgetParams,
}: OrdersProps) {
const content = () => {
@@ -275,7 +274,6 @@ export function OrdersTableContainer({
balancesAndAllowances={balancesAndAllowances}
getSpotPrice={getSpotPrice}
orderActions={orderActions}
- ordersPermitStatus={ordersPermitStatus}
/>
)
}
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/utils/getOrderParams.ts b/apps/cowswap-frontend/src/modules/ordersTable/utils/getOrderParams.ts
index bb800a9232..a384d35583 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/utils/getOrderParams.ts
+++ b/apps/cowswap-frontend/src/modules/ordersTable/utils/getOrderParams.ts
@@ -6,6 +6,7 @@ import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { BalancesAndAllowances } from 'modules/tokens'
import { RateInfoParams } from 'common/pure/RateInfo'
+import { getOrderPermitAmount } from 'utils/orderUtils/getOrderPermitAmount'
import { ParsedOrder } from 'utils/orderUtils/parseOrder'
export interface OrderParams {
@@ -22,10 +23,12 @@ const PERCENTAGE_FOR_PARTIAL_FILLS = new Percent(5, 10000) // 0.05%
export function getOrderParams(
chainId: SupportedChainId,
balancesAndAllowances: BalancesAndAllowances,
- order: ParsedOrder
+ order: ParsedOrder,
): OrderParams {
+ const isOrderAtLeastOnceFilled = order.executionData.filledAmount.gt(0)
const sellAmount = CurrencyAmount.fromRawAmount(order.inputToken, order.sellAmount)
const buyAmount = CurrencyAmount.fromRawAmount(order.outputToken, order.buyAmount)
+ const permitAmount = getOrderPermitAmount(chainId, order) || undefined
const rateInfoParams: RateInfoParams = {
chainId,
@@ -43,7 +46,8 @@ export function getOrderParams(
partiallyFillable: order.partiallyFillable,
sellAmount,
balance,
- allowance,
+ // If the order has been filled at least once, we should not consider the permit amount
+ allowance: isOrderAtLeastOnceFilled ? getBiggerAmount(allowance, permitAmount) : allowance,
})
return {
@@ -73,3 +77,10 @@ function _hasEnoughBalanceAndAllowance(params: {
return { hasEnoughBalance, hasEnoughAllowance }
}
+
+function getBiggerAmount(a: BigNumber | undefined, b: BigNumber | undefined): BigNumber | undefined {
+ if (!a) return b
+ if (!b) return a
+
+ return a.gt(b) ? a : b
+}
diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts
deleted file mode 100644
index 05708c6504..0000000000
--- a/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import { useCallback } from 'react'
-
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-import { checkIsCallDataAValidPermit, getPermitUtilsInstance, PermitInfo } from '@cowprotocol/permit-utils'
-import { useWalletInfo } from '@cowprotocol/wallet'
-import { useWalletProvider } from '@cowprotocol/wallet-provider'
-import { Web3Provider } from '@ethersproject/providers'
-
-import { getAppDataHooks } from 'modules/appData'
-
-import { ParsedOrder } from 'utils/orderUtils/parseOrder'
-
-import { useGetPermitInfo } from './useGetPermitInfo'
-import { usePreGeneratedPermitInfo } from './usePreGeneratedPermitInfo'
-
-import { CheckHasValidPendingPermit } from '../types'
-
-/**
- * TODO: there are some duplicated code between this and usePermitInfo.ts
- */
-export function useCheckHasValidPendingPermit(): CheckHasValidPendingPermit {
- const { chainId } = useWalletInfo()
- const provider = useWalletProvider()
- const getPermitInfo = useGetPermitInfo(chainId)
- const { allPermitInfo, isLoading: preGeneratedIsLoading } = usePreGeneratedPermitInfo()
-
- return useCallback(
- async (order: ParsedOrder): Promise => {
- if (!provider || preGeneratedIsLoading) {
- // Missing required params, we can't tell
- return undefined
- }
-
- const tokenAddress = order.inputToken.address.toLowerCase()
-
- const permitInfo = getPermitInfo(tokenAddress)
- const preGeneratedPermitInfo = allPermitInfo[tokenAddress]
-
- // If the token is not supported, we can say that there is no valid permit
- if (preGeneratedPermitInfo?.type === 'unsupported') {
- return false
- }
-
- if (permitInfo === undefined) {
- // Missing permit info, we can't tell
- return undefined
- }
-
- return checkHasValidPendingPermit(order, provider, chainId, permitInfo)
- },
- [chainId, getPermitInfo, provider, preGeneratedIsLoading, allPermitInfo]
- )
-}
-
-async function checkHasValidPendingPermit(
- order: ParsedOrder,
- provider: Web3Provider,
- chainId: SupportedChainId,
- permitInfo: PermitInfo
-): Promise {
- const { fullAppData, partiallyFillable, executionData } = order
- const preHooks = getAppDataHooks(fullAppData)?.pre
-
- if (
- // No hooks === no permit
- !preHooks ||
- // Permit is only executed for partially fillable orders in the first execution
- // Thus, if there is any amount executed, partiallyFillable permit is no longer valid
- (partiallyFillable && executionData.filledAmount.gt('0')) ||
- // Permit not supported, shouldn't even get this far
- !permitInfo
- ) {
- // These cases we know for sure permit isn't valid or there is no permit
- return false
- }
-
- const eip2162Utils = getPermitUtilsInstance(chainId, provider, order.owner)
-
- const tokenAddress = order.inputToken.address
- const tokenName = order.inputToken.name
-
- const checkedHooks = await Promise.all(
- preHooks.map(({ callData }) =>
- checkIsCallDataAValidPermit(order.owner, chainId, eip2162Utils, tokenAddress, tokenName, callData, permitInfo)
- )
- )
-
- const validPermits = checkedHooks.filter((v) => v !== undefined)
-
- if (!validPermits.length) {
- // No permits means no preHook permits, we can say that there is no valid permit
- return false
- }
-
- // Only when all permits are valid, then the order permits are still valid
- return validPermits.every(Boolean)
-}
diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useGetPermitInfo.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useGetPermitInfo.ts
deleted file mode 100644
index cb5356b5b9..0000000000
--- a/apps/cowswap-frontend/src/modules/permit/hooks/useGetPermitInfo.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { useAtomValue } from 'jotai'
-import { useCallback } from 'react'
-
-import { SupportedChainId } from '@cowprotocol/cow-sdk'
-
-import { permittableTokensAtom } from '../state/permittableTokensAtom'
-import { IsTokenPermittableResult } from '../types'
-
-/**
- * Returns a callback for getting PermitInfo for a given token
- *
- * Assumes permit info was already checked and cached.
- */
-export function useGetPermitInfo(chainId: SupportedChainId): (tokenAddress: string) => IsTokenPermittableResult {
- const permittableTokens = useAtomValue(permittableTokensAtom)
-
- return useCallback(
- (tokenAddress: string) => permittableTokens[chainId]?.[tokenAddress.toLowerCase()],
- [chainId, permittableTokens]
- )
-}
diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts
deleted file mode 100644
index b61aba3797..0000000000
--- a/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { useAtomValue } from 'jotai'
-
-import { ordersPermitStatusAtom } from '../state/ordersPermitStatusAtom'
-
-export function useGetOrdersPermitStatus() {
- return useAtomValue(ordersPermitStatusAtom)
-}
diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts
index 712e9d3442..cb734a99e6 100644
--- a/apps/cowswap-frontend/src/modules/permit/index.ts
+++ b/apps/cowswap-frontend/src/modules/permit/index.ts
@@ -1,12 +1,10 @@
export * from './hooks/useAccountAgnosticPermitHookData'
export * from './hooks/useGeneratePermitHook'
export * from './hooks/usePermitInfo'
-export * from './hooks/useOrdersPermitStatus'
export * from './hooks/usePermitCompatibleTokens'
export * from './hooks/useTokenSupportsPermit'
export { useGetCachedPermit } from './hooks/useGetCachedPermit'
export * from './types'
-export * from './updaters/PendingPermitUpdater'
export * from './utils/handlePermit'
export * from './utils/callDataContainsPermitSigner'
export * from './utils/recoverSpenderFromCalldata'
diff --git a/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts b/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts
deleted file mode 100644
index cf132cefc3..0000000000
--- a/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { atom } from 'jotai'
-
-import { atomWithPartialUpdate } from '@cowprotocol/common-utils'
-
-import { OrdersPermitStatus } from '../types'
-
-export const { atom: ordersPermitStatusAtom, updateAtom: updateOrdersPermitStatusAtom } = atomWithPartialUpdate(
- atom({})
-)
diff --git a/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts b/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts
deleted file mode 100644
index b286652ed9..0000000000
--- a/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { useSetAtom } from 'jotai'
-import { useEffect, useRef } from 'react'
-
-import { ParsedOrder } from 'utils/orderUtils/parseOrder'
-
-import { PENDING_ORDER_PERMIT_CHECK_INTERVAL } from '../const'
-import { useCheckHasValidPendingPermit } from '../hooks/useCheckHasValidPendingPermit'
-import { updateOrdersPermitStatusAtom } from '../state/ordersPermitStatusAtom'
-
-export type PendingPermitUpdaterProps = {
- orders: ParsedOrder[]
-}
-
-export function PendingPermitUpdater({ orders }: PendingPermitUpdaterProps): null {
- const ordersRef = useRef(orders)
- ordersRef.current = orders
-
- const checkHasValidPendingPermit = useCheckHasValidPendingPermit()
- const updateOrdersPermitStatus = useSetAtom(updateOrdersPermitStatusAtom)
-
- useEffect(() => {
- const checkOrders = () => {
- console.debug(`UpdatePendingPermit: checking orders`, ordersRef.current.length)
- ordersRef.current.forEach((order) => {
- checkHasValidPendingPermit(order).then((status) => {
- console.debug(`UpdatePendingPermit: checked order ${order.id} with status ${status}`)
- updateOrdersPermitStatus({ [order.id]: status })
- })
- })
- }
-
- checkOrders()
- const interval = setInterval(checkOrders, PENDING_ORDER_PERMIT_CHECK_INTERVAL)
-
- return () => clearInterval(interval)
- }, [checkHasValidPendingPermit, updateOrdersPermitStatus])
-
- return null
-}
diff --git a/apps/cowswap-frontend/src/utils/orderUtils/getOrderPermitAmount.ts b/apps/cowswap-frontend/src/utils/orderUtils/getOrderPermitAmount.ts
new file mode 100644
index 0000000000..d579add099
--- /dev/null
+++ b/apps/cowswap-frontend/src/utils/orderUtils/getOrderPermitAmount.ts
@@ -0,0 +1,41 @@
+import { Erc20__factory } from '@cowprotocol/abis'
+import type { LatestAppDataDocVersion } from '@cowprotocol/app-data'
+import { COW_PROTOCOL_VAULT_RELAYER_ADDRESS, SupportedChainId } from '@cowprotocol/cow-sdk'
+import { BigNumber } from '@ethersproject/bignumber'
+
+import { ParsedOrder } from './parseOrder'
+
+const erc20Interface = Erc20__factory.createInterface()
+
+export function getOrderPermitAmount(chainId: SupportedChainId, order: ParsedOrder): BigNumber | null {
+ if (!order.fullAppData) return null
+
+ try {
+ const spenderAddress = COW_PROTOCOL_VAULT_RELAYER_ADDRESS[chainId].toLowerCase()
+ const appData: LatestAppDataDocVersion = JSON.parse(order.fullAppData)
+ const preHooks = appData.metadata.hooks?.pre
+
+ if (!preHooks) return null
+
+ const permitData = preHooks
+ .map((hook) => {
+ try {
+ return erc20Interface.decodeFunctionData('permit', hook.callData)
+ } catch {
+ return null
+ }
+ })
+ .find((decoded) => {
+ return (
+ decoded &&
+ decoded.spender?.toLowerCase() === spenderAddress &&
+ decoded.owner?.toLowerCase() === order.owner.toLowerCase() &&
+ (decoded.deadline as BigNumber)?.toNumber() > Date.now() / 1000
+ )
+ })
+
+ return permitData?.value || null
+ } catch {
+ return null
+ }
+}
diff --git a/libs/abis/src/index.ts b/libs/abis/src/index.ts
index cc6dc87148..b9ffc02a93 100644
--- a/libs/abis/src/index.ts
+++ b/libs/abis/src/index.ts
@@ -55,6 +55,7 @@ export type {
} from './generated/legacy'
export type { Erc20Interface } from './generated/legacy/Erc20'
+export { Erc20__factory } from './generated/legacy/factories/Erc20__factory'
// EthFlow
export type { CoWSwapEthFlow } from './generated/ethflow'