CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-uniswap--router-sdk

SDK for routing swaps across Uniswap V2, V3, and V4 protocols with automatic route optimization and gas-efficient execution.

Pending
Overview
Eval results
Files

approval-liquidity.mddocs/

Approval & Liquidity

Token approval and liquidity management utilities for position management and swap-and-add operations. The ApproveAndCall class supports various approval strategies and NFT position handling for Uniswap V3 liquidity operations.

Capabilities

ApproveAndCall Class

Abstract class providing static methods for encoding token approvals and liquidity management operations.

/**
 * Abstract class for encoding approval and liquidity operations
 */
abstract class ApproveAndCall {
  /** Contract interface for IApproveAndCall */
  static INTERFACE: Interface;
  
  /**
   * Encode maximum token approval
   * @param token - Token to approve
   * @returns Encoded function data for max approval
   */
  static encodeApproveMax(token: Token): string;
  
  /**
   * Encode maximum minus one token approval  
   * @param token - Token to approve
   * @returns Encoded function data for max-1 approval
   */
  static encodeApproveMaxMinusOne(token: Token): string;
  
  /**
   * Encode zero then maximum token approval (for tokens requiring zero reset)
   * @param token - Token to approve
   * @returns Encoded function data for zero then max approval
   */
  static encodeApproveZeroThenMax(token: Token): string;
  
  /**
   * Encode zero then maximum minus one token approval
   * @param token - Token to approve  
   * @returns Encoded function data for zero then max-1 approval
   */
  static encodeApproveZeroThenMaxMinusOne(token: Token): string;
  
  /**
   * Encode call to position manager with batched calldatas
   * @param calldatas - Array of encoded function calls
   * @returns Encoded function data for position manager call
   */
  static encodeCallPositionManager(calldatas: string[]): string;
  
  /**
   * Encode adding liquidity to a position in the NFT manager contract
   * @param position - Forecasted position with expected amount out from swap
   * @param minimalPosition - Forecasted position with custom minimal token amounts
   * @param addLiquidityOptions - Options for adding liquidity (mint or increase)
   * @param slippageTolerance - Maximum slippage tolerance
   * @returns Encoded function data for add liquidity operation
   */
  static encodeAddLiquidity(
    position: Position,
    minimalPosition: Position,
    addLiquidityOptions: CondensedAddLiquidityOptions,
    slippageTolerance: Percent
  ): string;
  
  /**
   * Encode approval with specified approval type
   * @param token - Currency to approve (will use wrapped version)
   * @param approvalType - Type of approval to perform
   * @returns Encoded function data for the specified approval type
   */
  static encodeApprove(token: Currency, approvalType: ApprovalTypes): string;
}

Approval Types

Enumeration of different approval strategies for token spending.

/**
 * Different approval strategies for token spending
 */
enum ApprovalTypes {
  /** No approval required */
  NOT_REQUIRED = 0,
  
  /** Approve maximum uint256 amount */
  MAX = 1,
  
  /** Approve maximum uint256 minus one */
  MAX_MINUS_ONE = 2,
  
  /** First approve zero, then approve maximum (for problematic tokens) */
  ZERO_THEN_MAX = 3,
  
  /** First approve zero, then approve maximum minus one */
  ZERO_THEN_MAX_MINUS_ONE = 4
}

Liquidity Options

Configuration options for adding liquidity to positions.

/**
 * Condensed version of v3-sdk AddLiquidityOptions containing only necessary swap + add attributes
 */
type CondensedAddLiquidityOptions = Omit<MintSpecificOptions, 'createPool'> | IncreaseSpecificOptions;

/**
 * Type guard to check if options are for minting a new position
 * @param options - Liquidity options to check
 * @returns True if options are for minting, false for increasing existing position
 */
function isMint(options: CondensedAddLiquidityOptions): options is Omit<MintSpecificOptions, 'createPool'>;

Usage Examples:

import { ApproveAndCall, ApprovalTypes, isMint } from "@uniswap/router-sdk";
import { Token, Percent } from "@uniswap/sdk-core";
import { Position } from "@uniswap/v3-sdk";

// Basic token approval
const token = new Token(1, "0x...", 18, "USDC", "USD Coin");
const approvalCalldata = ApproveAndCall.encodeApproveMax(token);

