For the complete documentation index, see llms.txt. This page is also available as Markdown.

Manage Liquidity Programmatically

Auto LP

Managing your liquidity on Turbine means:

  1. Authenticating

  2. Submitting a liquidity intent

  3. Waiting for Turbine to execute the intent, or executing it directly.

We'll explore these steps below.

Learn more about liquidity provision: Market Tracking LP and Liquidity Pools in Depth.

Providing and Withdrawing Liquidity via API

See add-liquidity.ts in the SDK repo for a complete example of providing liquidity.

See remove-liquidity.ts in the SDK repo for a complete example of withdrawing liquidity.

1

Prepare your wallet

To submit a liquidity intent to Turbine and have it executed, the following conditions must be met:

  • You need to have enough balance of provided tokens.

  • You need to approve Permit2 contract to spend at least the amounts you're providing (i.e. call approve(permit2address, amount) on the provided token contracts; you can use approve-token.ts script).

  • You need to have enough balance of pool's LP token.

  • You need to approve Permit2 contract to spend at least the amount of LP token you want to burn (i.e. call approve(permit2address, amount) on the LP token contract; you can use the approve-lp-token.ts script).

2

Instantiate TurbineClient

Set environment variables for the below example to work:

  • PRIVATE_KEY - private key of the wallet

  • RPC_URL - URL to access Ethereum blockchain; you can use your private RPC or pick one from https://ethereumnodes.com/

  • TURBINE_API_URL - URL of Turbine API instance, with /api suffix. E.g. https://api.turbine.exchange/api.

import { createPublicClient, createWalletClient, http, Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { TurbineClient, getRandomSalt } from "turbine-sdk";

const account = privateKeyToAccount(PRIVATE_KEY);
const walletClient = createWalletClient({
    account: account,
    chain: mainnet,
    transport: http(RPC_URL),
});
const publicClient = createPublicClient({
    chain: mainnet,
    transport: http(RPC_URL),
});

const turbineClient = await TurbineClient.create(
    walletClient,
    publicClient,
    TURBINE_API_URL
);
3

Authenticate

To submit liquidity intents you must be authenticated. See Authentication for details.

The SDK handles authentication automatically.

4

Get available pools

Call getPools() to get a list of available pools:

const pools = await turbineClient.getPools();

The result looks like this:

[
  {
    metadata: {
      token0: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
      token1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
      fee: 3000,
      lpToken: '0xB03aC5cabFc98DB26C0D9eA232E1e900724d91F3'
    },
    state: { reserve0: 0n, reserve1: 0n, liquidity: 0n },
    stats: { weeklySellVolumeToken0: 0n, weeklySellVolumeToken1: 0n }
  },
  {
    metadata: {
      token0: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
      token1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
      fee: 10000,
      lpToken: '0x2bcF0170103930dc12d748c8b54205a36B7351dA'
    },
    state: { reserve0: 10000000000n, reserve1: 500000000000000000n, liquidity: 250000005000000000n },
    stats: { weeklySellVolumeToken0: 0n, weeklySellVolumeToken1: 0n }
  }
]

The snippet above shows two USDC/WETH pools: one at 0.3% fee tier and one at 1% fee tier. The first is empty; the second holds 10,000 USDC and 0.5 WETH.

Pool statistics aren't implemented yet — the stats fields above return placeholders.

5

Create a liquidity intent

Create an intent to provide exactly 1000 USDC and 0.1 WETH to the pool at 1% fee tier.

const liquidityIntent: AddLiquidityIntent = {
    owner: account.address,
    token0: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as Hex,
    token1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" as Hex,
    fee: 10000,
    token0Amount: 1000000000n,
    token1Amount: 100000000000000000n,
    exact: true,
    salt: getRandomSalt(),
};

Create an intent to withdraw 40% of liquidity from the USDC/WETH pool at 1% fee tier. 40% of total pool liquidity equals 100,000,002 × 109 units of LP token.

const liquidityIntent: RemoveLiquidityIntent = {
    owner: account.address,
    token0: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as Hex,
    token1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" as Hex,
    fee: 10000,
    lpToken: "0x2bcF0170103930dc12d748c8b54205a36B7351dA" as Hex,
    lpTokenAmount: 100000002000000000n,
    salt: getRandomSalt(),
};
6

Submit liquidity intent

Submit the intent to Turbine:

const intentHash = await turbineClient.addLiquidity(liquidityIntent);

This method calls: POST /api/add_liquidity

const intentHash = await turbineClient.removeLiquidity(liquidityIntent);

This method calls: POST /api/remove_liquidity

This call errors if Turbine rejects your intent during initial validation.

Submitting the intent does not execute it immediately. Your intent must still pass The Speedbump.

7

Check intent state

To check intent state, call getLiquidityIntents:

const intentState = (await turbineClient.getLiquidityIntents([intentHash]))[0];
console.log(intentState.status);

The intent can be in the following states:

  • Pending - The intent is waiting to pass the speedbump.

  • Invalid - The intent was removed due to validation errors during a settlement.

  • Expired - The intent was removed because it expired before execution.

  • Executed - The intent was executed.

  • PendingCancellation - The owner has requested cancellation.

  • Canceled - The owner canceled the intent.

Directly Withdrawing Liquidity Onchain

You can withdraw liquidity by submitting onchain transactions, without the Turbine backend acting as intermediary. The speedbump still applies.

Direct onchain withdrawal has two steps:

  1. Submit a liquidity withdrawal intent to LiquidityRouter

  2. Execute the submitted intent (after the speedbump)

Instead of authenticating to the Turbine backend, you confirm your identity by signing a transaction.

1

Create liquidity intent

Follow the steps in Providing and Withdrawing Liquidity via API up through creating the liquidity intent. You can skip authentication.

2

Submit liquidity intent onchain

This method calls submitRemoveLiquidityIntent

3

Execute the liquidity intent

After submitting, wait at least the speedbump duration (12 seconds, or 1 Ethereum block).

Then execute the intent:

Turbine also executes liquidity removal intents submitted directly to LiquidityRouter (not only those submitted via the Turbine API).

See also

Last updated

Was this helpful?