or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

approval-liquidity.mdindex.mdmixed-routes.mdroute-handling.mdswap-routing.mdtrade-management.mdutilities.md

approval-liquidity.mddocs/

0

# Approval & Liquidity

1

2

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.

3

4

## Capabilities

5

6

### ApproveAndCall Class

7

8

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

9

10

```typescript { .api }

11

/**

12

* Abstract class for encoding approval and liquidity operations

13

*/

14

abstract class ApproveAndCall {

15

/** Contract interface for IApproveAndCall */

16

static INTERFACE: Interface;

17

18

/**

19

* Encode maximum token approval

20

* @param token - Token to approve

21

* @returns Encoded function data for max approval

22

*/

23

static encodeApproveMax(token: Token): string;

24

25

/**

26

* Encode maximum minus one token approval

27

* @param token - Token to approve

28

* @returns Encoded function data for max-1 approval

29

*/

30

static encodeApproveMaxMinusOne(token: Token): string;

31

32

/**

33

* Encode zero then maximum token approval (for tokens requiring zero reset)

34

* @param token - Token to approve

35

* @returns Encoded function data for zero then max approval

36

*/

37

static encodeApproveZeroThenMax(token: Token): string;

38

39

/**

40

* Encode zero then maximum minus one token approval

41

* @param token - Token to approve

42

* @returns Encoded function data for zero then max-1 approval

43

*/

44

static encodeApproveZeroThenMaxMinusOne(token: Token): string;

45

46

/**

47

* Encode call to position manager with batched calldatas

48

* @param calldatas - Array of encoded function calls

49

* @returns Encoded function data for position manager call

50

*/

51

static encodeCallPositionManager(calldatas: string[]): string;

52

53

/**

54

* Encode adding liquidity to a position in the NFT manager contract

55

* @param position - Forecasted position with expected amount out from swap

56

* @param minimalPosition - Forecasted position with custom minimal token amounts

57

* @param addLiquidityOptions - Options for adding liquidity (mint or increase)

58

* @param slippageTolerance - Maximum slippage tolerance

59

* @returns Encoded function data for add liquidity operation

60

*/

61

static encodeAddLiquidity(

62

position: Position,

63

minimalPosition: Position,

64

addLiquidityOptions: CondensedAddLiquidityOptions,

65

slippageTolerance: Percent

66

): string;

67

68

/**

69

* Encode approval with specified approval type

70

* @param token - Currency to approve (will use wrapped version)

71

* @param approvalType - Type of approval to perform

72

* @returns Encoded function data for the specified approval type

73

*/

74

static encodeApprove(token: Currency, approvalType: ApprovalTypes): string;

75

}

76

```

77

78

### Approval Types

79

80

Enumeration of different approval strategies for token spending.

81

82

```typescript { .api }

83

/**

84

* Different approval strategies for token spending

85

*/

86

enum ApprovalTypes {

87

/** No approval required */

88

NOT_REQUIRED = 0,

89

90

/** Approve maximum uint256 amount */

91

MAX = 1,

92

93

/** Approve maximum uint256 minus one */

94

MAX_MINUS_ONE = 2,

95

96

/** First approve zero, then approve maximum (for problematic tokens) */

97

ZERO_THEN_MAX = 3,

98

99

/** First approve zero, then approve maximum minus one */

100

ZERO_THEN_MAX_MINUS_ONE = 4

101

}

102

```

103

104

### Liquidity Options

105

106

Configuration options for adding liquidity to positions.

107

108

```typescript { .api }

109

/**

110

* Condensed version of v3-sdk AddLiquidityOptions containing only necessary swap + add attributes

111

*/

112

type CondensedAddLiquidityOptions = Omit<MintSpecificOptions, 'createPool'> | IncreaseSpecificOptions;

113

114

/**

115

* Type guard to check if options are for minting a new position

116

* @param options - Liquidity options to check

117

* @returns True if options are for minting, false for increasing existing position

118

*/

119

function isMint(options: CondensedAddLiquidityOptions): options is Omit<MintSpecificOptions, 'createPool'>;

120

```

121

122

**Usage Examples:**

123

124

```typescript

125

import { ApproveAndCall, ApprovalTypes, isMint } from "@uniswap/router-sdk";

126

import { Token, Percent } from "@uniswap/sdk-core";

127

import { Position } from "@uniswap/v3-sdk";

128

129

// Basic token approval

130

const token = new Token(1, "0x...", 18, "USDC", "USD Coin");

131

const approvalCalldata = ApproveAndCall.encodeApproveMax(token);

132

133

// Send approval transaction

134

const approvalTx = {

135

to: APPROVE_AND_CALL_ADDRESS,

136

data: approvalCalldata

137

};

138

```

