Skip to content

Commit bb01259

Browse files
committed
feat: add test for removeLiquidity
1 parent 72f1fcf commit bb01259

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { createMockSdkInstance } from '@/test/helpers/sdkInstance'
2+
import { getDefaultDeadline } from '@/utils/getDefaultDeadline'
3+
import { getPosition } from '@/utils/getPosition'
4+
import { Token } from '@uniswap/sdk-core'
5+
import { Pool, Position, V4PositionManager } from '@uniswap/v4-sdk'
6+
import { beforeEach, describe, expect, it, vi } from 'vitest'
7+
8+
const instance = createMockSdkInstance()
9+
10+
vi.mock('@/utils/getPosition', () => ({
11+
getPosition: vi.fn(),
12+
}))
13+
14+
const token0 = new Token(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD Coin')
15+
const token1 = new Token(
16+
1,
17+
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
18+
18,
19+
'WETH',
20+
'Wrapped Ether',
21+
)
22+
const pool = new Pool(
23+
token0,
24+
token1,
25+
3000,
26+
60,
27+
'0x1111111111111111111111111111111111111111',
28+
'79228162514264337593543950336',
29+
'1000000', // liquidity as string
30+
0,
31+
)
32+
const position = new Position({ pool, liquidity: '1000000', tickLower: -60, tickUpper: 60 }) // liquidity as string
33+
34+
const mockPosition = {
35+
position,
36+
pool,
37+
token0,
38+
token1,
39+
poolId: '0x1111111111111111111111111111111111111111' as `0x${string}`,
40+
tokenId: '1',
41+
}
42+
43+
describe('buildRemoveLiquidityCallData', () => {
44+
beforeEach(() => {
45+
vi.resetAllMocks()
46+
})
47+
48+
it('should build calldata for removing 100% liquidity', async () => {
49+
vi.mock('@/utils/getDefaultDeadline', () => ({
50+
getDefaultDeadline: vi.fn().mockResolvedValue('1234567890'),
51+
}))
52+
vi.mocked(getPosition).mockReturnValueOnce(Promise.resolve(mockPosition))
53+
vi.spyOn(V4PositionManager, 'removeCallParameters').mockReturnValueOnce({
54+
calldata: '0x123',
55+
value: '0',
56+
})
57+
const { buildRemoveLiquidityCallData } = await import('@/utils/buildRemoveLiquidityCallData')
58+
const result = await buildRemoveLiquidityCallData(
59+
{
60+
liquidityPercentage: 10_000,
61+
tokenId: '1',
62+
deadline: '123',
63+
},
64+
instance,
65+
)
66+
expect(result.calldata).toBe('0x123')
67+
expect(result.value).toBe('0')
68+
})
69+
70+
it('should use custom slippageTolerance', async () => {
71+
vi.mock('@/utils/getDefaultDeadline', () => ({
72+
getDefaultDeadline: vi.fn().mockResolvedValue('1234567890'),
73+
}))
74+
vi.mocked(getPosition).mockReturnValueOnce(Promise.resolve(mockPosition))
75+
const spy = vi.spyOn(V4PositionManager, 'removeCallParameters').mockReturnValueOnce({
76+
calldata: '0xabc',
77+
value: '1',
78+
})
79+
const { buildRemoveLiquidityCallData } = await import('@/utils/buildRemoveLiquidityCallData')
80+
await buildRemoveLiquidityCallData(
81+
{
82+
liquidityPercentage: 5000,
83+
tokenId: '1',
84+
slippageTolerance: 123,
85+
deadline: '123',
86+
},
87+
instance,
88+
)
89+
expect(spy).toHaveBeenCalledWith(
90+
mockPosition.position,
91+
expect.objectContaining({ slippageTolerance: expect.any(Object) }),
92+
)
93+
})
94+
95+
it('should throw if position not found', async () => {
96+
vi.mock('@/utils/getDefaultDeadline', () => ({
97+
getDefaultDeadline: vi.fn().mockResolvedValue('1234567890'),
98+
}))
99+
vi.mocked(getPosition).mockReturnValueOnce(
100+
Promise.resolve(undefined as unknown as ReturnType<typeof getPosition>),
101+
)
102+
const { buildRemoveLiquidityCallData } = await import('@/utils/buildRemoveLiquidityCallData')
103+
await expect(
104+
buildRemoveLiquidityCallData({ liquidityPercentage: 10_000, tokenId: '404' }, instance),
105+
).rejects.toThrow('Position not found')
106+
})
107+
108+
it('should throw if V4PositionManager throws', async () => {
109+
vi.mock('@/utils/getDefaultDeadline', () => ({
110+
getDefaultDeadline: vi.fn().mockResolvedValue('1234567890'),
111+
}))
112+
vi.mocked(getPosition).mockReturnValueOnce(Promise.resolve(mockPosition))
113+
vi.spyOn(V4PositionManager, 'removeCallParameters').mockImplementationOnce(() => {
114+
throw new Error('fail')
115+
})
116+
const { buildRemoveLiquidityCallData } = await import('@/utils/buildRemoveLiquidityCallData')
117+
await expect(
118+
buildRemoveLiquidityCallData(
119+
{ liquidityPercentage: 10_000, tokenId: '1', deadline: '123' },
120+
instance,
121+
),
122+
).rejects.toThrow('fail')
123+
})
124+
})

0 commit comments

Comments
 (0)