UNPKG

@swaptoshi/dex-module

Version:

Klayr decentralized exchange (dex) on-chain module

481 lines 28.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NonfungiblePositionManager = void 0; const codec_1 = require("@klayr/codec"); const utils = require("@klayr/utils"); const IPFSHash = require("ipfs-only-hash"); const int_1 = require("../library/int"); const position_info_1 = require("../position_info"); const pool_1 = require("../pool"); const schema_1 = require("../../schema"); const PositionKey = require("../library/periphery/position_key"); const PoolAddress = require("../library/periphery/pool_address"); const TickMath = require("../library/core/tick_math"); const LiquidityAmounts = require("../library/periphery/liquidity_amounts"); const FullMath = require("../library/core/full_math"); const FixedPoint128 = require("../library/core/fixed_point_128"); const NFTDescriptor = require("../library/periphery/nft_descriptor"); const token_symbol_1 = require("../token_symbol"); const collect_position_1 = require("../../events/collect_position"); const decrease_liquidity_1 = require("../../events/decrease_liquidity"); const increase_liquidity_1 = require("../../events/increase_liquidity"); const tokenuri_created_1 = require("../../events/tokenuri_created"); const constants_1 = require("../../constants"); const tokenuri_destroyed_1 = require("../../events/tokenuri_destroyed"); class NonfungiblePositionManager { constructor(positionManager, stores, events, genesisConfig, dexConfig, moduleName) { this.collectionId = Buffer.alloc(0); this.poolAddress = Buffer.alloc(0); this.name = ''; this.symbol = ''; this.address = constants_1.POSITION_MANAGER_ADDRESS; this.chainId = Buffer.alloc(0); this.mutableDependencyReady = false; this.immutableDependencyReady = false; Object.assign(this, utils.objects.cloneDeep(positionManager)); this.collectionId = PoolAddress.computePoolId(positionManager.poolAddress); this.events = events; this.chainId = Buffer.from(genesisConfig.chainID, 'hex'); this.dexConfig = dexConfig; this.poolStore = stores.get(pool_1.PoolStore); this.tokenSymbolStore = stores.get(token_symbol_1.TokenSymbolStore); this.positionInfoStore = stores.get(position_info_1.PositionInfoStore); this.moduleName = moduleName; } toJSON() { return utils.objects.cloneDeep({ poolAddress: this.poolAddress, name: this.name, symbol: this.symbol, }); } addMutableDependencies(context, tokenMethod, nftMethod) { if (this.mutableDependencyReady || this.immutableDependencyReady) { throw new Error('this instance dependencies already been configured'); } this.mutableContext = context; this.immutableContext = this.mutableContext; this.tokenMethod = tokenMethod; this.nftMethod = nftMethod; this.immutableDependencyReady = true; this.mutableDependencyReady = true; } addImmutableDependencies(context, tokenMethod, nftMethod) { if (this.mutableDependencyReady || this.immutableDependencyReady) { throw new Error('this instance dependencies already been configured'); } this.immutableContext = context; this.tokenMethod = tokenMethod; this.nftMethod = nftMethod; this.immutableDependencyReady = true; } setSender(senderAddress) { if (this.mutableContext) { this.mutableContext.senderAddress = senderAddress; } else if (this.immutableContext) { this.immutableContext.senderAddress = senderAddress; } } async createAndInitializePoolIfNecessary(token0, token0Symbol, token0Decimal, token1, token1Symbol, token1Decimal, fee, sqrtPriceX96) { this._checkMutableDependency(); if (token0.compare(token1) >= 0) throw new Error('invalid token order'); let pool; try { pool = await this.poolStore.getMutablePool(this.mutableContext, token0, token1, fee); const { sqrtPriceX96: sqrtPriceX96Existing } = pool.slot0; if (sqrtPriceX96Existing === '0') await pool.initialize(sqrtPriceX96); } catch { pool = await this.poolStore.createPool(this.mutableContext, token0, token0Symbol, token0Decimal, token1, token1Symbol, token1Decimal, fee); await pool.initialize(sqrtPriceX96); } this.poolAddress = pool.address; this.collectionId = PoolAddress.computePoolId(pool.address); return pool; } async getPositions(tokenId) { this._checkImmutableDependency(); const nft = await this.nftMethod.getNFT(this.immutableContext.context, PositionKey.getNFTId(this.chainId, this.collectionId, tokenId)); const dexAttribute = nft.attributesArray.find(t => t.module === this.moduleName); if (!dexAttribute) throw new Error(`attributes '${this.moduleName}' doesnt exist on nft ${PositionKey.getNFTId(this.chainId, this.collectionId, tokenId).toString('hex')}`); const positionBuf = dexAttribute.attributes; return codec_1.codec.decode(schema_1.dexNFTAttributeSchema, positionBuf); } async mint(params) { this._checkMutableDependency(); this._checkDeadline(params.deadline); let liquidity = int_1.Uint128.from(0); let amount0 = int_1.Uint256.from(0); let amount1 = int_1.Uint256.from(0); const [_liquidity, _amount0, _amount1] = await this._addLiquidity({ token0: params.token0, token1: params.token1, fee: params.fee, recipient: this.address, tickLower: params.tickLower, tickUpper: params.tickUpper, amount0Desired: params.amount0Desired, amount1Desired: params.amount1Desired, amount0Min: params.amount0Min, amount1Min: params.amount1Min, }); liquidity = int_1.Uint128.from(_liquidity); amount0 = int_1.Uint256.from(_amount0); amount1 = int_1.Uint256.from(_amount1); const positionKey = PositionKey.compute(this.address, params.tickLower, params.tickUpper); const { feeGrowthInside0LastX128, feeGrowthInside1LastX128 } = await this.positionInfoStore.get(this.mutableContext.context, this.positionInfoStore.getKey(this.poolAddress, positionKey)); const position = { token0: params.token0, token1: params.token1, fee: params.fee, tickLower: params.tickLower, tickUpper: params.tickUpper, liquidity: liquidity.toString(), feeGrowthInside0LastX128, feeGrowthInside1LastX128, tokensOwed0: '0', tokensOwed1: '0', }; const tokenId = await this.nftMethod.getNextAvailableIndex(this.mutableContext.context, this.collectionId); await this.nftMethod.create(this.mutableContext.context, params.recipient, this.collectionId, [ { module: this.moduleName, attributes: codec_1.codec.encode(schema_1.dexNFTAttributeSchema, position), }, ]); const { tokenURI } = await this._saveTokenURI(tokenId.toString()); const events = this.events.get(increase_liquidity_1.IncreaseLiquidityEvent); events.add(this.mutableContext.context, { tokenId: PositionKey.getNFTId(this.chainId, this.collectionId, tokenId.toString()), ownerAddress: params.recipient, liquidity: liquidity.toString(), amount0: amount0.toString(), amount1: amount1.toString(), }, [this.poolAddress, this.mutableContext.senderAddress]); const tokenUriEvent = this.events.get(tokenuri_created_1.TokenURICreatedEvent); tokenUriEvent.add(this.mutableContext.context, { tokenURI, tokenId: PositionKey.getNFTId(this.chainId, this.collectionId, tokenId.toString()), }, [this.mutableContext.senderAddress]); return [tokenId.toString(), liquidity.toString(), amount0.toString(), amount1.toString()]; } async increaseLiquidity(params) { this._checkMutableDependency(); this._checkDeadline(params.deadline); const position = await this.getPositions(params.tokenId); let liquidity = int_1.Uint128.from(0); let amount0 = int_1.Uint256.from(0); let amount1 = int_1.Uint256.from(0); const [_liquidity, _amount0, _amount1] = await this._addLiquidity({ token0: position.token0, token1: position.token1, fee: position.fee, tickLower: position.tickLower, tickUpper: position.tickUpper, amount0Desired: params.amount0Desired, amount1Desired: params.amount1Desired, amount0Min: params.amount0Min, amount1Min: params.amount1Min, recipient: this.address, }); liquidity = int_1.Uint128.from(_liquidity); amount0 = int_1.Uint256.from(_amount0); amount1 = int_1.Uint256.from(_amount1); const positionKey = PositionKey.compute(this.address, position.tickLower, position.tickUpper); const { feeGrowthInside0LastX128, feeGrowthInside1LastX128 } = await this.positionInfoStore.get(this.mutableContext.context, this.positionInfoStore.getKey(this.poolAddress, positionKey)); position.tokensOwed0 = int_1.Uint128.from(position.tokensOwed0) .add(FullMath.mulDiv(int_1.Uint256.from(feeGrowthInside0LastX128).sub(position.feeGrowthInside0LastX128).toString(), position.liquidity, FixedPoint128.Q128)) .toString(); position.tokensOwed1 = int_1.Uint128.from(position.tokensOwed1) .add(FullMath.mulDiv(int_1.Uint256.from(feeGrowthInside1LastX128).sub(position.feeGrowthInside1LastX128).toString(), position.liquidity, FixedPoint128.Q128)) .toString(); position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128; position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128; position.liquidity = int_1.Uint128.from(position.liquidity).add(liquidity).toString(); await this._savePosition(params.tokenId, position); const nft = await this.nftMethod.getNFT(this.mutableContext.context, PositionKey.getNFTId(this.chainId, this.collectionId, params.tokenId)); const events = this.events.get(increase_liquidity_1.IncreaseLiquidityEvent); events.add(this.mutableContext.context, { tokenId: PositionKey.getNFTId(this.chainId, this.collectionId, params.tokenId), ownerAddress: nft.owner, liquidity: liquidity.toString(), amount0: amount0.toString(), amount1: amount1.toString(), }, [this.poolAddress, this.mutableContext.senderAddress]); return [liquidity.toString(), amount0.toString(), amount1.toString()]; } async decreaseLiquidity(params) { this._checkMutableDependency(); await this._isAuthorizedForToken(this.mutableContext.senderAddress, params.tokenId); this._checkDeadline(params.deadline); let amount0 = int_1.Uint256.from(0); let amount1 = int_1.Uint256.from(0); if (int_1.Uint128.from(params.liquidity).lte(0)) throw new Error('params.liquidity cant be negative'); const position = await this.getPositions(params.tokenId); const positionLiquidity = position.liquidity; if (int_1.Uint128.from(positionLiquidity).lt(params.liquidity)) throw new Error('invalid params.liquidity'); const originalSender = this.mutableContext.senderAddress; const pool = await this.poolStore.getMutablePool(this.mutableContext, position.token0, position.token1, position.fee); pool.setSender(this.address); const [_amount0, _amount1] = await pool.burn(position.tickLower, position.tickUpper, params.liquidity); amount0 = int_1.Uint256.from(_amount0); amount1 = int_1.Uint256.from(_amount1); if (amount0.lt(params.amount0Min) || amount1.lt(params.amount1Min)) throw new Error('Price slippage check'); const positionKey = PositionKey.compute(this.address, position.tickLower, position.tickUpper); const { feeGrowthInside0LastX128, feeGrowthInside1LastX128 } = await this.positionInfoStore.get(this.mutableContext.context, this.positionInfoStore.getKey(this.poolAddress, positionKey)); position.tokensOwed0 = int_1.Uint128.from(position.tokensOwed0) .add(amount0) .add(FullMath.mulDiv(int_1.Uint256.from(feeGrowthInside0LastX128).sub(position.feeGrowthInside0LastX128).toString(), positionLiquidity, FixedPoint128.Q128)) .toString(); position.tokensOwed1 = int_1.Uint128.from(position.tokensOwed1) .add(amount1) .add(FullMath.mulDiv(int_1.Uint256.from(feeGrowthInside1LastX128).sub(position.feeGrowthInside1LastX128).toString(), positionLiquidity, FixedPoint128.Q128)) .toString(); position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128; position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128; position.liquidity = int_1.Uint128.from(positionLiquidity).sub(params.liquidity).toString(); await this._savePosition(params.tokenId, position); const events = this.events.get(decrease_liquidity_1.DecreaseLiquidityEvent); events.add(this.mutableContext.context, { tokenId: PositionKey.getNFTId(this.chainId, this.collectionId, params.tokenId), liquidity: params.liquidity, amount0: amount0.toString(), amount1: amount1.toString(), }, [this.poolAddress, this.mutableContext.senderAddress]); pool.setSender(originalSender); return [amount0.toString(), amount1.toString()]; } async collect(params) { this._checkMutableDependency(); await this._isAuthorizedForToken(this.mutableContext.senderAddress, params.tokenId); if (int_1.Uint128.from(params.amount0Max).lte(0) && int_1.Uint128.from(params.amount1Max).lte(0)) throw new Error('invalid params amount max'); const recipient = params.recipient.compare(Buffer.alloc(0)) === 0 ? this.address : params.recipient; const position = await this.getPositions(params.tokenId); let { tokensOwed0, tokensOwed1 } = position; const originalSender = this.mutableContext.senderAddress; const pool = await this.poolStore.getMutablePool(this.mutableContext, position.token0, position.token1, position.fee); pool.setSender(this.address); if (int_1.Uint128.from(position.liquidity).gt(0)) { await pool.burn(position.tickLower, position.tickUpper, '0'); const { feeGrowthInside0LastX128, feeGrowthInside1LastX128 } = await this.positionInfoStore.get(this.mutableContext.context, this.positionInfoStore.getKey(this.poolAddress, PositionKey.compute(this.address, position.tickLower, position.tickUpper))); tokensOwed0 = int_1.Uint128.from(tokensOwed0) .add(FullMath.mulDiv(int_1.Uint256.from(feeGrowthInside0LastX128).sub(position.feeGrowthInside0LastX128).toString(), position.liquidity, FixedPoint128.Q128)) .toString(); tokensOwed1 = int_1.Uint128.from(tokensOwed1) .add(FullMath.mulDiv(int_1.Uint256.from(feeGrowthInside1LastX128).sub(position.feeGrowthInside1LastX128).toString(), position.liquidity, FixedPoint128.Q128)) .toString(); position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128; position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128; } const amount0Collect = int_1.Uint128.from(params.amount0Max).gt(tokensOwed0) ? tokensOwed0 : params.amount0Max; const amount1Collect = int_1.Uint128.from(params.amount1Max).gt(tokensOwed1) ? tokensOwed1 : params.amount1Max; const [amount0, amount1] = await pool.collect(recipient, position.tickLower, position.tickUpper, amount0Collect, amount1Collect); position.tokensOwed0 = int_1.Uint128.from(tokensOwed0).sub(amount0Collect).toString(); position.tokensOwed1 = int_1.Uint128.from(tokensOwed1).sub(amount1Collect).toString(); await this._savePosition(params.tokenId, position); const events = this.events.get(collect_position_1.CollectPositionEvent); events.add(this.mutableContext.context, { tokenId: PositionKey.getNFTId(this.chainId, this.collectionId, params.tokenId), recipientAddress: recipient, amount0Collect, amount1Collect, }, [this.poolAddress, recipient]); pool.setSender(originalSender); return [amount0, amount1]; } async burn(tokenId) { this._checkMutableDependency(); await this._isAuthorizedForToken(this.mutableContext.senderAddress, tokenId); const position = await this.getPositions(tokenId); if (!int_1.Uint128.from(position.liquidity).eq(0) || !int_1.Uint128.from(position.tokensOwed0).eq(0) || !int_1.Uint128.from(position.tokensOwed1).eq(0)) throw new Error('Not cleared'); const tokenURI = await this.tokenURI(tokenId); const nftId = PositionKey.getNFTId(this.chainId, this.collectionId, tokenId); const nft = await this.nftMethod.getNFT(this.mutableContext.context, nftId); await this.nftMethod.destroy(this.mutableContext.context, nft.owner, nftId); const events = this.events.get(tokenuri_destroyed_1.TokenURIDestroyedEvent); events.add(this.mutableContext.context, { tokenURI, tokenId: nftId }, [this.poolAddress, this.mutableContext.senderAddress]); } async tokenURI(tokenId) { this._checkImmutableDependency(); const nft = await this.nftMethod.getNFT(this.immutableContext.context, PositionKey.getNFTId(this.chainId, this.collectionId, tokenId)); const tokenUriAttribute = nft.attributesArray.find(t => t.module === constants_1.TOKENURI_ATTTRIBUTE); if (!tokenUriAttribute) throw new Error(`attributes '${constants_1.TOKENURI_ATTTRIBUTE}' doesnt exist on nft ${PositionKey.getNFTId(this.chainId, this.collectionId, tokenId).toString('hex')}`); return codec_1.codec.decode(schema_1.tokenUriNFTAttributeSchema, tokenUriAttribute.attributes).tokenURI; } async getMetadata(tokenId) { this._checkImmutableDependency(); const { token0, token1, fee, tickLower, tickUpper } = await this.getPositions(tokenId); const pool = await this.poolStore.getImmutablePool(this.immutableContext, token0, token1, fee); const baseTokenAddress = token0; const quoteTokenAddress = token1; const { tick } = pool.slot0; const baseToken = await this.tokenSymbolStore.get(this.immutableContext.context, this.tokenSymbolStore.getKey(baseTokenAddress)); const quoteToken = await this.tokenSymbolStore.get(this.immutableContext.context, this.tokenSymbolStore.getKey(quoteTokenAddress)); const uri = NFTDescriptor.constructTokenURI({ config: this.dexConfig, tokenId, quoteTokenAddress, baseTokenAddress, quoteTokenSymbol: quoteToken.symbol, baseTokenSymbol: baseToken.symbol, quoteTokenDecimals: quoteToken.decimal.toString(), baseTokenDecimals: baseToken.decimal.toString(), flipRatio: false, tickLower, tickUpper, tickCurrent: tick, tickSpacing: pool.tickSpacing, fee, poolAddress: pool.address, }); const encodedJSON = uri.substring('data:application/json;base64,'.length); const decodedJSON = Buffer.from(encodedJSON, 'base64').toString('utf8'); return JSON.parse(decodedJSON); } async total(tokenId, sqrtRatioX96) { this._checkImmutableDependency(); const [amount0Principal, amount1Principal] = await this.principal(tokenId, sqrtRatioX96); const [amount0Fee, amount1Fee] = await this.fees(tokenId); return [int_1.Uint256.from(amount0Principal).add(amount0Fee).toString(), int_1.Uint256.from(amount1Principal).add(amount1Fee).toString()]; } async principal(tokenId, sqrtRatioX96) { this._checkImmutableDependency(); const { tickLower, tickUpper, liquidity } = await this.getPositions(tokenId); return LiquidityAmounts.getAmountsForLiquidity(sqrtRatioX96, TickMath.getSqrtRatioAtTick(tickLower), TickMath.getSqrtRatioAtTick(tickUpper), liquidity); } async fees(tokenId) { this._checkImmutableDependency(); const { token0, token1, fee, tickLower, tickUpper, liquidity, feeGrowthInside0LastX128: positionFeeGrowthInside0LastX128, feeGrowthInside1LastX128: positionFeeGrowthInside1LastX128, tokensOwed0, tokensOwed1, } = await this.getPositions(tokenId); return this._fees({ token0, token1, fee, tickLower, tickUpper, liquidity, positionFeeGrowthInside0LastX128, positionFeeGrowthInside1LastX128, tokensOwed0, tokensOwed1, }); } async _fees(feeParams) { let amount0 = int_1.Uint256.from(0); let amount1 = int_1.Uint256.from(0); const pool = await this.poolStore.getImmutablePool(this.immutableContext, feeParams.token0, feeParams.token1, feeParams.fee); const [poolFeeGrowthInside0LastX128, poolFeeGrowthInside1LastX128] = await this._getFeeGrowthInside(pool, feeParams.tickLower, feeParams.tickUpper); amount0 = int_1.Uint256.from(FullMath.mulDiv(int_1.Uint256.from(poolFeeGrowthInside0LastX128).sub(feeParams.positionFeeGrowthInside0LastX128).toString(), feeParams.liquidity, FixedPoint128.Q128)).add(feeParams.tokensOwed0); amount1 = int_1.Uint256.from(FullMath.mulDiv(int_1.Uint256.from(poolFeeGrowthInside1LastX128).sub(feeParams.positionFeeGrowthInside1LastX128).toString(), feeParams.liquidity, FixedPoint128.Q128)).add(feeParams.tokensOwed1); return [amount0.toString(), amount1.toString()]; } async _getFeeGrowthInside(pool, tickLower, tickUpper) { let feeGrowthInside0X128 = int_1.Uint256.from(0); let feeGrowthInside1X128 = int_1.Uint256.from(0); const { tick: tickCurrent } = pool.slot0; const { feeGrowthOutside0X128: lowerFeeGrowthOutside0X128, feeGrowthOutside1X128: lowerFeeGrowthOutside1X128 } = await pool.getTick(tickLower); const { feeGrowthOutside0X128: upperFeeGrowthOutside0X128, feeGrowthOutside1X128: upperFeeGrowthOutside1X128 } = await pool.getTick(tickUpper); if (int_1.Int24.from(tickCurrent).lt(tickLower)) { feeGrowthInside0X128 = int_1.Uint256.from(lowerFeeGrowthOutside0X128).sub(upperFeeGrowthOutside0X128); feeGrowthInside1X128 = int_1.Uint256.from(lowerFeeGrowthOutside1X128).sub(upperFeeGrowthOutside1X128); } else if (int_1.Int24.from(tickCurrent).lt(tickUpper)) { const { feeGrowthGlobal0X128 } = pool; const { feeGrowthGlobal1X128 } = pool; feeGrowthInside0X128 = int_1.Uint256.from(feeGrowthGlobal0X128).sub(lowerFeeGrowthOutside0X128).sub(upperFeeGrowthOutside0X128); feeGrowthInside1X128 = int_1.Uint256.from(feeGrowthGlobal1X128).sub(lowerFeeGrowthOutside1X128).sub(upperFeeGrowthOutside1X128); } else { feeGrowthInside0X128 = int_1.Uint256.from(upperFeeGrowthOutside0X128).sub(lowerFeeGrowthOutside0X128); feeGrowthInside1X128 = int_1.Uint256.from(upperFeeGrowthOutside1X128).sub(lowerFeeGrowthOutside1X128); } return [feeGrowthInside0X128.toString(), feeGrowthInside1X128.toString()]; } async _metadataToIPFS(metadata) { const cid = await IPFSHash.of(Buffer.from(JSON.stringify(metadata, null, 0), 'utf8'), { cidVersion: 1, rawLeaves: true, }); return `ipfs://${cid}`; } async _saveTokenURI(tokenId) { const metadata = await this.getMetadata(tokenId); const tokenURI = await this._metadataToIPFS(metadata); const encodedTokenURI = codec_1.codec.encode(schema_1.tokenUriNFTAttributeSchema, { tokenURI }); await this.nftMethod.setAttributes(this.mutableContext.context, constants_1.TOKENURI_ATTTRIBUTE, PositionKey.getNFTId(this.chainId, this.collectionId, tokenId), encodedTokenURI); return { tokenURI, metadata }; } async _savePosition(tokenId, position) { const encodedPosition = codec_1.codec.encode(schema_1.dexNFTAttributeSchema, position); await this.nftMethod.setAttributes(this.mutableContext.context, this.moduleName, PositionKey.getNFTId(this.chainId, this.collectionId, tokenId), encodedPosition); } _checkImmutableDependency() { if (!this.immutableDependencyReady) { throw new Error('dependencies not configured'); } } _checkMutableDependency() { if (!this.mutableDependencyReady) { throw new Error('dependencies not configured'); } } async _pay(token, payer, recipient, value) { await this.tokenMethod.transfer(this.mutableContext.context, payer, recipient, token, BigInt(value)); } async _mintCallback(amount0Owed, amount1Owed, data) { const decoded = JSON.parse(data); const pool = await this.poolStore.getMutablePool(this.mutableContext, Buffer.from(decoded.poolKey.token0, 'hex'), Buffer.from(decoded.poolKey.token1, 'hex'), decoded.poolKey.fee); if (int_1.Uint256.from(amount0Owed).gt(0)) { await this._pay(Buffer.from(decoded.poolKey.token0, 'hex'), Buffer.from(decoded.payer, 'hex'), pool.address, amount0Owed); } if (int_1.Uint256.from(amount1Owed).gt(0)) { await this._pay(Buffer.from(decoded.poolKey.token1, 'hex'), Buffer.from(decoded.payer, 'hex'), pool.address, amount1Owed); } } _checkDeadline(deadline) { if (int_1.Uint256.from(this.mutableContext.timestamp).gt(deadline)) throw new Error('Transaction too old'); } async _addLiquidity(params) { const poolKey = { token0: params.token0, token1: params.token1, fee: params.fee, }; const pool = await this.poolStore.getMutablePool(this.mutableContext, params.token0, params.token1, params.fee); const { sqrtPriceX96 } = pool.slot0; const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower); const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper); const liquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, params.amount0Desired, params.amount1Desired); const data = JSON.stringify({ poolKey: { token0: poolKey.token0.toString('hex'), token1: poolKey.token1.toString('hex'), fee: poolKey.fee, }, payer: this.mutableContext.senderAddress.toString('hex'), }); const [amount0, amount1] = await pool.mint(params.recipient, params.tickLower, params.tickUpper, liquidity, data, this._mintCallback.bind(this)); if (int_1.Uint256.from(amount0).lt(params.amount0Min) || int_1.Uint256.from(amount1).lt(params.amount1Min)) { throw new Error('Price slippage check'); } return [liquidity, amount0, amount1, pool]; } async _isAuthorizedForToken(sender, tokenId) { const nft = await this.nftMethod.getNFT(this.mutableContext.context, PositionKey.getNFTId(this.chainId, this.collectionId, tokenId)); if (nft.owner.compare(sender) !== 0) { throw new Error('Not approved'); } } } exports.NonfungiblePositionManager = NonfungiblePositionManager; //# sourceMappingURL=position_manager.js.map