139

140

```typescript

141

// Different approval strategies

142

const maxApproval = ApproveAndCall.encodeApprove(token, ApprovalTypes.MAX);

143

const zeroThenMaxApproval = ApproveAndCall.encodeApprove(token, ApprovalTypes.ZERO_THEN_MAX);

144

145

// For problematic tokens that require zero reset

146

if (requiresZeroReset) {

147

const calldata = ApproveAndCall.encodeApprove(token, ApprovalTypes.ZERO_THEN_MAX);

148

}

149

```

150

151

```typescript

152

// Add liquidity after swap

153

import { Pool } from "@uniswap/v3-sdk";

154

155

const pool = new Pool(token0, token1, fee, sqrtPriceX96, liquidity, tick);

156

const position = new Position({

157

pool,

158

liquidity: targetLiquidity,

159

tickLower: -887220,

160

tickUpper: 887220

161

});

162

163

// Create minimal position for slippage protection

164

const minimalPosition = Position.fromAmounts({

165

pool: position.pool,

166

tickLower: position.tickLower,

167

tickUpper: position.tickUpper,

168

amount0: minimumAmount0,

169

amount1: minimumAmount1,

170

useFullPrecision: false

171

});

172

173

// Configure liquidity options for new position

174

const mintOptions = {

175

recipient: "0x742d35Cc6435C6329Eb54F0d86C05B1E11a02E6B",

176

deadline: Math.floor(Date.now() / 1000) + 1800,

177

slippageTolerance: new Percent(50, 10000)

178

};

179

180

// Encode add liquidity operation

181

const addLiquidityCalldata = ApproveAndCall.encodeAddLiquidity(

182

position,

183

minimalPosition,

184

mintOptions,

185

new Percent(50, 10000) // 0.5% slippage

186

);

187

```

188

189

```typescript

190

// Increase existing position liquidity

191

const increaseOptions = {

192

tokenId: 123456, // Existing position NFT ID

193

deadline: Math.floor(Date.now() / 1000) + 1800,

194

slippageTolerance: new Percent(50, 10000)

195

};

196

197

// Check if this is a mint or increase operation

198

if (isMint(mintOptions)) {

199

console.log("Creating new position");

200

} else {

201

console.log("Increasing existing position");

202

}

203

204

const increaseCalldata = ApproveAndCall.encodeAddLiquidity(

205

position,

206

minimalPosition,

207

increaseOptions,

208

new Percent(50, 10000)

209

);

210

```

211

212

```typescript

213

// Batch multiple operations

214

const calldatas = [

215

ApproveAndCall.encodeApproveMax(token0),

216

ApproveAndCall.encodeApproveMax(token1),

217

addLiquidityCalldata

218

];

219

220

// Encode batched call to position manager

221

const batchedCalldata = ApproveAndCall.encodeCallPositionManager(calldatas);

222

223

// Execute batched transaction

224

const batchTx = {

225

to: APPROVE_AND_CALL_ADDRESS,

226

data: batchedCalldata

227

};

228

```

229

230

```typescript

231

// Complete swap and add workflow

232

import { SwapRouter } from "@uniswap/router-sdk";

233

234

const swapAndAddCalldata = SwapRouter.swapAndAddCallParameters(

235

trade,

236

swapAndAddOptions,

237

position,

238

mintOptions,

239

ApprovalTypes.MAX, // Input token approval

240

ApprovalTypes.NOT_REQUIRED // Output token approval (already have from swap)

241

);

242

243

// This internally uses ApproveAndCall for the liquidity portion

244

console.log("Swap and add calldata:", swapAndAddCalldata.calldata);

245

console.log("ETH value required:", swapAndAddCalldata.value);

246

```

247

248

### Error Handling

249

250

Common errors and their handling:

251

252

```typescript

253

// Handle approval failures

254

try {

255

const calldata = ApproveAndCall.encodeApprove(token, ApprovalTypes.MAX);

256

} catch (error) {

257

if (error.message === 'Error: invalid ApprovalType') {

258

// Handle invalid approval type

259

console.error("Invalid approval type provided");

260

}

261

}

262

263

// Validate liquidity options

264

function validateLiquidityOptions(options: CondensedAddLiquidityOptions) {

265

if (isMint(options)) {

266

if (!options.recipient) {

267

throw new Error("Recipient required for mint operations");

268

}

269

} else {

270

if (!options.tokenId) {

271

throw new Error("Token ID required for increase operations");

272

}

273

}

274

}

275

```