import DeployHelper from "../deploys" ; import { MAX_UINT_256 } from "../constants" ; import { BigNumber , BigNumberish , Signer , providers } from "ethers" ; import { Address } from "../types" ; import { Account } from "../test/types" ; import { UniswapV3Factory , SwapRouter , NonfungiblePositionManager , UniswapV3Pool , Quoter , NFTDescriptor } from "../contracts/uniswapV3" ; import { UniswapV3Pool__factory } from "../../typechain/factories/UniswapV3Pool__factory" ; import { ether } from "../index" ; import { StandardTokenMock } from "../../typechain/StandardTokenMock" ; import { WETH9 } from "../../typechain/WETH9" ; import { parseEther } from "ethers/lib/utils" ; type Token = StandardTokenMock | WETH9 ; export class UniswapV3Fixture { private _deployer : DeployHelper ; private _ownerSigner : Signer ; public factory : UniswapV3Factory ; public swapRouter : SwapRouter ; public nftPositionManager : NonfungiblePositionManager ; public nftDescriptor : NFTDescriptor ; public quoter : Quoter ; public wethDaiPool : UniswapV3Pool ; public wethWbtcPool : UniswapV3Pool ; param provider param ownerAddress constructor ( provider , ownerAddress ) { this . _ownerSigner = provider . getSigner ( ownerAddress ) ; this . _deployer = new DeployHelper ( this . _ownerSigner ) ; } param _owner param _weth param _wbtc param _dai public async initialize ( _owner , _weth , _wethPrice , _wbtc , _wbtcPrice , _dai ) { this . factory = await this . _deployer . external . deployUniswapV3Factory ( ) ; this . swapRouter = await this . _deployer . external . deploySwapRouter ( this . factory . address , _weth . address ) ; this . nftDescriptor = await this . _deployer . external . deployNFTDescriptor ( ) ; this . nftPositionManager = await this . _deployer . external . deployNftPositionManager ( this . factory . address , _weth . address , this . nftDescriptor . address ) ; this . quoter = await this . _deployer . external . deployQuoter ( this . factory . address , _weth . address ) ; this . wethDaiPool = await this . createNewPair ( _weth , _dai , 3000 , _wethPrice ) ; this . wethWbtcPool = await this . createNewPair ( _weth , _wbtc , 3000 , _wethPrice / _wbtcPrice ) ; } param _token0 param _token1 param _fee param _ratio returns public async createNewPair ( _token0 , _token1 , _fee , _ratio ) { let ratio = _ratio * ( 10 ** ( await _token1 . decimals ( ) - await _token0 . decimals ( ) ) ) ; if ( _token0 . address . toLowerCase ( ) > _token1 . address . toLowerCase ( ) ) { ratio = 1 / ratio ; } const [ token0Ordered , token1Ordered ] = this . getTokenOrder ( _token0 , _token1 ) ; const sqrtPrice = this . _getSqrtPriceX96 ( ratio ) ; await this . nftPositionManager . createAndInitializePoolIfNecessary ( token0Ordered . address , token1Ordered . address , _fee , sqrtPrice ) ; return this . getPool ( _token0 , _token1 , _fee ) ; } param _token0 param _token1 param _fee param _amount0 param _amount1 param _recipient public async addLiquidityWide ( _token0 , _token1 , _fee , _amount0 , _amount1 , _recipient ) { let [ amount0Ordered , amount1Ordered ] = [ _amount0 , _amount1 ] ; let [ token0Ordered , token1Ordered ] = [ _token0 , _token1 ] ; if ( _token0 . address . toLowerCase ( ) > _token1 . address . toLowerCase ( ) ) { [ amount0Ordered , amount1Ordered ] = [ _amount1 , _amount0 ] ; [ token0Ordered , token1Ordered ] = [ _token1 , _token0 ] ; } const tickSpacing = _fee / 50 ; const maxTick = 887272 ; const maxValidTick = Math . floor ( maxTick / tickSpacing ) * tickSpacing ; const minValidTick = Math . ceil ( - maxTick / tickSpacing ) * tickSpacing ; await this . nftPositionManager . connect ( this . _ownerSigner ) . mint ( { fee : _fee , token0 : token0Ordered . address , token1 : token1Ordered . address , tickLower : minValidTick , tickUpper : maxValidTick , amount0Desired : amount0Ordered , amount1Desired : amount1Ordered , amount0Min : 0 , amount1Min : 0 , deadline : MAX_UINT_256 , recipient : _recipient , } ) ; } param _token0 param _token1 param _fee returns public async getPool ( _token0 , _token1 , _fee ) { const [ token0Ordered , token1Ordered ] = this . getTokenOrder ( _token0 , _token1 ) ; const poolAddress = await this . factory . getPool ( token0Ordered . address , token1Ordered . address , _fee ) ; return UniswapV3Pool__factory . connect ( poolAddress , this . _ownerSigner ) ; } param _token0 param _token1 returns public getTokenOrder ( _token0 , _token1 ) { return _token0 . address . toLowerCase ( ) < _token1 . address . toLowerCase ( ) ? [ _token0 , _token1 ] : [ _token1 , _token0 ] ; } _getSqrtPriceX96 ( _ratio ) { return parseEther ( Math . sqrt ( _ratio ) . toFixed ( 18 ) . toString ( ) ) . mul ( BigNumber . from ( 2 ) . pow ( 96 ) ) . div ( ether ( 1 ) ) ; } }