Notus API

Liquidity Pools Quickstart

Get started with Uniswap v3 liquidity provision using Notus API

Liquidity Pools Quickstart

Liquidity Pools allow you to provide liquidity to decentralized exchanges and earn trading fees. This guide shows you how to create your first Uniswap v3 liquidity position using the Notus API.

With Notus Liquidity Pools, you can:

  • Create new positions with custom price ranges and fee tiers
  • Add liquidity to existing pools seamlessly
  • Earn trading fees from your liquidity positions

Currently supported: Uniswap v3 on Polygon network only.

Estimated time to complete: < 5 minutes

Prerequisites

Before you start, make sure you have:

Example Tokens

For this guide, we'll use tokens on Polygon network (Chain ID: 137):

TokenAddressDescription
USDC0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174USD Coin
USDT0xc2132D05D31c914a87C6611C10748AEb04B58e8FUSDT

Token Support: These are example tokens for this guide. You can use any supported token pairs - verify token support using the /tokens endpoint. Ensure your wallet has sufficient balances of both tokens you want to provide as liquidity.

Operation Flow

The liquidity provision process involves three simple steps:

  1. Calculate token amounts for your price range and budget
  2. Create the liquidity position with the calculated amounts
  3. Execute the transaction by signing and submitting

1. Calculate Required Token Amounts

Before providing liquidity, you need to know how much of each token is required for your chosen price range and budget. This endpoint calculates the optimal token distribution.

curl -X GET \
  "https://api.notus.team/api/v1/liquidity/amounts\
?chainId=137\
&token0=0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\
&token1=0xc2132D05D31c914a87C6611C10748AEb04B58e8F\
&token0MaxAmount=200\
&token1MaxAmount=300\
&poolFeePercent=0.01\
&minPrice=0.98\
&maxPrice=1.02\
&payGasFeeToken=0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\
&gasFeePaymentMethod=ADD_TO_AMOUNT" \
  -H "x-api-key: ${API_KEY}"
const getTokenAmounts = async () => {
  const params = new URLSearchParams({
    chainId: '137',
    token0: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
    token1: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
    token0MaxAmount: 200,
    token1MaxAmount: 300,
    poolFeePercent: '0.01',
    minPrice: '0.98',
    maxPrice: '1.02',
    payGasFeeToken: '0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc',
    gasFeePaymentMethod: 'ADD_TO_AMOUNT'
  });

  const response = await fetch(`https://api.notus.team/api/v1/liquidity/amounts?${params}`, {
    method: 'GET',
    headers: {
      'x-api-key': API_KEY,
      'Content-Type': 'application/json'
    }
  });

  const data = await response.json();
  return data;
};

Parameters:

  • chainId: Network ID (Polygon = 137)
  • token0: First token address (UDSC = 0x2791...a84174)
  • token1: Second token address (USDT = 0xc213...B58e8F)
  • token0MaxAmount / token1MaxAmount: Maximum amount of each token you have, or will have. These are the two upper bounds and the API return an estimate for each option.
  • poolFeePercent: Uniswap v3 fee tier (0.01, 0.05, 0.3, or 1)
  • minPrice / maxPrice: Your desired price range (expressed as the ratio of token1/token0)
  • payGasFeeToken: Token to use for gas fees
  • gasFeePaymentMethod: How to handle gas fees (ADD_TO_AMOUNT or DEDUCT_FROM_AMOUNT)

Example Response:

{
  "poolPrice": "0.999782",
  "amounts": {
    "token0MaxAmount": {
      "token0Amount": "200",
      "token1Amount": "199.59920435476736768744"
    },
    "token1MaxAmount": {
      "token0Amount": "300.60240066566637006887",
      "token1Amount": "300"
    }
  }
}

Price Definition: Price is calculated as token1 / token0. Ensure minPrice < maxPrice or you'll receive a BadPriceRangeException.

2. Create Liquidity Position

Now create your liquidity position using the calculated amounts from step 1. This will prepare the transaction for execution.

POST /api/v1/liquidity/create

Request:

{
  "walletAddress": "0x6e397ddf51d9f15dbe0414538e7529f51f2e5464",
  "toAddress": "0x6e397ddf51d9f15dbe0414538e7529f51f2e5464",
  "chainId": 137,
  "payGasFeeToken": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
  "gasFeePaymentMethod": "ADD_TO_AMOUNT",
  "token0": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
  "token1": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
  "poolFeePercent": 0.01,
  "token0Amount": "200",
  "token1Amount": "199.59920435476736768744",
  "minPrice": 0.98,
  "maxPrice": 1.02,
  "slippage": 1,
  "metadata": {
    "type": "POOL"
  }
}

Parameters:

  • walletAddress: Your account abstraction wallet address
  • toAddress: Recipient address (usually same as walletAddress)
  • token0Amount / token1Amount: Amounts from step 1 calculation
  • slippage: Maximum price movement tolerance (1 = 1%)
  • gasFeePaymentMethod: ADD_TO_AMOUNT or DEDUCT_FROM_AMOUNT
  • metadata: Optional metadata for tracking

