Commit d1fad3c4 authored by Noah Zinsmeister's avatar Noah Zinsmeister

update to latest deploy

refactor useV3Positions to work with remove

axe old redirects
parent a1c4b97a
describe('Remove Liquidity', () => { describe('Remove Liquidity', () => {
it('redirects', () => {
cy.visit('/remove/v2/0xc778417E063141139Fce010982780140Aa0cD5Ab-0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
cy.url().should(
'contain',
'/remove/v2/0xc778417E063141139Fce010982780140Aa0cD5Ab/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85'
)
})
it('eth remove', () => { it('eth remove', () => {
cy.visit('/remove/v2/ETH/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85') cy.visit('/remove/v2/ETH/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'ETH') cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'ETH')
......
...@@ -2,48 +2,48 @@ import { ChainId } from '@uniswap/sdk-core' ...@@ -2,48 +2,48 @@ import { ChainId } from '@uniswap/sdk-core'
export const FACTORY_ADDRESSES: { [chainId in ChainId]: string } = { export const FACTORY_ADDRESSES: { [chainId in ChainId]: string } = {
[ChainId.MAINNET]: '', [ChainId.MAINNET]: '',
[ChainId.ROPSTEN]: '0x5BbFe6FF864718cD1cE0F126be99e96239E3caDD', [ChainId.ROPSTEN]: '0x864e344eCd7f3a9A4368dEC11Be8104db5770364',
[ChainId.RINKEBY]: '0x7ba6C6345E7a73cC0D41d762C7Db9cb3DB721396', [ChainId.RINKEBY]: '0xAE28628c0fdFb5e54d60FEDC6C9085199aec14dF',
[ChainId.GÖRLI]: '0x5BbFe6FF864718cD1cE0F126be99e96239E3caDD', [ChainId.GÖRLI]: '0x864e344eCd7f3a9A4368dEC11Be8104db5770364',
[ChainId.KOVAN]: '', [ChainId.KOVAN]: '0xd4013a706fa79487989b595Df35eF8AD1ffBb422',
} }
export const TICK_LENS_ADDRESSES: { [chainId in ChainId]: string } = { export const TICK_LENS_ADDRESSES: { [chainId in ChainId]: string } = {
[ChainId.MAINNET]: '', [ChainId.MAINNET]: '',
[ChainId.ROPSTEN]: '0x1C8beBE5596b60A84e6d737229aDd502E14276Eb', [ChainId.ROPSTEN]: '0xc97c7D6C2F1EE518bE4D4B8566bcEb917dED4F39',
[ChainId.RINKEBY]: '0xd4013a706fa79487989b595Df35eF8AD1ffBb422', [ChainId.RINKEBY]: '0x2d31366B7D446d629ac36933F12bdbca96860f84',
[ChainId.GÖRLI]: '0x1C8beBE5596b60A84e6d737229aDd502E14276Eb', [ChainId.GÖRLI]: '0xc97c7D6C2F1EE518bE4D4B8566bcEb917dED4F39',
[ChainId.KOVAN]: '', [ChainId.KOVAN]: '0xD2AAa0217a203d9FaB6e5272b211Be2Aba52f385',
} }
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES: { [chainId in ChainId]: string } = { export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES: { [chainId in ChainId]: string } = {
[ChainId.MAINNET]: '', [ChainId.MAINNET]: '',
[ChainId.ROPSTEN]: '0x921647f0c094e2e59CDE6DEfafD77743012f52bd', [ChainId.ROPSTEN]: '0xc97c7D6C2F1EE518bE4D4B8566bcEb917dED4F39',
[ChainId.RINKEBY]: '0x30Ba713F78Ad3c175a25aD767e3f423549Ac2D65', [ChainId.RINKEBY]: '0xbBca0fFBFE60F60071630A8c80bb6253dC9D6023',
[ChainId.GÖRLI]: '0x921647f0c094e2e59CDE6DEfafD77743012f52bd', [ChainId.GÖRLI]: '0x539BF58f052dE91ae369dAd59f1ac6887dF39Bc5',
[ChainId.KOVAN]: '', [ChainId.KOVAN]: '0xAE28628c0fdFb5e54d60FEDC6C9085199aec14dF',
} }
export const NONFUNGIBLE_TOKEN_POSITION_DESCRIPTOR_ADDRESSES: { [chainId in ChainId]: string } = { export const NONFUNGIBLE_TOKEN_POSITION_DESCRIPTOR_ADDRESSES: { [chainId in ChainId]: string } = {
[ChainId.MAINNET]: '', [ChainId.MAINNET]: '',
[ChainId.ROPSTEN]: '0xD2AAa0217a203d9FaB6e5272b211Be2Aba52f385', [ChainId.ROPSTEN]: '0x8dF824f7885611c587AA45924BF23153EC832b89',
[ChainId.RINKEBY]: '0xAc03019C975F5e79215FeDAB4a1DC30Af3E478F2', [ChainId.RINKEBY]: '0x3b1aC1c352F3A18A58471908982b8b870c836EC0',
[ChainId.GÖRLI]: '0xD2AAa0217a203d9FaB6e5272b211Be2Aba52f385', [ChainId.GÖRLI]: '0x8dF824f7885611c587AA45924BF23153EC832b89',
[ChainId.KOVAN]: '', [ChainId.KOVAN]: '0x30Ba713F78Ad3c175a25aD767e3f423549Ac2D65',
} }
export const SWAP_ROUTER_ADDRESSES: { [chainId in ChainId]: string } = { export const SWAP_ROUTER_ADDRESSES: { [chainId in ChainId]: string } = {
[ChainId.MAINNET]: '', [ChainId.MAINNET]: '',
[ChainId.ROPSTEN]: '0xDD1B8aA26ac2330e39f8B291eA1E6a82A40E65C4', [ChainId.ROPSTEN]: '0x7046f9311663DB8B7cf218BC7B6F3f17B0Ea1047',
[ChainId.RINKEBY]: '0xD2AAa0217a203d9FaB6e5272b211Be2Aba52f385', [ChainId.RINKEBY]: '0x8dF824f7885611c587AA45924BF23153EC832b89',
[ChainId.GÖRLI]: '0xDD1B8aA26ac2330e39f8B291eA1E6a82A40E65C4', [ChainId.GÖRLI]: '0x7046f9311663DB8B7cf218BC7B6F3f17B0Ea1047',
[ChainId.KOVAN]: '', [ChainId.KOVAN]: '0x921647f0c094e2e59CDE6DEfafD77743012f52bd',
} }
export const V2_MIGRATOR_ADDRESSES: { [chainId in ChainId]: string } = { export const V2_MIGRATOR_ADDRESSES: { [chainId in ChainId]: string } = {
[ChainId.MAINNET]: '', [ChainId.MAINNET]: '',
[ChainId.ROPSTEN]: '0x30Ba713F78Ad3c175a25aD767e3f423549Ac2D65', [ChainId.ROPSTEN]: '0xbBca0fFBFE60F60071630A8c80bb6253dC9D6023',
[ChainId.RINKEBY]: '0x864e344eCd7f3a9A4368dEC11Be8104db5770364', [ChainId.RINKEBY]: '0xc4b81504F9a2bd6a6f2617091FB01Efb38D119c8',
[ChainId.GÖRLI]: '0x30Ba713F78Ad3c175a25aD767e3f423549Ac2D65', [ChainId.GÖRLI]: '0xbBca0fFBFE60F60071630A8c80bb6253dC9D6023',
[ChainId.KOVAN]: '', [ChainId.KOVAN]: '0xc97c7D6C2F1EE518bE4D4B8566bcEb917dED4F39',
} }
import { useSingleCallResult, useSingleContractMultipleData } from 'state/multicall/hooks' import { useSingleCallResult, useSingleContractMultipleData, Result } from 'state/multicall/hooks'
import { useMemo } from 'react' import { useMemo } from 'react'
import { PositionDetails } from 'types/position' import { PositionDetails } from 'types/position'
import { useV3NFTPositionManagerContract } from './useContract' import { useV3NFTPositionManagerContract } from './useContract'
import JSBI from 'jsbi' import { BigNumber, BigNumberish } from '@ethersproject/bignumber'
interface UseV3PositionsResults { interface UseV3PositionsResults {
error?: (string | boolean) | (string | boolean)[]
loading: boolean loading: boolean
error: boolean
positions: PositionDetails[] | undefined positions: PositionDetails[] | undefined
} }
function useV3PositionsFromTokenIds(tokenIds: BigNumberish[]): UseV3PositionsResults {
const positionManager = useV3NFTPositionManagerContract()
const inputs = useMemo(() => tokenIds.map((tokenId) => [BigNumber.from(tokenId)]), [tokenIds])
const results = useSingleContractMultipleData(positionManager ?? undefined, 'positions', inputs)
const loading = useMemo(() => results.some(({ loading }) => loading), [results])
const error = useMemo(() => results.some(({ error }) => error), [results])
const positions = useMemo(() => {
if (!loading && !error) {
return results.map((call) => {
const result = call.result as Result
return {
fee: result.fee,
feeGrowthInside0LastX128: result.feeGrowthInside0LastX128,
feeGrowthInside1LastX128: result.feeGrowthInside1LastX128,
liquidity: result.liquidity,
nonce: result.nonce,
operator: result.operator,
tickLower: result.tickLower,
tickUpper: result.tickUpper,
token0: result.token0,
token1: result.token1,
tokensOwed0: result.tokensOwed0,
tokensOwed1: result.tokensOwed1,
}
})
}
return undefined
}, [loading, error, results])
return {
loading,
error,
positions,
}
}
interface UseV3PositionResults {
loading: boolean
error: boolean
position: PositionDetails | undefined
}
export function useV3PositionFromTokenId(tokenId: BigNumberish): UseV3PositionResults {
const position = useV3PositionsFromTokenIds([tokenId])
return {
loading: position.loading,
error: position.error,
position: position.positions?.[0],
}
}
export function useV3Positions(account: string | null | undefined): UseV3PositionsResults { export function useV3Positions(account: string | null | undefined): UseV3PositionsResults {
const positionManager = useV3NFTPositionManagerContract() const positionManager = useV3NFTPositionManagerContract()
...@@ -18,9 +72,8 @@ export function useV3Positions(account: string | null | undefined): UseV3Positio ...@@ -18,9 +72,8 @@ export function useV3Positions(account: string | null | undefined): UseV3Positio
[account ?? undefined] [account ?? undefined]
) )
const accountBalance: number | undefined = balanceResult // we don't expect any account balance to ever exceed the bounds of max safe int
? parseFloat(JSBI.BigInt(balanceResult[0]).toString()) const accountBalance: number | undefined = balanceResult?.[0] ? Number.parseInt(balanceResult[0]) : undefined
: undefined
const positionIndicesArgs = useMemo(() => { const positionIndicesArgs = useMemo(() => {
if (accountBalance && account) { if (accountBalance && account) {
...@@ -45,51 +98,25 @@ export function useV3Positions(account: string | null | undefined): UseV3Positio ...@@ -45,51 +98,25 @@ export function useV3Positions(account: string | null | undefined): UseV3Positio
positionIndicesResults, positionIndicesResults,
]) ])
const formattedIndicesArgs = useMemo(() => { const tokenIds = useMemo(() => {
if (positionIndicesResults && account) { if (account) {
return positionIndicesResults.map((call) => { return positionIndicesResults
return [call.result?.[0] ? parseFloat(JSBI.BigInt(call.result?.[0]).toString()) : undefined] .map(({ result }) => result)
}) .filter((result): result is Result => !!result)
.map((result) => BigNumber.from(result[0]))
} }
return [] return []
}, [account, positionIndicesResults]) }, [account, positionIndicesResults])
const positionsResults = useSingleContractMultipleData( const positionsResults = useV3PositionsFromTokenIds(tokenIds)
positionManager ?? undefined,
'positions',
formattedIndicesArgs
)
const positionResultsLoading = useMemo(() => positionsResults.some(({ loading }) => loading), [positionsResults])
const positionResultsError = useMemo(() => positionsResults.some(({ error }) => error), [positionsResults])
const loading = balanceLoading || positionResultsLoading || positionIndicesLoading
const positions = useMemo(() => { // wrap the return value
if (positionsResults && !loading) { const loading = balanceLoading || positionIndicesLoading
return positionsResults.map((entry) => { const error = balanceError || positionIndicesError
const rp = entry.result
return {
fee: rp?.fee,
feeGrowthInside0LastX128: rp?.feeGrowthInside0LastX128,
feeGrowthInside1LastX128: rp?.feeGrowthInside1LastX128,
liquidity: rp?.liquidity,
nonce: rp?.nonce,
operator: rp?.operator,
tickLower: rp?.tickLower,
tickUpper: rp?.tickUpper,
token0: rp?.token0,
token1: rp?.token1,
tokensOwed0: rp?.tokensOwed0,
tokensOwed1: rp?.tokensOwed1,
}
})
}
return undefined
}, [positionsResults, loading])
return { return {
error: balanceError || positionIndicesError || positionResultsError, loading: loading || positionsResults.loading,
loading, error: error || positionsResults.error,
positions, positions: loading || error ? undefined : positionsResults.positions,
} }
} }
...@@ -2,10 +2,6 @@ import React from 'react' ...@@ -2,10 +2,6 @@ import React from 'react'
import { Redirect, RouteComponentProps } from 'react-router-dom' import { Redirect, RouteComponentProps } from 'react-router-dom'
import AddLiquidityV2 from './index' import AddLiquidityV2 from './index'
export function RedirectToAddLiquidityV2() {
return <Redirect to="/add/v2/ETH" />
}
export function RedirectDuplicateTokenIdsV2(props: RouteComponentProps<{ currencyIdA: string; currencyIdB: string }>) { export function RedirectDuplicateTokenIdsV2(props: RouteComponentProps<{ currencyIdA: string; currencyIdB: string }>) {
const { const {
match: { match: {
...@@ -14,7 +10,7 @@ export function RedirectDuplicateTokenIdsV2(props: RouteComponentProps<{ currenc ...@@ -14,7 +10,7 @@ export function RedirectDuplicateTokenIdsV2(props: RouteComponentProps<{ currenc
} = props } = props
if (currencyIdA.toLowerCase() === currencyIdB.toLowerCase()) { if (currencyIdA.toLowerCase() === currencyIdB.toLowerCase()) {
return <Redirect to={`/add/V2/${currencyIdA}`} /> return <Redirect to={`/add/v2/${currencyIdA}`} />
} }
return <AddLiquidityV2 {...props} /> return <AddLiquidityV2 {...props} />
} }
...@@ -24,14 +24,11 @@ import PoolV2 from './Pool/v2' ...@@ -24,14 +24,11 @@ import PoolV2 from './Pool/v2'
import PoolFinder from './PoolFinder' import PoolFinder from './PoolFinder'
import RemoveLiquidity from './RemoveLiquidity' import RemoveLiquidity from './RemoveLiquidity'
import RemoveLiquidityV3 from './RemoveLiquidity/V3' import RemoveLiquidityV3 from './RemoveLiquidity/V3'
import { RedirectOldRemoveLiquidityPathStructure } from './RemoveLiquidity/redirects'
import Swap from './Swap' import Swap from './Swap'
import { OpenClaimAddressModalAndRedirectToSwap, RedirectPathToSwapOnly, RedirectToSwap } from './Swap/redirects' import { OpenClaimAddressModalAndRedirectToSwap, RedirectPathToSwapOnly, RedirectToSwap } from './Swap/redirects'
import Vote from './Vote' import Vote from './Vote'
import VotePage from './Vote/VotePage' import VotePage from './Vote/VotePage'
import { RedirectDuplicateTokenIdsV2 } from './AddLiquidityV2/redirects' import { RedirectDuplicateTokenIdsV2 } from './AddLiquidityV2/redirects'
import AddLiquidity from './AddLiquidity'
import AddLiquidityV2 from './AddLiquidityV2'
import { PositionPage } from './Pool/PositionPage' import { PositionPage } from './Pool/PositionPage'
const AppWrapper = styled.div` const AppWrapper = styled.div`
...@@ -109,10 +106,6 @@ export default function App() { ...@@ -109,10 +106,6 @@ export default function App() {
<Route exact strict path="/pool" component={Pool} /> <Route exact strict path="/pool" component={Pool} />
<Route exact strict path="/pool/:positionIndex" component={PositionPage} /> <Route exact strict path="/pool/:positionIndex" component={PositionPage} />
<Route exact path="/add" component={AddLiquidity} />
<Route exact path="/add/v2/" component={AddLiquidityV2} />
<Route exact path="/add/v2/:currencyIdA" component={AddLiquidityV2} />
<Route exact path="/add/:currencyIdA" component={AddLiquidity} />
<Route exact strict path="/add/v2/:currencyIdA?/:currencyIdB?" component={RedirectDuplicateTokenIdsV2} /> <Route exact strict path="/add/v2/:currencyIdA?/:currencyIdB?" component={RedirectDuplicateTokenIdsV2} />
<Route <Route
exact exact
...@@ -122,9 +115,8 @@ export default function App() { ...@@ -122,9 +115,8 @@ export default function App() {
/> />
<Route exact strict path="/remove/v1/:address" component={RemoveV1Exchange} /> <Route exact strict path="/remove/v1/:address" component={RemoveV1Exchange} />
<Route exact strict path="/remove/v2/:tokens" component={RedirectOldRemoveLiquidityPathStructure} />
<Route exact strict path="/remove/v2/:currencyIdA/:currencyIdB" component={RemoveLiquidity} /> <Route exact strict path="/remove/v2/:currencyIdA/:currencyIdB" component={RemoveLiquidity} />
<Route exact strict path="/remove/:currencyIdA/:currencyIdB/:fee" component={RemoveLiquidityV3} /> <Route exact strict path="/remove/:tokenId" component={RemoveLiquidityV3} />
<Route exact strict path="/migrate/v1" component={MigrateV1} /> <Route exact strict path="/migrate/v1" component={MigrateV1} />
<Route exact strict path="/migrate/v1/:address" component={MigrateV1Exchange} /> <Route exact strict path="/migrate/v1/:address" component={MigrateV1Exchange} />
......
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
import React from 'react' import React from 'react'
import { RouteComponentProps } from 'react-router' import { RouteComponentProps } from 'react-router'
import AppBody from '../AppBody' import AppBody from '../AppBody'
...@@ -5,9 +6,13 @@ import AppBody from '../AppBody' ...@@ -5,9 +6,13 @@ import AppBody from '../AppBody'
// TODO // TODO
export default function RemoveLiquidityV3({ export default function RemoveLiquidityV3({
match: { match: {
params: { currencyIdA, currencyIdB, fee }, params: { tokenId },
}, },
}: RouteComponentProps<{ currencyIdA: string; currencyIdB: string; fee: string }>) { }: RouteComponentProps<{ tokenId: string }>) {
console.log(currencyIdA, currencyIdB, fee) const position = useV3PositionFromTokenId(tokenId)
// check that account actually owns the position
console.log(position)
return <AppBody>TODO</AppBody> return <AppBody>TODO</AppBody>
} }
import React from 'react'
import { RouteComponentProps, Redirect } from 'react-router-dom'
const OLD_PATH_STRUCTURE = /^(0x[a-fA-F0-9]{40})-(0x[a-fA-F0-9]{40})$/
export function RedirectOldRemoveLiquidityPathStructure({
match: {
params: { tokens },
},
}: RouteComponentProps<{ tokens: string }>) {
if (!OLD_PATH_STRUCTURE.test(tokens)) {
return <Redirect to="/pool/v2" />
}
const [currency0, currency1] = tokens.split('-')
return <Redirect to={`/remove/v2/${currency0}/${currency1}`} />
}
...@@ -25,7 +25,7 @@ type MethodArgs = Array<MethodArg | MethodArg[]> ...@@ -25,7 +25,7 @@ type MethodArgs = Array<MethodArg | MethodArg[]>
export type OptionalMethodInputs = Array<MethodArg | MethodArg[] | undefined> | undefined export type OptionalMethodInputs = Array<MethodArg | MethodArg[] | undefined> | undefined
function isMethodArg(x: unknown): x is MethodArg { function isMethodArg(x: unknown): x is MethodArg {
return ['string', 'number'].indexOf(typeof x) !== -1 return BigNumber.isBigNumber(x) || ['string', 'number'].indexOf(typeof x) !== -1
} }
function isValidMethodArgs(x: unknown): x is MethodArgs | undefined { function isValidMethodArgs(x: unknown): x is MethodArgs | undefined {
......
...@@ -4134,12 +4134,17 @@ ...@@ -4134,12 +4134,17 @@
tiny-invariant "^1.1.0" tiny-invariant "^1.1.0"
tiny-warning "^1.0.3" tiny-warning "^1.0.3"
"@uniswap/v3-core@1.0.0-rc.1", "@uniswap/v3-core@^1.0.0-rc.1": "@uniswap/v3-core@1.0.0-rc.1":
version "1.0.0-rc.1" version "1.0.0-rc.1"
resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0-rc.1.tgz#f2bbc483451364a951fba06eb2d978c6e8bdd58f" resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0-rc.1.tgz#f2bbc483451364a951fba06eb2d978c6e8bdd58f"
integrity sha512-4ET2H0a8p7nVBGFWfio9SHc+RA6UIXEvlTRIJNsDwjQvfs8Jq9lfJ+eSOUTGmiB8Vp8V5dWarLDBU/rDE159pQ== integrity sha512-4ET2H0a8p7nVBGFWfio9SHc+RA6UIXEvlTRIJNsDwjQvfs8Jq9lfJ+eSOUTGmiB8Vp8V5dWarLDBU/rDE159pQ==
"@uniswap/v3-periphery@^1.0.0-beta.17", "@uniswap/v3-periphery@^1.0.0-beta.19": "@uniswap/v3-core@1.0.0-rc.2", "@uniswap/v3-core@^1.0.0-rc.2":
version "1.0.0-rc.2"
resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0-rc.2.tgz#a1afb3253a7295bec6165ad1d960121e6851a576"
integrity sha512-vsqkqAHPCKsVi0nWwWeX+mHnSTJ8ZUdu1zAVXB9Mj9A+aeBQGV9foRKs9ufDGJq7S1nqmz+7FdjSOcVoeiUqgQ==
"@uniswap/v3-periphery@^1.0.0-beta.17":
version "1.0.0-beta.19" version "1.0.0-beta.19"
resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.0.0-beta.19.tgz#d9af90b12657049674cd2f26ae1c61b6cc393261" resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.0.0-beta.19.tgz#d9af90b12657049674cd2f26ae1c61b6cc393261"
integrity sha512-ZQX5KN/89OB7UjrmGOSB7QZIEbgW+R0uaVM5NdlK63Ji0rZjmddeoYS8oNk7i5BU3WR+xJY5DgfiDSmn1W6Sww== integrity sha512-ZQX5KN/89OB7UjrmGOSB7QZIEbgW+R0uaVM5NdlK63Ji0rZjmddeoYS8oNk7i5BU3WR+xJY5DgfiDSmn1W6Sww==
...@@ -4149,6 +4154,16 @@ ...@@ -4149,6 +4154,16 @@
"@uniswap/v2-core" "1.0.1" "@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0-rc.1" "@uniswap/v3-core" "1.0.0-rc.1"
"@uniswap/v3-periphery@^1.0.0-beta.20":
version "1.0.0-beta.20"
resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.0.0-beta.20.tgz#67a8086315e4820e3669b1f645916f9e246a6e56"
integrity sha512-sWh2W+CBjRVAwbPbKwgu8DWKYY7J3ucZf5mjRPBnmvsNLi6ILM5/NDAtefCvMnKEX7IQzO3gk7gDWZHPrkWXyw==
dependencies:
"@openzeppelin/contracts" "3.4.1-solc-0.7-2"
"@uniswap/lib" "^4.0.1-alpha"
"@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0-rc.2"
"@uniswap/v3-sdk@^1.0.0-alpha.11": "@uniswap/v3-sdk@^1.0.0-alpha.11":
version "1.0.0-alpha.11" version "1.0.0-alpha.11"
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-1.0.0-alpha.11.tgz#184ed5ee8322b27f35aa830ad5e217b5dda6bd67" resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-1.0.0-alpha.11.tgz#184ed5ee8322b27f35aa830ad5e217b5dda6bd67"
......
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