// Send approval transaction
const approvalTx = {
  to: APPROVE_AND_CALL_ADDRESS,
  data: approvalCalldata
};
// Different approval strategies
const maxApproval = ApproveAndCall.encodeApprove(token, ApprovalTypes.MAX);
const zeroThenMaxApproval = ApproveAndCall.encodeApprove(token, ApprovalTypes.ZERO_THEN_MAX);

// For problematic tokens that require zero reset
if (requiresZeroReset) {
  const calldata = ApproveAndCall.encodeApprove(token, ApprovalTypes.ZERO_THEN_MAX);
}
// Add liquidity after swap
import { Pool } from "@uniswap/v3-sdk";

const pool = new Pool(token0, token1, fee, sqrtPriceX96, liquidity, tick);
const position = new Position({
  pool,
  liquidity: targetLiquidity,
  tickLower: -887220,
  tickUpper: 887220
});

// Create minimal position for slippage protection
const minimalPosition = Position.fromAmounts({
  pool: position.pool,
  tickLower: position.tickLower,
  tickUpper: position.tickUpper,
  amount0: minimumAmount0,
  amount1: minimumAmount1,
  useFullPrecision: false
});

// Configure liquidity options for new position
const mintOptions = {
  recipient: "0x742d35Cc6435C6329Eb54F0d86C05B1E11a02E6B",
  deadline: Math.floor(Date.now() / 1000) + 1800,
  slippageTolerance: new Percent(50, 10000)
};

// Encode add liquidity operation
const addLiquidityCalldata = ApproveAndCall.encodeAddLiquidity(
  position,
  minimalPosition,
  mintOptions,
  new Percent(50, 10000) // 0.5% slippage
);
// Increase existing position liquidity
const increaseOptions = {
  tokenId: 123456, // Existing position NFT ID
  deadline: Math.floor(Date.now() / 1000) + 1800,
  slippageTolerance: new Percent(50, 10000)
};

// Check if this is a mint or increase operation
if (isMint(mintOptions)) {
  console.log("Creating new position");
} else {
  console.log("Increasing existing position");
}

const increaseCalldata = ApproveAndCall.encodeAddLiquidity(
  position,
  minimalPosition,
  increaseOptions,
  new Percent(50, 10000)
);
// Batch multiple operations
const calldatas = [
  ApproveAndCall.encodeApproveMax(token0),
  ApproveAndCall.encodeApproveMax(token1),
  addLiquidityCalldata
];

// Encode batched call to position manager
const batchedCalldata = ApproveAndCall.encodeCallPositionManager(calldatas);

// Execute batched transaction
const batchTx = {
  to: APPROVE_AND_CALL_ADDRESS,
  data: batchedCalldata
};
// Complete swap and add workflow
import { SwapRouter } from "@uniswap/router-sdk";

const swapAndAddCalldata = SwapRouter.swapAndAddCallParameters(
  trade,
  swapAndAddOptions,
  position,
  mintOptions,
  ApprovalTypes.MAX,        // Input token approval
  ApprovalTypes.NOT_REQUIRED // Output token approval (already have from swap)
);

// This internally uses ApproveAndCall for the liquidity portion
console.log("Swap and add calldata:", swapAndAddCalldata.calldata);
console.log("ETH value required:", swapAndAddCalldata.value);

Error Handling

Common errors and their handling:

// Handle approval failures
try {
  const calldata = ApproveAndCall.encodeApprove(token, ApprovalTypes.MAX);
} catch (error) {
  if (error.message === 'Error: invalid ApprovalType') {
    // Handle invalid approval type
    console.error("Invalid approval type provided");
  }
}

// Validate liquidity options
function validateLiquidityOptions(options: CondensedAddLiquidityOptions) {
  if (isMint(options)) {
    if (!options.recipient) {
      throw new Error("Recipient required for mint operations");
    }
  } else {
    if (!options.tokenId) {
      throw new Error("Token ID required for increase operations");
    }
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-uniswap--router-sdk

docs

approval-liquidity.md

index.md

mixed-routes.md

route-handling.md

swap-routing.md

trade-management.md

utilities.md

tile.json