Response:

{
  "operation": {
    "userOperationHash": "0x592b6d58aea182a9e4bfb58c93999b5b01bb465dfeda3867e364ee933660feb1",
    "walletAddress": "0xcdb6d29a5f2f8d56af07588f5bea0e500b72548a",
    "expiresAt": "2025-08-26T17:49:38.000Z",
    "chain": {
      "id": 137,
      "name": "Polygon",
      "logo": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
      "explorer": {
        "name": "PolygonScan",
        "url": "https://polygonscan.com"
      }
    },
    "amounts": [
      {
        "token": {
          "name": "USD Coin",
          "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
          "symbol": "USDC",
          "decimals": 6,
          "logoURL": "https://coin-images.coingecko.com/coins/images/6319/large/USD_Coin_icon.png"
        },
        "amount": "200",
        "amountIn": null
      },
      {
        "token": {
          "name": "(PoS) Tether USD",
          "address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
          "symbol": "USDT",
          "decimals": 6,
          "logoURL": "https://coin-images.coingecko.com/coins/images/35023/large/USDT.png"
        },
        "amount": "199.458201",
        "amountIn": null
      }
    ],
    "liquidityProvider": "UNISWAP_V3",
    "nftAddress": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
    "metadata": {
      "type": "POOL"
    }
  }
}

Important Notes:

  • Minimum slippage: Must be at least 0.5 (where 1 = 1%)
  • Gas fee deduction: If using DEDUCT_FROM_AMOUNT, the payGasFeeToken must be either token0 or token1
  • Position NFT: The nftAddress represents your liquidity position as an NFT

Quote Expiration: The userOperationHash expires at the time specified in expiresAt. Execute the transaction before this deadline.

3. Execute the User Operation

Finally, sign and execute the transaction to complete your liquidity provision.

POST /api/v1/crypto/execute-user-op

Request:

{
  "userOperationHash": "0x592b6d58aea182a9e4bfb58c93999b5b01bb465dfeda3867e364ee933660feb1",
  "signature": "0x1b2c3d4e5f6789abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}

Response:

{
  "userOperationHash": "0x592b6d58aea182a9e4bfb58c93999b5b01bb465dfeda3867e364ee933660feb1",
  "estimatedExecutionTime": "2025-08-26T17:45:41.406Z"
}

Execution Steps:

  1. Sign the userOperationHash with the private key of your walletAddress owner
  2. Submit before expiration - Check the expiresAt timestamp from step 2
  3. Wait for execution - The API returns an estimated execution time
  4. Monitor transaction - Use the userOpHash to track progress

Response Fields:

  • userOperationHash: Unique identifier for your transaction
  • estimatedExecutionTime: When the transaction is expected to be processed

Success: Once executed, your liquidity position is active and earning fees! You can track your position using the NFT address provided in step 2, and monitor it through the Polygon explorer.

This endpoint only queues the transaction for execution, while it does check for possible errors, it can still fail on the blockchain for multiple reasons, like price slippage limitations.

Troubleshooting

Common Errors and Solutions

ErrorDescriptionSolution
WalletNotFoundExceptionThe wallet address is not found in your projectEnsure the walletAddress exists and is properly created in your Notus project
NotAuthorizedTokensExceptionOne or more token addresses are not supported by the APIVerify token support using the /api/v1/tokens endpoint before creating positions
UnsupportedChainExceptionChain not supportedCurrently only Polygon (Chain ID: 137) is supported
BadPriceRangeExceptionInvalid price rangeEnsure minPrice < maxPrice and both are positive values
TickOutOfRangeExceptionPrice range outside valid tick boundsAdjust price range or try a different fee tier (0.05%, 0.3%, 1%)
BadDeductFeeTokenExceptionInvalid gas fee token for deductionWhen using DEDUCT_FROM_AMOUNT, ensure payGasFeeToken is either token0 or token1
ExpiredUserOperationExceptionThe transaction expired and needs to be executed againRe-run /api/v1/liquidity/amounts/api/v1/liquidity/create → execute before new expiration

More Liquidity Operations

This guide covers the basics of creating liquidity positions. For advanced operations, check out these additional endpoints in the API Reference:

OperationEndpointDescription
Change LiquidityPOST /api/v1/liquidity/changeAdd or remove tokens from existing positions
Collect FeesPOST /api/v1/liquidity/collectHarvest accumulated trading fees
List PoolsGET /api/v1/liquidity/poolsFind available pools and their details
Get Pool DetailsGET /api/v1/liquidity/pools/:idGet specific pool information
Pool StatisticsGET /api/v1/liquidity/pools/:id/historical-dataGet historical performance data

Full Documentation: For complete parameter details, examples, and advanced features, visit the Liquidity Pools API Reference.