Commit 01aa3291 authored by Jack Short's avatar Jack Short Committed by GitHub

chore: bubbling up pwat spender from route query (#6481)

* chore: bubbling up pwat spender from route query

* refactoring

* adding loading state

* moving to loading allowance

* responding to comments

* linting
parent 5539ebed
import gql from 'graphql-tag'
import { useNftUniversalRouterAddressQuery } from '../__generated__/types-and-hooks'
gql`
query NftUniversalRouterAddress($chain: Chain = ETHEREUM) {
nftRoute(chain: $chain, senderAddress: "", nftTrades: []) {
toAddress
}
}
`
export function useNftUniversalRouterAddress() {
const { data, loading } = useNftUniversalRouterAddressQuery({
// no cache because a different version of nftRoute query is going to be called around the same time
fetchPolicy: 'no-cache',
})
return {
universalRouterAddress: data?.nftRoute?.toAddress,
universalRouterAddressIsLoading: loading,
}
}
...@@ -14,6 +14,7 @@ import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal' ...@@ -14,6 +14,7 @@ import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal'
import { LoadingBubble } from 'components/Tokens/loading' import { LoadingBubble } from 'components/Tokens/loading'
import { MouseoverTooltip } from 'components/Tooltip' import { MouseoverTooltip } from 'components/Tooltip'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { useNftUniversalRouterAddress } from 'graphql/data/nft/NftUniversalRouterAddress'
import { useCurrency } from 'hooks/Tokens' import { useCurrency } from 'hooks/Tokens'
import { AllowanceState } from 'hooks/usePermit2Allowance' import { AllowanceState } from 'hooks/usePermit2Allowance'
import { useStablecoinValue } from 'hooks/useStablecoinPrice' import { useStablecoinValue } from 'hooks/useStablecoinPrice'
...@@ -316,6 +317,7 @@ export const BagFooter = ({ setModalIsOpen, eventProperties }: BagFooterProps) = ...@@ -316,6 +317,7 @@ export const BagFooter = ({ setModalIsOpen, eventProperties }: BagFooterProps) =
const isPending = PENDING_BAG_STATUSES.includes(bagStatus) const isPending = PENDING_BAG_STATUSES.includes(bagStatus)
const activeCurrency = inputCurrency ?? defaultCurrency const activeCurrency = inputCurrency ?? defaultCurrency
const usingPayWithAnyToken = !!inputCurrency && chainId === SupportedChainId.MAINNET const usingPayWithAnyToken = !!inputCurrency && chainId === SupportedChainId.MAINNET
const { universalRouterAddress, universalRouterAddressIsLoading } = useNftUniversalRouterAddress()
useSubscribeTransactionState(setModalIsOpen) useSubscribeTransactionState(setModalIsOpen)
const fetchAssets = useFetchAssets() const fetchAssets = useFetchAssets()
...@@ -332,8 +334,9 @@ export const BagFooter = ({ setModalIsOpen, eventProperties }: BagFooterProps) = ...@@ -332,8 +334,9 @@ export const BagFooter = ({ setModalIsOpen, eventProperties }: BagFooterProps) =
const { allowance, isAllowancePending, isApprovalLoading, updateAllowance } = usePermit2Approval( const { allowance, isAllowancePending, isApprovalLoading, updateAllowance } = usePermit2Approval(
trade?.inputAmount.currency.isToken ? (trade?.inputAmount as CurrencyAmount<Token>) : undefined, trade?.inputAmount.currency.isToken ? (trade?.inputAmount as CurrencyAmount<Token>) : undefined,
maximumAmountIn, maximumAmountIn,
true universalRouterAddress
) )
const loadingAllowance = allowance.state === AllowanceState.LOADING || universalRouterAddressIsLoading
usePayWithAnyTokenSwap(trade, allowance, allowedSlippage) usePayWithAnyTokenSwap(trade, allowance, allowedSlippage)
const priceImpact = usePriceImpact(trade) const priceImpact = usePriceImpact(trade)
...@@ -423,11 +426,11 @@ export const BagFooter = ({ setModalIsOpen, eventProperties }: BagFooterProps) = ...@@ -423,11 +426,11 @@ export const BagFooter = ({ setModalIsOpen, eventProperties }: BagFooterProps) =
buttonTextColor = theme.textPrimary buttonTextColor = theme.textPrimary
helperText = <Trans>Insufficient pool liquidity to complete transaction</Trans> helperText = <Trans>Insufficient pool liquidity to complete transaction</Trans>
} }
} else if (allowance.state === AllowanceState.REQUIRED || allowance.state === AllowanceState.LOADING) { } else if (allowance.state === AllowanceState.REQUIRED || loadingAllowance) {
handleClick = () => updateAllowance() handleClick = () => updateAllowance()
disabled = isAllowancePending || isApprovalLoading || allowance.state === AllowanceState.LOADING disabled = isAllowancePending || isApprovalLoading || loadingAllowance
if (allowance.state === AllowanceState.LOADING) { if (loadingAllowance) {
buttonText = <Trans>Loading Allowance</Trans> buttonText = <Trans>Loading Allowance</Trans>
} else if (isAllowancePending) { } else if (isAllowancePending) {
buttonText = <Trans>Approve in your wallet</Trans> buttonText = <Trans>Approve in your wallet</Trans>
...@@ -480,6 +483,7 @@ export const BagFooter = ({ setModalIsOpen, eventProperties }: BagFooterProps) = ...@@ -480,6 +483,7 @@ export const BagFooter = ({ setModalIsOpen, eventProperties }: BagFooterProps) =
usingPayWithAnyToken, usingPayWithAnyToken,
tradeState, tradeState,
allowance.state, allowance.state,
loadingAllowance,
priceImpact, priceImpact,
connector, connector,
toggleWalletDrawer, toggleWalletDrawer,
......
import { CurrencyAmount } from '@uniswap/sdk-core' import { CurrencyAmount } from '@uniswap/sdk-core'
import { USDC_MAINNET } from '@uniswap/smart-order-router' import { USDC_MAINNET } from '@uniswap/smart-order-router'
import { UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router-sdk'
import usePermit2Allowance, { AllowanceState } from 'hooks/usePermit2Allowance' import usePermit2Allowance, { AllowanceState } from 'hooks/usePermit2Allowance'
import { renderHook } from 'test-utils/render' import { renderHook } from 'test-utils/render'
import usePermit2Approval from './usePermit2Approval' import usePermit2Approval from './usePermit2Approval'
const USDCAmount = CurrencyAmount.fromRawAmount(USDC_MAINNET, '10000') const USDCAmount = CurrencyAmount.fromRawAmount(USDC_MAINNET, '10000')
const NFT_UNIVERSAL_ROUTER_MAINNET_ADDRESS = '0x4c60051384bd2d3c01bfc845cf5f4b44bcbe9de5'
jest.mock('hooks/usePermit2Allowance') jest.mock('hooks/usePermit2Allowance')
...@@ -15,7 +15,7 @@ const mockUsePermit2Allowance = usePermit2Allowance as jest.MockedFunction<typeo ...@@ -15,7 +15,7 @@ const mockUsePermit2Allowance = usePermit2Allowance as jest.MockedFunction<typeo
describe('usePermit2Approval', () => { describe('usePermit2Approval', () => {
it('sets spender of the correct UR contract from NFT side', async () => { it('sets spender of the correct UR contract from NFT side', async () => {
mockUsePermit2Allowance.mockReturnValue({ state: AllowanceState.LOADING }) mockUsePermit2Allowance.mockReturnValue({ state: AllowanceState.LOADING })
renderHook(() => usePermit2Approval(USDCAmount, undefined, true)) renderHook(() => usePermit2Approval(USDCAmount, undefined, UNIVERSAL_ROUTER_ADDRESS(1)))
expect(mockUsePermit2Allowance).toHaveBeenCalledWith(USDCAmount, NFT_UNIVERSAL_ROUTER_MAINNET_ADDRESS) expect(mockUsePermit2Allowance).toHaveBeenCalledWith(USDCAmount, UNIVERSAL_ROUTER_ADDRESS(1))
}) })
}) })
import { sendAnalyticsEvent } from '@uniswap/analytics' import { sendAnalyticsEvent } from '@uniswap/analytics'
import { InterfaceEventName } from '@uniswap/analytics-events' import { InterfaceEventName } from '@uniswap/analytics-events'
import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { CurrencyAmount, SupportedChainId, Token } from '@uniswap/sdk-core'
import { UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router-sdk' import { UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router-sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import usePermit2Allowance, { AllowanceState } from 'hooks/usePermit2Allowance' import usePermit2Allowance, { AllowanceState } from 'hooks/usePermit2Allowance'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import invariant from 'tiny-invariant' import invariant from 'tiny-invariant'
// TODO: This should be removed when the sdk is updated to include the new UR address function getURAddress(chainId?: number, nftURAddress?: string) {
const NFT_UNIVERSAL_ROUTER_MAINNET_ADDRESS = '0x4c60051384bd2d3c01bfc845cf5f4b44bcbe9de5' if (!chainId) return
// if mainnet and on NFT flow, use the contract address returned by GQL
if (chainId === SupportedChainId.MAINNET) {
return nftURAddress ?? UNIVERSAL_ROUTER_ADDRESS(chainId)
}
return UNIVERSAL_ROUTER_ADDRESS(chainId)
}
export default function usePermit2Approval( export default function usePermit2Approval(
amount?: CurrencyAmount<Token>, amount: CurrencyAmount<Token> | undefined,
maximumAmount?: CurrencyAmount<Token>, maximumAmount: CurrencyAmount<Token> | undefined,
shouldUseNftRouter?: boolean nftUniversalRouterContractAddress?: string
) { ) {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
let contractToApprove: string | undefined const universalRouterAddress = getURAddress(chainId, nftUniversalRouterContractAddress)
if (chainId) { const allowanceAmount = maximumAmount ?? (amount?.currency.isToken ? (amount as CurrencyAmount<Token>) : undefined)
const forceNftRouter = shouldUseNftRouter && chainId === 1 const allowance = usePermit2Allowance(allowanceAmount, universalRouterAddress)
contractToApprove = forceNftRouter ? NFT_UNIVERSAL_ROUTER_MAINNET_ADDRESS : UNIVERSAL_ROUTER_ADDRESS(chainId)
}
const allowance = usePermit2Allowance(
maximumAmount ?? (amount?.currency.isToken ? (amount as CurrencyAmount<Token>) : undefined),
contractToApprove
)
const isApprovalLoading = allowance.state === AllowanceState.REQUIRED && allowance.isApprovalLoading const isApprovalLoading = allowance.state === AllowanceState.REQUIRED && allowance.isApprovalLoading
const [isAllowancePending, setIsAllowancePending] = useState(false) const [isAllowancePending, setIsAllowancePending] = useState(false)
const updateAllowance = useCallback(async () => { const updateAllowance = useCallback(async () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment