From bedd0c75752fdefa7b37ffb59ce32786e067b363 Mon Sep 17 00:00:00 2001
From: jinoosss <jwchoi@onbloc.xyz>
Date: Wed, 13 Dec 2023 21:57:44 +0900
Subject: [PATCH] feat: [GSW-468] Implements Remove Position

---
 .../my-liquidity-header/MyLiquidityHeader.tsx |   7 +-
 .../pool/my-liquidity/MyLiquidity.tsx         |   5 +-
 .../RemoveLiquiditySelectListItem.tsx         | 126 +++++++++---------
 .../RemoveLiquiditySelectList.tsx             |  50 +++----
 .../RemoveLiquiditySelectResult.tsx           | 108 +++------------
 .../remove-liquidity/RemoveLiquidity.tsx      |  61 ++++-----
 .../RemovePositionModal.styles.ts             |  10 +-
 .../RemovePositionModal.tsx                   | 118 +++++++---------
 .../SelectLiquidityItem.tsx                   |   4 +-
 .../MyLiquidityContainer.tsx                  |  26 ++--
 .../RemoveLiquidityContainer.tsx              |  88 +++++++-----
 .../RemovePositionModalContainer.tsx          |  35 ++++-
 .../hooks/earn/use-remove-position-modal.tsx  |  16 ++-
 .../web/src/hooks/stake/use-remove-data.ts    |  98 ++++++++++++++
 .../position/position-repository-impl.ts      |  39 +++---
 .../position/position-repository.ts           |   6 +-
 .../request/decrease-liquidity-request.ts     |   2 +-
 .../request/remove-liquidity-request.ts       |   5 +
 18 files changed, 438 insertions(+), 366 deletions(-)
 create mode 100644 packages/web/src/hooks/stake/use-remove-data.ts
 create mode 100644 packages/web/src/repositories/position/request/remove-liquidity-request.ts

diff --git a/packages/web/src/components/pool/my-liquidity-header/MyLiquidityHeader.tsx b/packages/web/src/components/pool/my-liquidity-header/MyLiquidityHeader.tsx
index 63ebf7724..869b4935b 100644
--- a/packages/web/src/components/pool/my-liquidity-header/MyLiquidityHeader.tsx
+++ b/packages/web/src/components/pool/my-liquidity-header/MyLiquidityHeader.tsx
@@ -5,19 +5,18 @@ import React from "react";
 import { HeaderWrapper } from "./MyLiquidityHeader.styles";
 
 interface MyLiquidityHeaderProps {
-  connected: boolean;
-  isSwitchNetwork: boolean;
+  availableRemovePosition: boolean;
   handleClickAddPosition: () => void;
   handleClickRemovePosition: () => void;
 }
 
