> ## Documentation Index
> Fetch the complete documentation index at: https://docs.saucerswap.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Claiming Fees

> Claim the swap fees from an existing liquidity position

<Info>
  **Contract ID:** [SaucerSwapV2NonfungiblePositionManager](https://hashscan.io/mainnet/contract/0.0.4053945)
</Info>

<Note>
  See [Get user positions](/v/developer/saucerswap-v2/liquidity-operations/get-user-positions) for details how to retrieve all positions of a user including fees earned if any.
</Note>

***

Function name: **collect**

⛽ *Recommended gas:* 300,000 gwei (\~ \$0.026 USD)

| Struct Parameter Name | Description                                                           |
| --------------------- | --------------------------------------------------------------------- |
| *uint256 tokenSN*     | The serial number of the token for which liquidity is being increased |
| *address recipient*   | EVM address to receive the claimed swap fees                          |
| *uint256 amount0Max*  | The maximum amount for the first token in its smallest unit           |
| *uint256 amount1Max*  | The maximum amount for the second token in its smallest unit          |

<CodeGroup>
  ```solidity INonfungiblePositionManager.sol theme={null}
  struct CollectParams {
    uint256 tokenSN;
    address recipient;
    uint128 amount0Max;
    uint128 amount1Max;
  }

  /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient
  /// @param params tokenSN The serial number of the NFT for which tokens are being collected,
  /// recipient The account that should receive the tokens,
  /// amount0Max The maximum amount of token0 to collect,
  /// amount1Max The maximum amount of token1 to collect
  /// @return amount0 The amount of fees collected in token0
  /// @return amount1 The amount of fees collected in token1
  function collect(CollectParams calldata params) external payable 
    returns (uint256 amount0, uint256 amount1);
  ```

  ```solidity NonfungiblePositionManager.sol theme={null}
  /// @inheritdoc INonfungiblePositionManager
  function collect(CollectParams calldata params)
    external
    payable
    override
    isAuthorizedForToken(params.tokenSN)
    returns (uint256 amount0, uint256 amount1)
  {
    require(params.amount0Max > 0 || params.amount1Max > 0);
    // allow collecting to the nft position manager address with address 0
    address recipient = params.recipient == address(0) ? address(this) : params.recipient;

    Position storage position = _positions[params.tokenSN];

    PoolAddress.PoolKey memory poolKey = _poolIdToPoolKey[position.poolId];

    IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));

    (uint128 tokensOwed0, uint128 tokensOwed1) = (position.tokensOwed0, position.tokensOwed1);

    // trigger an update of the position fees owed and fee growth snapshots if it has any liquidity
    if (position.liquidity > 0) {
      pool.burn(position.tickLower, position.tickUpper, 0);
      (, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(
        PositionKey.compute(address(this), position.tickLower, position.tickUpper)
      );

      tokensOwed0 += uint128(
        FullMath.mulDiv(
          feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128,
          position.liquidity,
          FixedPoint128.Q128
        )
      );
      tokensOwed1 += uint128(
        FullMath.mulDiv(
          feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128,
          position.liquidity,
          FixedPoint128.Q128
        )
      );

      position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128;
      position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128;
    }

    // compute the arguments to give to the pool#collect method
    (uint128 amount0Collect, uint128 amount1Collect) = (
      params.amount0Max > tokensOwed0 ? tokensOwed0 : params.amount0Max,
      params.amount1Max > tokensOwed1 ? tokensOwed1 : params.amount1Max
    );

    // the actual amounts collected are returned
    (amount0, amount1) = pool.collect(
      recipient,
      position.tickLower,
      position.tickUpper,
      amount0Collect,
      amount1Collect
    );

    // sometimes there will be a few less wei than expected due to rounding down in core, but we just subtract the full amount expected
    // instead of the actual amount so we can burn the token
    (position.tokensOwed0, position.tokensOwed1) = (tokensOwed0 - amount0Collect, tokensOwed1 - amount1Collect);

    emit Collect(params.tokenSN, recipient, amount0Collect, amount1Collect);
  }
  ```
</CodeGroup>

### Code Overview

The following code demonstrates how to claim all swap fees from a pool.

<Tip>
  When claiming fees from a pool that involves HBAR, include **unwrapWHBAR** in your multicall to convert the Wrapped HBAR (WHBAR) output token back into the native HBAR cryptocurrency.
</Tip>

<Tabs>
  <Tab title="JavaScript SDK">
    **Resources:**

    * [SaucerSwap deployed contract IDs](/developerx/contract-deployments)
    * [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
    * [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
    * [Uniswap V3 SDK](https://docs.uniswap.org/sdk/v3/overview)
    * [Hedera JSON RPC Relay](https://docs.hedera.com/hedera/core-concepts/smart-contracts/deploying-smart-contracts/json-rpc-relay)
    * [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)

    ```typescript Typescript theme={null}
    import * as ethers from 'ethers'; //V6
    import { Pool, Position, nearestUsableTick, priceToClosestTick } from '@uniswap/v3-sdk';
    import { Fraction, Percent, Token, Price } from '@uniswap/sdk-core';
    import { ContractExecuteTransaction, .. } from '@hashgraph/sdk';

    //Set one of Hedera's JSON RPC Relay as the provider
    const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
      batchMaxCount: 1, //workaround for V6
    });

    //Load the ABI data for NonfungiblePositionManager
    const nftManagerInterfaces = new ethers.Interface(nftManagerAbi);

    //get max possible value for amount0Max and amount1Max
    const MAX_UINT128 = new BigNumber(2).pow(128).minus(1).toFixed(0);

    //CollectParams struct
    const params = {
      tokenSN: tokenSN,
      recipient: recipientAddress,    
      amount0Max: MAX_UINT128, //collect max fees
      amount1Max: MAX_UINT128, //collect max fees
    };

    //Construct encoded data for each function
    const collectEncoded = nftManagerInterfaces.encodeFunctionData('collect', [params]);  

    //Not needed if HBAR isn't include in the pool
    const unwrapWHBAREncoded = nftManagerInterfaces.encodeFunctionData('unwrapWHBAR', [0, recipientAddress]);

    //Build encoded data for the multicall
    const encodedData = nftManagerInterfaces.encodeFunctionData('multicall', 
      [[collectEncoded, unwrapWHBAREncoded]]);  
    const encodedDataAsUint8Array = hexToUint8Array(encodedData.substring(2));

    //Execute the paid contract call
    const response = await new ContractExecuteTransaction()
      .setContractId(nftManagerContractId)
      .setGas(gasGwei)
      .setFunctionParameters(encodedDataAsUint8Array)
      .execute(client);

    //Fetch the result
    const record = await response.getRecord(client);    
    const result = record.contractFunctionResult!;
    const results = nftManagerInterfaces.decodeFunctionResult('multicall', result.bytes)[0];
    const collectResult = nftManagerInterfaces.decodeFunctionResult('collect', results[0]);

    //Retrieve the collected amounts for informative purposes
    const amount0 = BigNumber(collectResult.amount0);
    const amount1 = BigNumber(collectResult.amount1);
    ```
  </Tab>
</Tabs>
