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:
Notus API Project
A Notus project with an API key for authentication
Account Abstraction Wallet
An ERC-4337 or EIP-7702 compatible wallet address in your project
Example Tokens
For this guide, we'll use tokens on Polygon network (Chain ID: 137
):
Token | Address | Description |
---|---|---|
USDC | 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 | USD Coin |
USDT | 0xc2132D05D31c914a87C6611C10748AEb04B58e8F | USDT |
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:
- Calculate token amounts for your price range and budget
- Create the liquidity position with the calculated amounts
- 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
, or1
)minPrice
/maxPrice
: Your desired price range (expressed as the ratio of token1/token0)payGasFeeToken
: Token to use for gas feesgasFeePaymentMethod
: How to handle gas fees (ADD_TO_AMOUNT
orDEDUCT_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 addresstoAddress
: Recipient address (usually same as walletAddress)token0Amount
/token1Amount
: Amounts from step 1 calculationslippage
: Maximum price movement tolerance (1 = 1%)gasFeePaymentMethod
:ADD_TO_AMOUNT
orDEDUCT_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
, thepayGasFeeToken
must be eithertoken0
ortoken1
- 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:
- Sign the userOperationHash with the private key of your
walletAddress
owner - Submit before expiration - Check the
expiresAt
timestamp from step 2 - Wait for execution - The API returns an estimated execution time
- Monitor transaction - Use the
userOpHash
to track progress
Response Fields:
userOperationHash
: Unique identifier for your transactionestimatedExecutionTime
: 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
Error | Description | Solution |
---|---|---|
WalletNotFoundException | The wallet address is not found in your project | Ensure the walletAddress exists and is properly created in your Notus project |
NotAuthorizedTokensException | One or more token addresses are not supported by the API | Verify token support using the /api/v1/tokens endpoint before creating positions |
UnsupportedChainException | Chain not supported | Currently only Polygon (Chain ID: 137 ) is supported |
BadPriceRangeException | Invalid price range | Ensure minPrice < maxPrice and both are positive values |
TickOutOfRangeException | Price range outside valid tick bounds | Adjust price range or try a different fee tier (0.05%, 0.3%, 1%) |
BadDeductFeeTokenException | Invalid gas fee token for deduction | When using DEDUCT_FROM_AMOUNT , ensure payGasFeeToken is either token0 or token1 |
ExpiredUserOperationException | The transaction expired and needs to be executed again | Re-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:
Operation | Endpoint | Description |
---|---|---|
Change Liquidity | POST /api/v1/liquidity/change | Add or remove tokens from existing positions |
Collect Fees | POST /api/v1/liquidity/collect | Harvest accumulated trading fees |
List Pools | GET /api/v1/liquidity/pools | Find available pools and their details |
Get Pool Details | GET /api/v1/liquidity/pools/:id | Get specific pool information |
Pool Statistics | GET /api/v1/liquidity/pools/:id/historical-data | Get historical performance data |
Full Documentation: For complete parameter details, examples, and advanced features, visit the Liquidity Pools API Reference.