-const MyLiquidityHeader: React.FC<MyLiquidityHeaderProps> = ({ connected, isSwitchNetwork, handleClickAddPosition, handleClickRemovePosition }) => {
+const MyLiquidityHeader: React.FC<MyLiquidityHeaderProps> = ({ availableRemovePosition, handleClickAddPosition, handleClickRemovePosition }) => {
   return (
     <HeaderWrapper>
       <h2>My Positions</h2>
       <div className="button-wrap">
         <Button
-          disabled={!connected || isSwitchNetwork}
+          disabled={!availableRemovePosition}
           text="Remove Position"
           onClick={handleClickRemovePosition}
           style={{
diff --git a/packages/web/src/components/pool/my-liquidity/MyLiquidity.tsx b/packages/web/src/components/pool/my-liquidity/MyLiquidity.tsx
index 047e204bd..4336d867c 100644
--- a/packages/web/src/components/pool/my-liquidity/MyLiquidity.tsx
+++ b/packages/web/src/components/pool/my-liquidity/MyLiquidity.tsx
@@ -17,6 +17,7 @@ interface MyLiquidityProps {
   onScroll: () => void;
   currentIndex: number;
   claimAll: () => void;
+  availableRemovePosition: boolean;
 }
 
 const MyLiquidity: React.FC<MyLiquidityProps> = ({
@@ -30,13 +31,13 @@ const MyLiquidity: React.FC<MyLiquidityProps> = ({
   onScroll,
   currentIndex,
   claimAll,
+  availableRemovePosition,
 }) => {
   return (
     <MyLiquidityWrapper>
       <div className="liquidity-wrap">
         <MyLiquidityHeader
-          connected={connected}
-          isSwitchNetwork={isSwitchNetwork}
+          availableRemovePosition={availableRemovePosition}
           handleClickAddPosition={handleClickAddPosition}
           handleClickRemovePosition={handleClickRemovePosition}
         />
diff --git a/packages/web/src/components/remove/remove-liquidity-select-list-item/RemoveLiquiditySelectListItem.tsx b/packages/web/src/components/remove/remove-liquidity-select-list-item/RemoveLiquiditySelectListItem.tsx
index 27768afc8..e7c8ff02a 100644
--- a/packages/web/src/components/remove/remove-liquidity-select-list-item/RemoveLiquiditySelectListItem.tsx
+++ b/packages/web/src/components/remove/remove-liquidity-select-list-item/RemoveLiquiditySelectListItem.tsx
@@ -1,107 +1,107 @@
 import DoubleLogo from "@components/common/double-logo/DoubleLogo";
 import Tooltip from "@components/common/tooltip/Tooltip";
-import React, { useCallback, useMemo, useRef, useState, useEffect } from "react";
+import React, { useMemo } from "react";
 import { RemoveLiquiditySelectListItemWrapper, TooltipWrapperContent } from "./RemoveLiquiditySelectListItem.styles";
 import Badge, { BADGE_TYPE } from "@components/common/badge/Badge";
-import { convertLiquidity } from "@utils/stake-position-utils";
 import { PoolPositionModel } from "@models/position/pool-position-model";
+import { tooltipWrapper } from "@components/stake/select-lilquidity-list-item/SelectLiquidityListItem.styles";
+import { makeDisplayTokenAmount } from "@utils/token-utils";
+import { numberToUSD } from "@utils/number-utils";
+import { SwapFeeTierInfoMap } from "@constants/option.constant";
+import { makeSwapFeeTier } from "@utils/swap-utils";
 
 interface RemoveLiquiditySelectListItemProps {
-  selected: boolean;
   position: PoolPositionModel;
-  select: (id: string) => void;
-  width: number;
+  checkedList: string[];
+  onCheckedItem: (checked: boolean, path: string) => void;
+  disabled?: boolean;
 }
 
 interface TooltipProps {
-  selectable: boolean;
+  position: PoolPositionModel;
+  disabled: boolean;
 }
 
-const TooltipContent: React.FC<TooltipProps> = ({ selectable }) => {
+const TooltipContent: React.FC<TooltipProps> = ({ position, disabled }) => {
   return (
     <TooltipWrapperContent>
-      <div>
-        <div className="title">Token ID</div>
-        <div className="title">#982932</div>
-      </div>
-      <div>
-        <div className="value">
-          <img src="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39/logo.png" />
-          GNS
+      <div css={tooltipWrapper()}>
+        <div>
+          <div className="title">Token ID</div>
+          <div className="title">#{position.id}</div>
         </div>
-        <div className="value">50.05881</div>
-      </div>
-      <div>
-        <div className="value">
-          <img src="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39/logo.png" />
-          GNS
+        <div>
+          <div className="value">
+            <img src={position.pool.tokenA.logoURI} alt="token logo" />
+            {position.pool.tokenA.symbol}
+          </div>
+          <div className="value">{makeDisplayTokenAmount(position.pool.tokenA, position.token0Balance)}</div>
+        </div>
+        <div>
+          <div className="value">
+            <img src={position.pool.tokenB.logoURI} alt="token logo" />
+            {position.pool.tokenB.symbol}
+          </div>
+          <div className="value">{makeDisplayTokenAmount(position.pool.tokenB, position.token1Balance)}</div>
         </div>
-        <div className="value">50.05881</div>
       </div>
-      {selectable && <div className="divider"></div>}
-      {selectable && <div className="unstake-description">
-        *You need to unstake your position first.
-      </div>}
+      {!disabled && <div className="divider"></div>}
+      {!disabled && (
+        <div className="unstake-description">
+          *You need to unstake your position first.
+        </div>
+      )}
     </TooltipWrapperContent>
   );
 };
 
 const RemoveLiquiditySelectListItem: React.FC<RemoveLiquiditySelectListItemProps> = ({
-  selected,
   position,
-  select,
-  width,
+  checkedList,
+  onCheckedItem,
+  disabled = false,
 }) => {
-  const [checkWidth, setIsCheckWidth] = useState(true);
-  const leftDivRef = useRef<HTMLDivElement>(null);
-  const liquidityRef = useRef<HTMLDivElement>(null);
+  const checked = useMemo(() => {
+    return checkedList.includes(position.id);
+  }, [checkedList, position.id]);
 
-  const selectable = useMemo(() => {
-    return position.unclaimedFee0Amount + position.unclaimedFee1Amount > 0;
-  }, [position]);
+  const tokenA = useMemo(() => {
+    return position.pool.tokenA;
+  }, [position.pool.tokenA]);
 
-  const doubleLogo = useMemo(() => {
-    const { tokenA, tokenB } = position.pool;
-    return {
-      left: tokenA.logoURI,
-      right: tokenB.logoURI,
-    };
-  }, [position]);
+  const tokenB = useMemo(() => {
+    return position.pool.tokenB;
+  }, [position.pool.tokenB]);
 
-  const onChangeCheckbox = useCallback(() => {
-    select(position.id);
-  }, [position.id, select]);
+  const liquidityUSD = useMemo(() => {
+    return numberToUSD(Number(position.positionUsdValue));
+  }, [position.positionUsdValue]);
 
-  useEffect(() => {
-    if (typeof window !== "undefined") {
-      const windowWidth = Math.min(width, 500);
-      const totalWidth = (leftDivRef?.current?.offsetWidth || 0) + (liquidityRef?.current?.offsetWidth || 0) + 100;
-      setIsCheckWidth(windowWidth > totalWidth);
-    }
-  }, [liquidityRef.current, leftDivRef.current, width]);
+  const feeStr = useMemo(() => {
+    return SwapFeeTierInfoMap[makeSwapFeeTier(position.pool.fee)].rateStr;
+  }, [position]);
 
   return (
-    <RemoveLiquiditySelectListItemWrapper selected={selected}>
-      <div className="left-content" ref={leftDivRef}>
+    <RemoveLiquiditySelectListItemWrapper selected={checked}>
+      <div className="left-content" >
         <input
           id={`checkbox-item-${position.id}`}
           type="checkbox"
-          disabled={!selectable}
-          checked={selected}
-          onChange={onChangeCheckbox}
+          disabled={disabled}
+          checked={checked}
+          onChange={e => onCheckedItem(e.target.checked, position.id)}
         />
         <label htmlFor={`checkbox-item-${position.id}`} />
-        <DoubleLogo {...doubleLogo} size={24} />
+        <DoubleLogo left={tokenA.logoURI} right={tokenB.logoURI} size={24} />
         <Tooltip
           placement="top"
-          FloatingContent={<TooltipContent selectable={!selectable} />}
+          FloatingContent={<TooltipContent position={position} disabled={disabled} />}
         >
-          <span className="token-id">GNS/GNOT</span>
+          <span className="token-id">{`${tokenA.symbol}/${tokenB.symbol}`}</span>
         </Tooltip>
-        <Badge text="0.3%" type={BADGE_TYPE.DARK_DEFAULT} />
+        <Badge text={feeStr} type={BADGE_TYPE.DARK_DEFAULT} />
       </div>
-      <span className="liquidity-value-fake" ref={liquidityRef}>${position.liquidity.toLocaleString()}</span>
-      <span className="liquidity-value" >${!checkWidth ? convertLiquidity(position.liquidity.toString()) : position.liquidity.toLocaleString()}</span>
+      <span className="liquidity-value" >{liquidityUSD}</span>
     </RemoveLiquiditySelectListItemWrapper>
   );
 };
diff --git a/packages/web/src/components/remove/remove-liquidity-select-list/RemoveLiquiditySelectList.tsx b/packages/web/src/components/remove/remove-liquidity-select-list/RemoveLiquiditySelectList.tsx
index d3d46dcbb..896d2b4db 100644
--- a/packages/web/src/components/remove/remove-liquidity-select-list/RemoveLiquiditySelectList.tsx
+++ b/packages/web/src/components/remove/remove-liquidity-select-list/RemoveLiquiditySelectList.tsx
@@ -1,30 +1,26 @@
-import React, { useCallback } from "react";
+import React from "react";
 import { RemoveLiquiditySelectListWrapper } from "./RemoveLiquiditySelectList.styles";
 import RemoveLiquiditySelectListItem from "../remove-liquidity-select-list-item/RemoveLiquiditySelectListItem";
 import { PoolPositionModel } from "@models/position/pool-position-model";
 
 interface RemoveLiquiditySelectListProps {
-  selectedAll: boolean;
-  positions: PoolPositionModel[];
-  selectedIds: string[];
-  select: (id: string) => void;
-  selectAll: () => void;
-  width: number;
+  stakedPositions: PoolPositionModel[];
+  unstakedPositions: PoolPositionModel[];
+  checkedList: string[];
+  onCheckedItem: (checked: boolean, path: string) => void;
+  onCheckedAll: (checked: boolean) => void;
+  checkedAll: boolean;
 }
 
 const RemoveLiquiditySelectList: React.FC<RemoveLiquiditySelectListProps> = ({
-  selectedAll,
-  positions,
-  selectedIds,
-  select,
-  selectAll,
-  width,
+  stakedPositions,
+  unstakedPositions,
+  checkedList,
+  onCheckedItem,
+  onCheckedAll,
+  checkedAll,
 }) => {
 
-  const isSelectLiquidity = useCallback((position: PoolPositionModel) => {
-    return selectedIds.findIndex(id => id === position.id) > -1;
-  }, [selectedIds]);
-
   return (
     <RemoveLiquiditySelectListWrapper>
       <div className="checked-all-wrap">
@@ -32,8 +28,8 @@ const RemoveLiquiditySelectList: React.FC<RemoveLiquiditySelectListProps> = ({
           <input
             id="checkbox-all"
             type="checkbox"
-            checked={selectedAll}
-            onChange={selectAll}
+            checked={checkedAll}
+            onChange={e => onCheckedAll(e.target.checked)}
           />
           <label htmlFor="checkbox-all" />
           <span className="custom-label">Select All</span>
@@ -41,13 +37,21 @@ const RemoveLiquiditySelectList: React.FC<RemoveLiquiditySelectListProps> = ({
         <span>Liquidity</span>
       </div>
       <ul>
-        {positions.map((position, index) => (
+        {unstakedPositions.map((position, index) => (
           <RemoveLiquiditySelectListItem
+            position={position}
+            checkedList={checkedList}
+            onCheckedItem={onCheckedItem}
             key={index}
+          />
+        ))}
+        {stakedPositions.map((position, index) => (
+          <RemoveLiquiditySelectListItem
             position={position}
-            selected={isSelectLiquidity(position)}
-            select={select}
-            width={width}
+            checkedList={checkedList}
+            onCheckedItem={onCheckedItem}
+            key={index}
+            disabled
           />
         ))}
       </ul>
diff --git a/packages/web/src/components/remove/remove-liquidity-select-result/RemoveLiquiditySelectResult.tsx b/packages/web/src/components/remove/remove-liquidity-select-result/RemoveLiquiditySelectResult.tsx
index 6217a3d04..bbe8ad3c7 100644
--- a/packages/web/src/components/remove/remove-liquidity-select-result/RemoveLiquiditySelectResult.tsx
+++ b/packages/web/src/components/remove/remove-liquidity-select-result/RemoveLiquiditySelectResult.tsx
@@ -1,116 +1,48 @@
-import React, { useMemo } from "react";
+import React from "react";
 import { RemoveLiquiditySelectResultWrapper } from "./RemoveLiquiditySelectResult.styles";
-import BigNumber from "bignumber.js";
-import { TokenPairAmountInfo } from "@models/token/token-pair-amount-info";
-import { PositionMapper } from "@models/position/mapper/position-mapper";
 import { PoolPositionModel } from "@models/position/pool-position-model";
+import { useRemoveData } from "@hooks/stake/use-remove-data";
 
 interface RemoveLiquiditySelectResultProps {
-  selectedLiquidities: PoolPositionModel[];
-}
-
-function mappedTokenPairAmountMap(tokenPairAmounts: TokenPairAmountInfo[]) {
-  const initTokenMap: { [key in string]: {
-    symbol: string;
-    amount: string;
-    price: string;
-    logoURI: string;
-  } } = {};
-  const tokenPairMap = tokenPairAmounts.reduce((acc, current) => {
-    const tokenA = current.tokenA;
-    const tokenB = current.tokenB;
-    const tokenAAmount = current.tokenAAmount;
-    const tokenBAmount = current.tokenBAmount;
-    if (!acc[tokenA.path]) {
-      acc[tokenA.path] = {
-        symbol: tokenA.symbol,
-        logoURI: tokenA.logoURI,
-        amount: "0",
-        price: "0",
-      };
-    }
-    if (!acc[tokenB.path]) {
-      acc[tokenB.path] = {
-        symbol: tokenB.symbol,
-        logoURI: tokenB.logoURI,
-        amount: "0",
-        price: "0",
-      };
-    }
-    const token0Amount = BigNumber(acc[tokenA.path].amount).plus(tokenAAmount.amount || "0");
-    acc[tokenA.path] = {
-      ...acc[tokenA.path],
-      amount: token0Amount.toString(),
-    };
-    const token1Amount = BigNumber(acc[tokenB.path].amount).plus(tokenBAmount.amount || "0");
-    acc[tokenB.path] = {
-      ...acc[tokenB.path],
-      amount: token1Amount.toString(),
-    };
-    return acc;
-  }, initTokenMap);
-  return tokenPairMap;
+  positions: PoolPositionModel[];
 }
 
 const RemoveLiquiditySelectResult: React.FC<
   RemoveLiquiditySelectResultProps
 > = ({
-  selectedLiquidities
+  positions
 }) => {
-    const pooledTokenMap = useMemo(() => {
-      const tokenPairAmounts = selectedLiquidities.map(position => PositionMapper.toTokenPairAmount(position));
-      return mappedTokenPairAmountMap(tokenPairAmounts);
-    }, [selectedLiquidities]);
-
-    const unclaimedTokenMap = useMemo(() => {
-      const tokenPairAmounts = selectedLiquidities.map(position => PositionMapper.toTokenPairAmount(position));
-      return mappedTokenPairAmountMap(tokenPairAmounts);
-    }, [selectedLiquidities]);
+    const { pooledTokenInfos, unclaimedRewards, totalLiquidityUSD } = useRemoveData({ positions });
 
-    const totalAmount = useMemo(() => {
-      const pooledAmount = Object.values(pooledTokenMap)
-        .map(token => token.amount)
-        .reduce((acc, current) =>
-          BigNumber(acc).plus(current).toNumber(), 0);
-      const unclaimedAmount = Object.values(unclaimedTokenMap)
-        .map(token => token.amount)
-        .reduce((acc, current) =>
-          BigNumber(acc).plus(current).toNumber(), 0);
-      return BigNumber(pooledAmount + unclaimedAmount).toFormat();
-    }, [pooledTokenMap, unclaimedTokenMap]);
-
-    if (selectedLiquidities.length === 0) {
-      return <></>;
-    }
+    if (positions.length === 0) return <></>;
 
     return (
       <RemoveLiquiditySelectResultWrapper>
-        <ul>
-          {Object.keys(pooledTokenMap).map((path, index) => (
-            <li key={index} className="pooled-tokenA">
+        <ul className="pooled-section">
+          {pooledTokenInfos.map((pooledTokenInfo, index) => (
+            <li key={index}>
               <div className="main-info">
-                <img src={pooledTokenMap[path].logoURI} alt="pooled tokenA logo" />
-                <p>{`Pooled ${pooledTokenMap[path].symbol}`}</p>
-                <strong>{Number(pooledTokenMap[path].amount).toFixed(2)}</strong>
+                <img src={pooledTokenInfo.token.logoURI} alt="pooled token logo" />
+                <p>Pooled {pooledTokenInfo.token.symbol}</p>
+                <strong>{pooledTokenInfo.amount}</strong>
               </div>
-              <span className="dallor">{`$${Number(pooledTokenMap[path].amount).toFixed(2)}`}</span>
+              <span className="dallor">{pooledTokenInfo.amountUSD}</span>
             </li>
           ))}
-
-          {Object.keys(unclaimedTokenMap).map((path, index) => (
-            <li key={index} className="pooled-tokenA">
+          {unclaimedRewards.map((pooledTokenInfo, index) => (
+            <li key={index}>
               <div className="main-info">
-                <img src={unclaimedTokenMap[path].logoURI} alt="pooled tokenA logo" />
-                <p>{`Unclaimed ${unclaimedTokenMap[path].symbol} Fees`}</p>
-                <strong>{Number(unclaimedTokenMap[path].amount).toFixed(2)}</strong>
+                <img src={pooledTokenInfo.token.logoURI} alt="pooled token logo" />
+                <p>Unclaimed {pooledTokenInfo.token.symbol}</p>
+                <strong>{pooledTokenInfo.amount}</strong>
               </div>
-              <span className="dallor">{`$${Number(unclaimedTokenMap[path].amount).toFixed(2)}`}</span>
+              <span className="dallor">{pooledTokenInfo.amountUSD}</span>
             </li>
           ))}
         </ul>
         <div className="total-section">
           <h5>Total Amount</h5>
-          <span className="total-value">{`$${Number(totalAmount.replace(/,/g, "") || 0).toFixed(2)}`}</span>
+          <span className="total-value">{totalLiquidityUSD}</span>
         </div>
       </RemoveLiquiditySelectResultWrapper>
     );
diff --git a/packages/web/src/components/remove/remove-liquidity/RemoveLiquidity.tsx b/packages/web/src/components/remove/remove-liquidity/RemoveLiquidity.tsx
index 652caefac..957b52a27 100644
--- a/packages/web/src/components/remove/remove-liquidity/RemoveLiquidity.tsx
+++ b/packages/web/src/components/remove/remove-liquidity/RemoveLiquidity.tsx
@@ -1,62 +1,59 @@
 import Button, { ButtonHierarchy } from "@components/common/button/Button";
-import React, { useCallback, useMemo } from "react";
+import React, { useMemo } from "react";
 import { wrapper } from "./RemoveLiquidity.styles";
 import RemoveLiquiditySelectList from "../remove-liquidity-select-list/RemoveLiquiditySelectList";
 import RemoveLiquiditySelectResult from "../remove-liquidity-select-result/RemoveLiquiditySelectResult";
 import { PoolPositionModel } from "@models/position/pool-position-model";
 
 interface RemoveLiquidityProps {
-  selectedAll: boolean;
-  positions: PoolPositionModel[];
-  selectedIds: string[];
-  select: (id: string) => void;
-  selectAll: () => void;
+  stakedPositions: PoolPositionModel[];
+  unstakedPositions: PoolPositionModel[];
+  checkedList: string[];
+  onCheckedItem: (checked: boolean, path: string) => void;
+  onCheckedAll: (checked: boolean) => void;
+  checkedAll: boolean;
   removeLiquidity: () => void;
-  width: number;
 }
 
 const RemoveLiquidity: React.FC<RemoveLiquidityProps> = ({
-  selectedAll,
-  positions,
-  selectedIds,
-  select,
-  selectAll,
+  stakedPositions,
+  unstakedPositions,
+  checkedList,
+  onCheckedItem,
+  onCheckedAll,
+  checkedAll,
   removeLiquidity,
-  width,
 }) => {
-  const selectedLiquidites = useMemo(() => {
-    return positions.filter(lpPosition => selectedIds.includes(lpPosition.id));
-  }, [selectedIds, positions]);
 
-  const disabledConfirm = useMemo(() => {
-    return selectedLiquidites.length === 0;
-  }, [selectedLiquidites.length]);
+  const disabledRemoveLiquidity = useMemo(() => {
+    return checkedList.length === 0;
+  }, [checkedList.length]);
 
-  const onClickRemoveLiquidity = useCallback(() => {
-    removeLiquidity();
-  }, [removeLiquidity]);
+  const selectedPositions = useMemo(() => {
+    return stakedPositions.filter(position => checkedList.includes(position.id));
+  }, [checkedList, stakedPositions]);
 
   return (
     <div css={wrapper}>
       <h3 className="title">Remove Position</h3>
       <RemoveLiquiditySelectList
-        positions={positions}
-        selectedIds={selectedIds}
-        selectedAll={selectedAll}
-        select={select}
-        selectAll={selectAll}
-        width={width}
+        stakedPositions={stakedPositions}
+        unstakedPositions={unstakedPositions}
+        checkedList={checkedList}
+        onCheckedItem={onCheckedItem}
+        onCheckedAll={onCheckedAll}
+        checkedAll={checkedAll}
       />
-      <RemoveLiquiditySelectResult selectedLiquidities={selectedLiquidites} />
+      <RemoveLiquiditySelectResult positions={selectedPositions} />
       <Button
-        text={disabledConfirm ? "Select Position" : "Remove Position"}
-        disabled={disabledConfirm}
+        text={disabledRemoveLiquidity ? "Select Position" : "Remove Position"}
+        disabled={disabledRemoveLiquidity}
         style={{
           hierarchy: ButtonHierarchy.Primary,
           fullWidth: true,
         }}
         className="button-submit"
-        onClick={onClickRemoveLiquidity}
+        onClick={removeLiquidity}
       />
     </div>
   );
diff --git a/packages/web/src/components/remove/remove-position-modal/RemovePositionModal.styles.ts b/packages/web/src/components/remove/remove-position-modal/RemovePositionModal.styles.ts
index 3916b565c..bb2efe4a8 100644
--- a/packages/web/src/components/remove/remove-position-modal/RemovePositionModal.styles.ts
+++ b/packages/web/src/components/remove/remove-position-modal/RemovePositionModal.styles.ts
@@ -51,7 +51,7 @@ export const RemovePositionModalWrapper = styled.div`
       .box-item {
         width: 100%;
         ${mixins.flexbox("column", "flex-start", "flex-start")};
-        gap: 8px;
+        gap: 16px;
         
         h4 {
           ${fonts.body12}
@@ -150,7 +150,7 @@ export const RemovePositionModalWrapper = styled.div`
       > div {
         width: 100%;
         .button-confirm {
-          gap: 8px;
+          gap: 16px;
           height: 57px;
           span {
             ${fonts.body7}
@@ -183,8 +183,12 @@ export const RemovePositionModalWrapper = styled.div`
       }
     }
   }
-`;
 
+  .button-wrapper {
+    display: flex;
+    width: 100%;
+  }
+`;
 
 export const Divider = styled.div`
   width: 100%;
diff --git a/packages/web/src/components/remove/remove-position-modal/RemovePositionModal.tsx b/packages/web/src/components/remove/remove-position-modal/RemovePositionModal.tsx
index 93809c56a..2090a5e5f 100644
--- a/packages/web/src/components/remove/remove-position-modal/RemovePositionModal.tsx
+++ b/packages/web/src/components/remove/remove-position-modal/RemovePositionModal.tsx
@@ -2,15 +2,20 @@ import Badge, { BADGE_TYPE } from "@components/common/badge/Badge";
 import Button, { ButtonHierarchy } from "@components/common/button/Button";
 import DoubleLogo from "@components/common/double-logo/DoubleLogo";
 import IconClose from "@components/common/icons/IconCancel";
+import { useRemoveData } from "@hooks/stake/use-remove-data";
+import { PoolPositionModel } from "@models/position/pool-position-model";
+import { numberToUSD } from "@utils/number-utils";
 import React, { useCallback } from "react";
 import { Divider, RemovePositionModalWrapper } from "./RemovePositionModal.styles";
 
 interface Props {
+  positions: PoolPositionModel[];
   close: () => void;
   onSubmit: () => void;
 }
 
-const RemovePositionModal: React.FC<Props> = ({ close, onSubmit }) => {
+const RemovePositionModal: React.FC<Props> = ({ positions, close, onSubmit }) => {
+  const { unclaimedRewards, totalLiquidityUSD } = useRemoveData({ positions });
   const onClickClose = useCallback(() => {
     close();
   }, [close]);
@@ -28,84 +33,61 @@ const RemovePositionModal: React.FC<Props> = ({ close, onSubmit }) => {
           <div className="box-item">
             <h4>Positions</h4>
             <div className="item-content">
-              <div>
-                <div className="label-logo">
-                  <DoubleLogo
-                    left="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39/logo.png"
-                    right="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
-                    size={24}
-                  />
-                  <div>GNS/GNOT</div>
-                  <Badge className="position-bar" text="0.3%" type={BADGE_TYPE.DARK_DEFAULT} />
-                </div>
-                <div className="value">$145,541.10</div>
-              </div>
-              <div>
-                <div className="label-logo">
-                  <DoubleLogo
-                    left="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39/logo.png"
-                    right="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
-                    size={24}
-                  />
-                  <div>GNS/GNOT</div>
-                  <Badge className="position-bar" text="0.3%" type={BADGE_TYPE.DARK_DEFAULT} />
-                </div>
-                <div className="value">$145,541.10</div>
-              </div>
-            </div>
-          </div>
-          <div className="box-item box-item-unclaim">
-            <h4>Unclaimed Fees</h4>
-            <div className="item-content">
-              <div>
-                <div>
+              {positions.map((position, index) => (
+                <div key={index}>
                   <div className="label-logo">
-                    <img className="image-logo" src="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png" alt="logo" />
-                    <div>GNS</div>
+                    <DoubleLogo
+                      left={position.pool.tokenA.logoURI}
+                      right={position.pool.tokenB.logoURI}
+                      size={24}
+                    />
+                    <div>{`${position.pool.tokenA.symbol}/${position.pool.tokenB.symbol}`}</div>
+                    <Badge className="position-bar" text="0.3%" type={BADGE_TYPE.DARK_DEFAULT} />
                   </div>
-                  <div className="value">15,000.005</div>
-                </div>
-                <div className="sub-value">
-                  $15,000.01
+                  <div className="value">{numberToUSD(Number(position.positionUsdValue))}</div>
                 </div>
+              ))}
+            </div>
+            <div className="box-item box-item-unclaim">
+              <h4>Unclaimed Fees</h4>
+              <div className="item-content">
+                {unclaimedRewards.map((rewardInfo, index) => (
+                  <div key={index}>
+                    <div>
+                      <div className="label-logo">
+                        <img className="image-logo" src={rewardInfo.token.logoURI} alt="logo" />
+                        <div>{rewardInfo.token.symbol}</div>
+                      </div>
+                      <div className="value">{rewardInfo.amount}</div>
+                    </div>
+                    <div className="sub-value">{rewardInfo.amountUSD}</div>
+                  </div>
+                ))}
               </div>
-              <div>
+            </div>
+            <Divider />
+            <div className="box-item">
+              <div className="item-content">
                 <div>
-                  <div className="label-logo">
-                    <img className="image-logo" src="https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png" alt="logo" />
-                    <div>GNS</div>
+                  <div className="label-large">
+                    Total Amount
                   </div>
-                  <div className="value">15,000.005</div>
-                </div>
-                <div className="sub-value">
-                  $15,000.01
+                  <div className="value-large">{totalLiquidityUSD}</div>
                 </div>
               </div>
-              
             </div>
-          </div>
-          <Divider />
-          <div className="box-item">
-            <div className="item-content">
-              <div>
-                <div className="label-large">
-                  Total Amount
-                </div>
-                <div className="value-large">$291,082.2</div>
-              </div>
+            <div className="button-wrapper">
+              <Button
+                text="Confirm Remove Position"
+                style={{
+                  hierarchy: ButtonHierarchy.Primary,
+                  fullWidth: true,
+                }}
+                className="button-confirm"
+                onClick={onSubmit}
+              />
             </div>
           </div>
-          <div>
-            <Button
-              text="Confirm Remove Position"
-              style={{
-                hierarchy: ButtonHierarchy.Primary,
-                fullWidth: true,
-              }}
-              className="button-confirm"
-              onClick={onSubmit}
-            />
-          </div>
         </div>
       </div>
     </RemovePositionModalWrapper>
diff --git a/packages/web/src/components/unstake/select-liquidity-item/SelectLiquidityItem.tsx b/packages/web/src/components/unstake/select-liquidity-item/SelectLiquidityItem.tsx
index 19dfca7bb..e09fe1c89 100644
--- a/packages/web/src/components/unstake/select-liquidity-item/SelectLiquidityItem.tsx
+++ b/packages/web/src/components/unstake/select-liquidity-item/SelectLiquidityItem.tsx
@@ -58,8 +58,8 @@ const SelectLiquidityItem: React.FC<SelectLiquidityItemProps> = ({
   }, [position.pool.tokenB]);
 
   const liquidityUSD = useMemo(() => {
-    return numberToUSD(Number(position.liquidity));
-  }, [position.liquidity]);
+    return numberToUSD(Number(position.positionUsdValue));
+  }, [position.positionUsdValue]);
 
   return (
     <li css={wrapper(checked)}>
diff --git a/packages/web/src/containers/my-liquidity-container/MyLiquidityContainer.tsx b/packages/web/src/containers/my-liquidity-container/MyLiquidityContainer.tsx
index 34749b9da..8450c5b1e 100644
--- a/packages/web/src/containers/my-liquidity-container/MyLiquidityContainer.tsx
+++ b/packages/web/src/containers/my-liquidity-container/MyLiquidityContainer.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useEffect, useRef, useState } from "react";
+import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
 import MyLiquidity from "@components/pool/my-liquidity/MyLiquidity";
 import { useWindowSize } from "@hooks/common/use-window-size";
 import { useWallet } from "@hooks/wallet/use-wallet";
@@ -19,15 +19,12 @@ const MyLiquidityContainer: React.FC = () => {
   const { getPositionsByPoolId } = usePositionData();
   const { claimAll } = usePosition(positions);
 
-  useEffect(() => {
-    const poolPath = router.query["pool-path"] as string;
-    if (!poolPath) {
-      return;
+  const availableRemovePosition = useMemo(() => {
+    if (!connectedWallet || isSwitchNetwork) {
+      return false;
     }
-    if (account?.address) {
-      getPositionsByPoolId(poolPath).then(setPositions);
-    }
-  }, [account?.address, getPositionsByPoolId, router.query]);
+    return positions.length > 0;
+  }, [connectedWallet, isSwitchNetwork, positions.length]);
 
   const handleClickAddPosition = useCallback(() => {
     router.push(`${router.asPath}/add`);
@@ -52,6 +49,16 @@ const MyLiquidityContainer: React.FC = () => {
     });
   }, [claimAll, router]);
 
+  useEffect(() => {
+    const poolPath = router.query["pool-path"] as string;
+    if (!poolPath) {
+      return;
+    }
+    if (account?.address) {
+      getPositionsByPoolId(poolPath).then(setPositions);
+    }
+  }, [account?.address, getPositionsByPoolId, router.query]);
+
   return (
     <MyLiquidity
       positions={positions}
@@ -64,6 +71,7 @@ const MyLiquidityContainer: React.FC = () => {
       onScroll={handleScroll}
       currentIndex={currentIndex}
       claimAll={claimAllReward}
+      availableRemovePosition={availableRemovePosition}
     />
   );
 };
diff --git a/packages/web/src/containers/remove-liquidity-container/RemoveLiquidityContainer.tsx b/packages/web/src/containers/remove-liquidity-container/RemoveLiquidityContainer.tsx
index dfc14a9fe..82892a95b 100644
--- a/packages/web/src/containers/remove-liquidity-container/RemoveLiquidityContainer.tsx
+++ b/packages/web/src/containers/remove-liquidity-container/RemoveLiquidityContainer.tsx
@@ -1,59 +1,81 @@
 import RemoveLiquidity from "@components/remove/remove-liquidity/RemoveLiquidity";
 import React, { useCallback, useEffect, useMemo, useState } from "react";
 import { useRemovePositionModal } from "@hooks/earn/use-remove-position-modal";
-import { useWindowSize } from "@hooks/common/use-window-size";
 import { PoolPositionModel } from "@models/position/pool-position-model";
 import { usePositionData } from "@hooks/common/use-position-data";
+import { useRouter } from "next/router";
+import { useWallet } from "@hooks/wallet/use-wallet";
 
 const RemoveLiquidityContainer: React.FC = () => {
-  const [selectedIds, setSelectedIds] = useState<string[]>([]);
-  const { width } = useWindowSize();
-  const { openModal } = useRemovePositionModal();
+  const router = useRouter();
+  const { account } = useWallet();
   const [positions, setPositions] = useState<PoolPositionModel[]>([]);
-  const { getPositions } = usePositionData();
+  const [checkedList, setCheckedList] = useState<string[]>([]);
+  const { getPositionsByPoolId } = usePositionData();
+  const { openModal } = useRemovePositionModal({
+    positions,
+    selectedIds: checkedList,
+  });
 
-  useEffect(() => {
-    getPositions().then(setPositions);
-  }, [getPositions]);
-
-  const unstakedLiquidities = useMemo(() => {
-    return positions.filter(item => item.unclaimedFee0Amount + item.unclaimedFee1Amount > 0);
+  const stakedPositions = useMemo(() => {
+    return positions.filter(position => position.staked);
   }, [positions]);
 
-  const selectedAll = useMemo(() => {
-    return unstakedLiquidities.length === selectedIds.length;
-  }, [selectedIds.length, unstakedLiquidities.length]);
+  const unstakedPositions = useMemo(() => {
+    return positions.filter(position => !position.staked);
+  }, [positions]);
 
-  const selectAll = useCallback(() => {
-    if (selectedAll) {
-      setSelectedIds([]);
-      return;
+  const checkedAll = useMemo(() => {
+    if (unstakedPositions.length === 0) {
+      return false;
     }
-    const selectedIds = unstakedLiquidities.map(liquidity => liquidity.id);
-    setSelectedIds(selectedIds);
-  }, [selectedAll, unstakedLiquidities]);
+    return unstakedPositions.length === checkedList.length;
+  }, [unstakedPositions, checkedList]);
+
+  const onCheckedItem = useCallback(
+    (isChecked: boolean, path: string) => {
+      if (isChecked) {
+        return setCheckedList((prev: string[]) => [...prev, path]);
+      }
+      if (!isChecked && checkedList.includes(path)) {
+        return setCheckedList(checkedList.filter(el => el !== path));
+      }
+    },
+    [checkedList],
+  );
 
-  const select = useCallback((id: string) => {
-    if (selectedIds.includes(id)) {
-      setSelectedIds(selectedIds.filter((selectedId => selectedId !== id)));
+  const onCheckedAll = useCallback(() => {
+    if (checkedAll) {
+      setCheckedList([]);
       return;
     }
-    setSelectedIds([...selectedIds, id]);
-  }, [selectedIds]);
+    const checkedList = unstakedPositions.map(position => position.id);
+    setCheckedList(checkedList);
+  }, [checkedAll, unstakedPositions]);
 
   const removeLiquidity = useCallback(() => {
     openModal();
-  }, []);
+  }, [openModal]);
+
+  useEffect(() => {
+    const poolPath = router.query["pool-path"] as string;
+    if (!poolPath) {
+      return;
+    }
+    if (account?.address) {
+      getPositionsByPoolId(poolPath).then(setPositions);
+    }
+  }, [account?.address, getPositionsByPoolId, router.query]);
 
   return (
     <RemoveLiquidity
-      positions={positions}
-      selectedAll={selectedAll}
-      selectedIds={selectedIds}
-      select={select}
-      selectAll={selectAll}
+      stakedPositions={stakedPositions}
+      unstakedPositions={unstakedPositions}
+      checkedList={checkedList}
+      onCheckedItem={onCheckedItem}
+      onCheckedAll={onCheckedAll}
+      checkedAll={checkedAll}
       removeLiquidity={removeLiquidity}
-      width={width}
     />
   );
 };
diff --git a/packages/web/src/containers/remove-position-modal-container/RemovePositionModalContainer.tsx b/packages/web/src/containers/remove-position-modal-container/RemovePositionModalContainer.tsx
index 48410a063..b60a05ae7 100644
--- a/packages/web/src/containers/remove-position-modal-container/RemovePositionModalContainer.tsx
+++ b/packages/web/src/containers/remove-position-modal-container/RemovePositionModalContainer.tsx
@@ -1,19 +1,44 @@
 import RemovePositionModal from "@components/remove/remove-position-modal/RemovePositionModal";
 import { useClearModal } from "@hooks/common/use-clear-modal";
+import { useGnoswapContext } from "@hooks/common/use-gnoswap-context";
+import { useWallet } from "@hooks/wallet/use-wallet";
+import { PoolPositionModel } from "@models/position/pool-position-model";
+import { useRouter } from "next/router";
 import React, { useCallback } from "react";
 
-const RemovePositionModalContainer = () => {
+interface RemovePositionModalContainerProps {
+  positions: PoolPositionModel[];
+}
+
+const RemovePositionModalContainer = ({
+  positions,
+}: RemovePositionModalContainerProps) => {
+  const { account } = useWallet();
+  const { positionRepository } = useGnoswapContext();
+  const router = useRouter();
   const clearModal = useClearModal();
 
   const close = useCallback(() => {
     clearModal();
   }, [clearModal]);
 
-  const onSubmit = useCallback(() => {
-    clearModal();
-  }, [clearModal]);
+  const onSubmit = useCallback(async () => {
+    const address = account?.address;
+    if (!address) {
+      return null;
+    }
+    const lpTokenIds = positions.map(position => position.id);
+    const result = await positionRepository.removeLiquidity({
+      lpTokenIds,
+      caller: address
+    }).catch(() => null);
+    if (result) {
+      clearModal();
+      router.back();
+    }
+  }, [account?.address, clearModal, positionRepository, positions, router]);
 
-  return <RemovePositionModal close={close} onSubmit={onSubmit}/>;
+  return <RemovePositionModal positions={positions} close={close} onSubmit={onSubmit} />;
 };
 
 export default RemovePositionModalContainer;
diff --git a/packages/web/src/hooks/earn/use-remove-position-modal.tsx b/packages/web/src/hooks/earn/use-remove-position-modal.tsx
index 63dfd46ea..853cbdfae 100644
--- a/packages/web/src/hooks/earn/use-remove-position-modal.tsx
+++ b/packages/web/src/hooks/earn/use-remove-position-modal.tsx
@@ -1,20 +1,26 @@
 import RemovePositionModalContainer from "@containers/remove-position-modal-container/RemovePositionModalContainer";
+import { PoolPositionModel } from "@models/position/pool-position-model";
 import { CommonState } from "@states/index";
 import { useAtom } from "jotai";
-import { useCallback } from "react";
+import { useCallback, useMemo } from "react";
 
 export interface Props {
-  openModal: () => void;
+  positions: PoolPositionModel[];
+  selectedIds: string[];
 }
 
-export const useRemovePositionModal = (): Props => {
+export const useRemovePositionModal = ({ positions, selectedIds }: Props) => {
   const [, setOpenedModal] = useAtom(CommonState.openedModal);
   const [, setModalContent] = useAtom(CommonState.modalContent);
 
+  const selectedPositions = useMemo(() => {
+    return positions.filter(position => selectedIds.includes(position.id));
+  }, [positions, selectedIds]);
+
   const openModal = useCallback(() => {
     setOpenedModal(true);
-    setModalContent(<RemovePositionModalContainer />);
-  }, [setModalContent, setOpenedModal]);
+    setModalContent(<RemovePositionModalContainer positions={selectedPositions} />);
+  }, [selectedPositions, setModalContent, setOpenedModal]);
 
   return {
     openModal,
diff --git a/packages/web/src/hooks/stake/use-remove-data.ts b/packages/web/src/hooks/stake/use-remove-data.ts
new file mode 100644
index 000000000..f46f9be34
--- /dev/null
+++ b/packages/web/src/hooks/stake/use-remove-data.ts
@@ -0,0 +1,98 @@
+import { useTokenData } from "@hooks/token/use-token-data";
+import { PoolPositionModel } from "@models/position/pool-position-model";
+import { numberToUSD } from "@utils/number-utils";
+import { makeDisplayTokenAmount } from "@utils/token-utils";
+import { useMemo } from "react";
+
+export interface RemoveDataProps {
+  positions: PoolPositionModel[];
+}
+
+export const useRemoveData = ({ positions }: RemoveDataProps) => {
+  const { tokenPrices } = useTokenData();
+
+  const pooledTokenInfos = useMemo(() => {
+    if (positions.length === 0) {
+      return [];
+    }
+    const tokenA = positions[0].pool.tokenA;
+    const tokenB = positions[0].pool.tokenB;
+    const pooledTokenAAmount = positions.reduce(
+      (accum, position) => accum + position.token0Balance,
+      0n,
+    );
+    const pooledTokenBAmount = positions.reduce(
+      (accum, position) => accum + position.token1Balance,
+      0n,
+    );
+    const tokenAPrice = tokenPrices[tokenA.priceId]?.usd || 0;
+    const tokenBPrice = tokenPrices[tokenB.priceId]?.usd || 0;
+    const tokenAAmount =
+      makeDisplayTokenAmount(tokenA, Number(pooledTokenAAmount)) || 0;
+    const tokenBAmount =
+      makeDisplayTokenAmount(tokenB, Number(pooledTokenBAmount)) || 0;
+    return [
+      {
+        token: tokenA,
+        amount: tokenAAmount,
+        amountUSD: numberToUSD(tokenAAmount * Number(tokenAPrice)),
+      },
+      {
+        token: tokenB,
+        amount: tokenBAmount,
+        amountUSD: numberToUSD(tokenBAmount * Number(tokenBPrice)),
+      },
+    ];
+  }, [positions, tokenPrices]);
+
+  const unclaimedRewards = useMemo(() => {
+    if (positions.length === 0) {
+      return [];
+    }
+    const tokenA = positions[0].pool.tokenA;
+    const tokenB = positions[0].pool.tokenB;
+    const pooledTokenAAmount = positions.reduce(
+      (accum, position) => accum + position.unclaimedFee0Amount,
+      0n,
+    );
+    const pooledTokenBAmount = positions.reduce(
+      (accum, position) => accum + position.unclaimedFee1Amount,
+      0n,
+    );
+    const tokenAPrice = tokenPrices[tokenA.priceId]?.usd || 0;
+    const tokenBPrice = tokenPrices[tokenB.priceId]?.usd || 0;
+    const tokenAAmount =
+      makeDisplayTokenAmount(tokenA, Number(pooledTokenAAmount)) || 0;
+    const tokenBAmount =
+      makeDisplayTokenAmount(tokenB, Number(pooledTokenBAmount)) || 0;
+    return [
+      {
+        token: tokenA,
+        amount: tokenAAmount,
+        amountUSD: numberToUSD(tokenAAmount * Number(tokenAPrice)),
+      },
+      {
+        token: tokenB,
+        amount: tokenBAmount,
+        amountUSD: numberToUSD(tokenBAmount * Number(tokenBPrice)),
+      },
+    ];
+  }, [positions, tokenPrices]);
+
+  const totalLiquidityUSD = useMemo(() => {
+    if (positions.length === 0) {
+      return "-";
+    }
+    const totalUSDValue = positions.reduce(
+      (accum, position) => accum + Number(position.positionUsdValue),
+      0,
+    );
+    return numberToUSD(totalUSDValue);
+  }, [positions]);
+
+  return {
+    pooledTokenInfos,
+    unclaimedRewards,
+    totalLiquidityUSD,
+  };
+};
diff --git a/packages/web/src/repositories/position/position-repository-impl.ts b/packages/web/src/repositories/position/position-repository-impl.ts
index f1208d871..4b898c338 100644
--- a/packages/web/src/repositories/position/position-repository-impl.ts
+++ b/packages/web/src/repositories/position/position-repository-impl.ts
@@ -8,12 +8,12 @@ import {
   DEFAULT_TRANSACTION_DEADLINE,
 } from "@common/values";
 import { GnoProvider } from "@gnolang/gno-js-client";
-import { MAX_INT64 } from "@gnoswap-labs/swap-router";
 import { PositionMapper } from "@models/position/mapper/position-mapper";
 import { PositionModel } from "@models/position/position-model";
+import { MAX_INT256 } from "@utils/math.utils";
 import { PositionRepository } from "./position-repository";
 import { ClaimAllRequest } from "./request/claim-all-request";
-import { DecreaseLiquidityReqeust } from "./request/decrease-liquidity-request";
+import { RemoveLiquidityReqeust } from "./request/remove-liquidity-request";
 import { StakePositionsRequest } from "./request/stake-positions-request";
 import { UnstakePositionsRequest } from "./request/unstake-positions-request";
 import { PositionListResponse } from "./response";
@@ -124,28 +124,18 @@ export class PositionRepositoryImpl implements PositionRepository {
     return hash;
   };
 
-  decreaseLiquidity = async (
-    request: DecreaseLiquidityReqeust,
+  removeLiquidity = async (
+    request: RemoveLiquidityReqeust,
   ): Promise<string | null> => {
     if (this.walletClient === null) {
       throw new CommonError("FAILED_INITIALIZE_WALLET");
     }
-    const {
-      lpTokenId,
-      liquidity,
-      amountAMin,
-      amountBMax,
-      caller,
-      deadline = DEFAULT_TRANSACTION_DEADLINE,
-    } = request;
-    const messages = [];
-    messages.push(
+    const { lpTokenIds, caller } = request;
+    const messages = lpTokenIds.map(lpTokenId =>
       PositionRepositoryImpl.makeDecreaseLiquidityMessage(
         lpTokenId,
-        liquidity,
-        amountAMin,
-        amountBMax,
-        deadline,
+        MAX_INT256.toString(),
+        DEFAULT_TRANSACTION_DEADLINE,
         caller,
       ),
     );
@@ -167,7 +157,12 @@ export class PositionRepositoryImpl implements PositionRepository {
       send: "",
       pkg_path: POSITION_PATH,
       func: "Collect",
-      args: [lpTokenId, receipient, MAX_INT64.toString(), MAX_INT64.toString()],
+      args: [
+        lpTokenId,
+        receipient,
+        MAX_INT256.toString(),
+        MAX_INT256.toString(),
+      ],
     };
   }
 
@@ -216,8 +211,6 @@ export class PositionRepositoryImpl implements PositionRepository {
   private static makeDecreaseLiquidityMessage(
     lpTokenId: string,
     liquidity: string,
-    amountAMin: string,
-    amountBMin: string,
     deadeline: string,
     caller: string,
   ) {
@@ -226,7 +219,7 @@ export class PositionRepositoryImpl implements PositionRepository {
       send: "",
       pkg_path: POSITION_PATH,
       func: "DecreaseLiquidity",
-      args: [lpTokenId, liquidity, amountAMin, amountBMin, deadeline],
+      args: [lpTokenId, liquidity, deadeline],
     };
   }
 
@@ -237,8 +230,6 @@ export class PositionRepositoryImpl implements PositionRepository {
     return this.makeDecreaseLiquidityMessage(
       lpTokenId,
       "0",
-      "0",
-      "0",
       DEFAULT_TRANSACTION_DEADLINE,
       caller,
     );
diff --git a/packages/web/src/repositories/position/position-repository.ts b/packages/web/src/repositories/position/position-repository.ts
index e8bb5e812..57cd27c27 100644
--- a/packages/web/src/repositories/position/position-repository.ts
+++ b/packages/web/src/repositories/position/position-repository.ts
@@ -1,6 +1,6 @@
 import { PositionModel } from "@models/position/position-model";
 import { ClaimAllRequest } from "./request/claim-all-request";
-import { DecreaseLiquidityReqeust } from "./request/decrease-liquidity-request";
+import { RemoveLiquidityReqeust } from "./request/remove-liquidity-request";
 import { StakePositionsRequest } from "./request/stake-positions-request";
 import { UnstakePositionsRequest } from "./request/unstake-positions-request";
 
@@ -15,7 +15,5 @@ export interface PositionRepository {
     request: UnstakePositionsRequest,
   ) => Promise<string | null>;
 
-  decreaseLiquidity: (
-    request: DecreaseLiquidityReqeust,
-  ) => Promise<string | null>;
+  removeLiquidity: (request: RemoveLiquidityReqeust) => Promise<string | null>;
 }
diff --git a/packages/web/src/repositories/position/request/decrease-liquidity-request.ts b/packages/web/src/repositories/position/request/decrease-liquidity-request.ts
index 69df49754..a243ca9bf 100644
--- a/packages/web/src/repositories/position/request/decrease-liquidity-request.ts
+++ b/packages/web/src/repositories/position/request/decrease-liquidity-request.ts
@@ -5,7 +5,7 @@ export interface DecreaseLiquidityReqeust {
 
   amountAMin: string;
 
-  amountBMax: string;
+  amountBMin: string;
 
   deadline?: string;
 
diff --git a/packages/web/src/repositories/position/request/remove-liquidity-request.ts b/packages/web/src/repositories/position/request/remove-liquidity-request.ts
new file mode 100644
index 000000000..c73d077a1
--- /dev/null
+++ b/packages/web/src/repositories/position/request/remove-liquidity-request.ts
@@ -0,0 +1,5 @@
+export interface RemoveLiquidityReqeust {
+  lpTokenIds: string[];
+
+  caller: string;
+}