@steerprotocol/sdk 1.30.8 → 1.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/cjs/base/PoolClient.js +137 -0
  2. package/dist/cjs/base/PoolClient.js.map +1 -1
  3. package/dist/cjs/base/VaultClient.js +111 -2
  4. package/dist/cjs/base/VaultClient.js.map +1 -1
  5. package/dist/cjs/const/feeManagerContracts.js +25 -0
  6. package/dist/cjs/const/feeManagerContracts.js.map +1 -0
  7. package/dist/cjs/const/network.js +7 -0
  8. package/dist/cjs/const/network.js.map +1 -1
  9. package/dist/cjs/const/protocol.js +68 -92
  10. package/dist/cjs/const/protocol.js.map +1 -1
  11. package/dist/cjs/scripts/processDeployments.js +1 -0
  12. package/dist/cjs/scripts/processDeployments.js.map +1 -1
  13. package/dist/esm/base/PoolClient.js +137 -0
  14. package/dist/esm/base/PoolClient.js.map +1 -1
  15. package/dist/esm/base/VaultClient.js +111 -2
  16. package/dist/esm/base/VaultClient.js.map +1 -1
  17. package/dist/esm/const/feeManagerContracts.js +25 -0
  18. package/dist/esm/const/feeManagerContracts.js.map +1 -0
  19. package/dist/esm/const/network.js +7 -0
  20. package/dist/esm/const/network.js.map +1 -1
  21. package/dist/esm/const/protocol.js +68 -92
  22. package/dist/esm/const/protocol.js.map +1 -1
  23. package/dist/esm/scripts/processDeployments.js +1 -0
  24. package/dist/esm/scripts/processDeployments.js.map +1 -1
  25. package/dist/types/base/PoolClient.d.ts +22 -0
  26. package/dist/types/base/PoolClient.d.ts.map +1 -1
  27. package/dist/types/base/VaultClient.d.ts +20 -0
  28. package/dist/types/base/VaultClient.d.ts.map +1 -1
  29. package/dist/types/const/feeManagerContracts.d.ts +6 -0
  30. package/dist/types/const/feeManagerContracts.d.ts.map +1 -0
  31. package/dist/types/const/network.d.ts +1 -0
  32. package/dist/types/const/network.d.ts.map +1 -1
  33. package/dist/types/const/protocol.d.ts +4 -19
  34. package/dist/types/const/protocol.d.ts.map +1 -1
  35. package/package.json +3 -2
  36. package/src/__tests__/base/PoolClient.test.ts +355 -104
  37. package/src/__tests__/base/StakingClient.test.ts +72 -72
  38. package/src/__tests__/base/VaultClient.protocol-filter.test.ts +64 -137
  39. package/src/__tests__/base/VaultClient.test.ts +460 -60
  40. package/src/__tests__/base/vault/single-asset/calculateLimitPrice.test.ts +32 -14
  41. package/src/__tests__/base/vault/single-asset/calculateSwapAmount.test.ts +7 -4
  42. package/src/__tests__/base/vault/single-asset/estimateLpTokens.test.ts +105 -570
  43. package/src/__tests__/base/vault/single-asset/simulateSwap.test.ts +45 -66
  44. package/src/__tests__/base/vault/single-asset/singleAssetDepositClient.test.ts +178 -381
  45. package/src/__tests__/const/network.feeManager.test.ts +47 -0
  46. package/src/__tests__/fixtures/live/single-asset.fixture.json +116 -0
  47. package/src/__tests__/fixtures/live/staking-pools.fixture.json +353 -0
  48. package/src/__tests__/fixtures/live/vaults.fixture.json +5392 -0
  49. package/src/base/PoolClient.ts +200 -1
  50. package/src/base/VaultClient.ts +169 -2
  51. package/src/const/feeManagerContracts.ts +28 -0
  52. package/src/const/network.ts +10 -1
  53. package/src/const/protocol.ts +18 -39
  54. package/src/scripts/processDeployments.ts +1 -0
@@ -1,436 +1,107 @@
1
- import { Address, createPublicClient, createTestClient, http, parseEther, publicActions } from 'viem';
2
- import { privateKeyToAccount } from 'viem/accounts';
3
- import { foundry, polygon } from 'viem/chains';
1
+ import { Address, parseEther } from 'viem';
4
2
  import { estimateLpTokens, getVaultReserves } from '../../../../base/vault/single-asset/estimateLpTokens.js';
5
3
 
6
- // Mock the vault ABI import
7
- jest.mock('../../../../const/deployments/abis', () => ({
8
- abis: {
9
- QuickSwapUniv3MultiPositionLiquidityManager: [
10
- {
11
- type: 'function',
12
- name: 'totalSupply',
13
- inputs: [],
14
- outputs: [{ name: '', type: 'uint256' }],
15
- stateMutability: 'view'
16
- },
17
- {
18
- type: 'function',
19
- name: 'token0',
20
- inputs: [],
21
- outputs: [{ name: '', type: 'address' }],
22
- stateMutability: 'view'
23
- },
24
- {
25
- type: 'function',
26
- name: 'token1',
27
- inputs: [],
28
- outputs: [{ name: '', type: 'address' }],
29
- stateMutability: 'view'
30
- }
31
- ]
32
- }
33
- }));
34
-
35
4
  describe('estimateLpTokens', () => {
36
5
  let publicClient: any;
37
6
  const mockVaultAddress = '0xd6bac58d87772fa3a7400f15fd121b7edc30ce3c' as Address;
38
- const mockToken0Address = '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619';
39
- const mockToken1Address = '0xc708d6f2153933daa50b2d0758955be0a93a8fec';
40
7
 
41
8
  beforeEach(() => {
42
- publicClient = createPublicClient({chain: polygon, transport: http()});
43
-
44
-
45
- // Initialize SteerClient with real clients
9
+ publicClient = {
10
+ getChainId: jest.fn().mockResolvedValue(137),
11
+ readContract: jest.fn(),
12
+ };
46
13
  });
47
14
 
48
- describe('successful LP token estimation', () => {
49
- it.only('should estimate LP tokens for token0 deposit with balanced swap', async () => {
50
-
51
- const params = {
52
- vault: mockVaultAddress as Address,
53
- originalAssets: 10000n, // Depositing 100 token0
54
- swapAmount: 47197431190251602083645n, // Swapping 50 token0
55
- swapResult: {
56
- amount0: -47197431190251602083645n, // 50 token0 out
57
- amount1: 226901274916051693072080311n, // 50 token1 in
58
- sqrtPriceX96After: BigInt('79228162514264337593543950336')
59
- },
60
- isToken0: true
61
- };
62
-
63
- const result = await estimateLpTokens(publicClient, params);
64
-
65
- expect(result.success).toBe(true);
66
- expect(result.status).toBe(200);
67
- expect(result.data).toBeDefined();
68
-
69
- // Final amounts should be:
70
- // token0: 100 - 50 + 50 = 100 (but we get 50 because 50 was swapped out)
71
- // token1: 0 + 50 = 50
72
- const expectedFinalAmount0 = parseEther('50'); // 100 - 50 (swapped) + 50 (from swap, but this is already deducted)
73
- const expectedFinalAmount1 = parseEther('50'); // 0 + 50 (from swap)
74
-
75
- expect(result.data?.finalAmount0).toBe(expectedFinalAmount0);
76
- expect(result.data?.finalAmount1).toBe(expectedFinalAmount1);
77
-
78
- // LP tokens calculation: min(amount0 * totalSupply / reserve0, amount1 * totalSupply / reserve1)
79
- // LP0 = 50 * 1000 / 500 = 100
80
- // LP1 = 50 * 1000 / 500 = 100
81
- // LP = min(100, 100) = 100
82
- expect(result.data?.lpTokens).toBe(parseEther('100'));
83
- });
84
-
85
- it('should estimate LP tokens for token1 deposit', async () => {
86
- const mockTotalSupply = parseEther('2000');
87
- const mockToken0Balance = parseEther('1000');
88
- const mockToken1Balance = parseEther('800');
89
-
90
- publicClient.readContract = jest.fn()
91
- .mockResolvedValueOnce(mockTotalSupply)
92
- .mockResolvedValueOnce(mockToken0Address)
93
- .mockResolvedValueOnce(mockToken1Address)
94
- .mockResolvedValueOnce(mockToken0Balance)
95
- .mockResolvedValueOnce(mockToken1Balance);
96
-
97
- const params = {
98
- vault: mockVaultAddress,
99
- originalAssets: parseEther('80'), // Depositing 80 token1
100
- swapAmount: parseEther('40'), // Swapping 40 token1
101
- swapResult: {
102
- amount0: parseEther('60'), // 60 token0 in
103
- amount1: -parseEther('40'), // 40 token1 out
104
- sqrtPriceX96After: BigInt('79228162514264337593543950336')
105
- },
106
- isToken0: false
107
- };
108
-
109
- const result = await estimateLpTokens(publicClient, params);
110
-
111
- expect(result.success).toBe(true);
112
-
113
- // Final amounts should be:
114
- // token0: 0 + 60 = 60
115
- // token1: 80 - 40 + 40 = 80 (but we get 40 because 40 was swapped out)
116
- const expectedFinalAmount0 = parseEther('60');
117
- const expectedFinalAmount1 = parseEther('40'); // 80 - 40 (swapped out)
118
-
119
- expect(result.data?.finalAmount0).toBe(expectedFinalAmount0);
120
- expect(result.data?.finalAmount1).toBe(expectedFinalAmount1);
121
-
122
- // LP calculation: min(60 * 2000 / 1000, 40 * 2000 / 800) = min(120, 100) = 100
123
- expect(result.data?.lpTokens).toBe(parseEther('100'));
124
- });
125
-
126
- it('should handle first deposit (zero total supply)', async () => {
127
- const mockTotalSupply = BigInt('0'); // First deposit
128
- const mockToken0Balance = BigInt('0');
129
- const mockToken1Balance = BigInt('0');
130
-
131
- publicClient.readContract = jest.fn()
132
- .mockResolvedValueOnce(mockTotalSupply)
133
- .mockResolvedValueOnce(mockToken0Address)
134
- .mockResolvedValueOnce(mockToken1Address)
135
- .mockResolvedValueOnce(mockToken0Balance)
136
- .mockResolvedValueOnce(mockToken1Balance);
137
-
138
- const params = {
139
- vault: mockVaultAddress,
140
- originalAssets: parseEther('100'),
141
- swapAmount: parseEther('50'),
142
- swapResult: {
143
- amount0: -parseEther('50'),
144
- amount1: parseEther('100'),
145
- sqrtPriceX96After: BigInt('79228162514264337593543950336')
146
- },
147
- isToken0: true
148
- };
149
-
150
- const result = await estimateLpTokens(publicClient, params);
151
-
152
- expect(result.success).toBe(true);
153
-
154
- const expectedFinalAmount0 = parseEther('50');
155
- const expectedFinalAmount1 = parseEther('100');
156
-
157
- expect(result.data?.finalAmount0).toBe(expectedFinalAmount0);
158
- expect(result.data?.finalAmount1).toBe(expectedFinalAmount1);
159
-
160
- // For first deposit, LP = sqrt(amount0 * amount1) = sqrt(50 * 100) = sqrt(5000) ≈ 70.71
161
- const expectedLpTokens = BigInt('70710678118654752440'); // sqrt(50 * 100 * 10^36)
162
- expect(result.data?.lpTokens).toBe(expectedLpTokens);
163
- });
164
-
165
- it('should handle imbalanced pool scenario', async () => {
166
- const mockTotalSupply = parseEther('1500');
167
- const mockToken0Balance = parseEther('300'); // Much less token0
168
- const mockToken1Balance = parseEther('1200'); // Much more token1
169
-
170
- publicClient.readContract = jest.fn()
171
- .mockResolvedValueOnce(mockTotalSupply)
172
- .mockResolvedValueOnce(mockToken0Address)
173
- .mockResolvedValueOnce(mockToken1Address)
174
- .mockResolvedValueOnce(mockToken0Balance)
175
- .mockResolvedValueOnce(mockToken1Balance);
176
-
177
- const params = {
178
- vault: mockVaultAddress,
179
- originalAssets: parseEther('100'),
180
- swapAmount: parseEther('80'), // Large swap due to imbalance
181
- swapResult: {
182
- amount0: -parseEther('80'),
183
- amount1: parseEther('40'), // Lower amount due to imbalanced pool
184
- sqrtPriceX96After: BigInt('79228162514264337593543950336')
185
- },
186
- isToken0: true
187
- };
188
-
189
- const result = await estimateLpTokens(publicClient, params);
190
-
191
- expect(result.success).toBe(true);
192
-
193
- const expectedFinalAmount0 = parseEther('20'); // 100 - 80 (swapped out)
194
- const expectedFinalAmount1 = parseEther('40'); // 0 + 40 (from swap)
195
-
196
- expect(result.data?.finalAmount0).toBe(expectedFinalAmount0);
197
- expect(result.data?.finalAmount1).toBe(expectedFinalAmount1);
198
-
199
- // LP calculation: min(20 * 1500 / 300, 40 * 1500 / 1200) = min(100, 50) = 50
200
- expect(result.data?.lpTokens).toBe(parseEther('50'));
201
- });
202
-
203
- it('should handle small amounts', async () => {
204
- const mockTotalSupply = parseEther('1000000'); // Large pool
205
- const mockToken0Balance = parseEther('500000');
206
- const mockToken1Balance = parseEther('500000');
207
-
208
- publicClient.readContract = jest.fn()
209
- .mockResolvedValueOnce(mockTotalSupply)
210
- .mockResolvedValueOnce(mockToken0Address)
211
- .mockResolvedValueOnce(mockToken1Address)
212
- .mockResolvedValueOnce(mockToken0Balance)
213
- .mockResolvedValueOnce(mockToken1Balance);
214
-
215
- const smallAmount = BigInt('1000000000000000'); // 0.001 tokens
216
- const params = {
217
- vault: mockVaultAddress,
218
- originalAssets: smallAmount * 2n,
219
- swapAmount: smallAmount,
220
- swapResult: {
221
- amount0: -smallAmount,
222
- amount1: smallAmount,
223
- sqrtPriceX96After: BigInt('79228162514264337593543950336')
224
- },
225
- isToken0: true
226
- };
227
-
228
- const result = await estimateLpTokens(publicClient, params);
229
-
230
- expect(result.success).toBe(true);
231
- expect(result.data?.finalAmount0).toBe(smallAmount);
232
- expect(result.data?.finalAmount1).toBe(smallAmount);
233
-
234
- // Should get proportional LP tokens
235
- const expectedLpTokens = smallAmount * 2n; // 2 * 0.001 = 0.002 LP
236
- expect(result.data?.lpTokens).toBe(expectedLpTokens);
15
+ it('estimates LP tokens for token0 deposit', async () => {
16
+ publicClient.readContract
17
+ .mockResolvedValueOnce(parseEther('1000'))
18
+ .mockResolvedValueOnce([parseEther('500'), parseEther('500')])
19
+ .mockResolvedValueOnce([parseEther('100'), parseEther('50'), parseEther('50')]);
20
+
21
+ const result = await estimateLpTokens(publicClient, {
22
+ vault: mockVaultAddress,
23
+ originalAssets: parseEther('100'),
24
+ swapAmount: parseEther('50'),
25
+ swapResult: {
26
+ amount0: -parseEther('50'),
27
+ amount1: parseEther('50'),
28
+ sqrtPriceX96After: 0n,
29
+ },
30
+ isToken0: true,
237
31
  });
238
32
 
239
- it('should handle zero reserves (edge case)', async () => {
240
- const mockTotalSupply = parseEther('1000');
241
- const mockToken0Balance = BigInt('0'); // Zero reserve
242
- const mockToken1Balance = parseEther('1000');
243
-
244
- publicClient.readContract = jest.fn()
245
- .mockResolvedValueOnce(mockTotalSupply)
246
- .mockResolvedValueOnce(mockToken0Address)
247
- .mockResolvedValueOnce(mockToken1Address)
248
- .mockResolvedValueOnce(mockToken0Balance)
249
- .mockResolvedValueOnce(mockToken1Balance);
250
-
251
- const params = {
252
- vault: mockVaultAddress,
253
- originalAssets: parseEther('100'),
254
- swapAmount: parseEther('50'),
255
- swapResult: {
256
- amount0: -parseEther('50'),
257
- amount1: parseEther('50')
258
- },
259
- isToken0: true
260
- };
261
-
262
- const result = await estimateLpTokens(publicClient, params);
263
-
264
- expect(result.success).toBe(true);
265
-
266
- // With zero token0 reserve, LP from token0 should be 0
267
- // LP = min(0, 50 * 1000 / 1000) = min(0, 50) = 0
268
- expect(result.data?.lpTokens).toBe(BigInt('0'));
269
- });
33
+ expect(result.success).toBe(true);
34
+ expect(result.status).toBe(200);
35
+ expect(result.data?.lpTokens).toBe(parseEther('100'));
36
+ expect(result.data?.finalAmount0).toBe(parseEther('50'));
37
+ expect(result.data?.finalAmount1).toBe(parseEther('50'));
38
+ expect(publicClient.getChainId).toHaveBeenCalledTimes(1);
270
39
  });
271
40
 
272
- describe('error handling', () => {
273
- it('should handle contract call errors', async () => {
274
- publicClient.readContract = jest.fn().mockRejectedValue(new Error('Contract call failed'));
275
-
276
- const params = {
277
- vault: mockVaultAddress,
278
- originalAssets: parseEther('100'),
279
- swapAmount: parseEther('50'),
280
- swapResult: {
281
- amount0: -parseEther('50'),
282
- amount1: parseEther('50')
283
- },
284
- isToken0: true
285
- };
286
-
287
- const result = await estimateLpTokens(publicClient, params);
288
-
289
- expect(result.success).toBe(false);
290
- expect(result.status).toBe(500);
291
- expect(result.error).toBe('Contract call failed');
292
- });
293
-
294
- it('should handle network errors', async () => {
295
- publicClient.readContract = jest.fn().mockRejectedValue(new Error('Network error'));
296
-
297
- const params = {
298
- vault: mockVaultAddress,
299
- originalAssets: parseEther('100'),
300
- swapAmount: parseEther('50'),
301
- swapResult: {
302
- amount0: -parseEther('50'),
303
- amount1: parseEther('50')
304
- },
305
- isToken0: true
306
- };
307
-
308
- const result = await estimateLpTokens(publicClient, params);
309
-
310
- expect(result.success).toBe(false);
311
- expect(result.error).toBe('Network error');
41
+ it('estimates LP tokens for token1 deposit', async () => {
42
+ publicClient.readContract
43
+ .mockResolvedValueOnce(parseEther('1000'))
44
+ .mockResolvedValueOnce([parseEther('400'), parseEther('600')])
45
+ .mockResolvedValueOnce([parseEther('80'), parseEther('20'), parseEther('60')]);
46
+
47
+ const result = await estimateLpTokens(publicClient, {
48
+ vault: mockVaultAddress,
49
+ originalAssets: parseEther('100'),
50
+ swapAmount: parseEther('40'),
51
+ swapResult: {
52
+ amount0: parseEther('20'),
53
+ amount1: -parseEther('40'),
54
+ sqrtPriceX96After: 0n,
55
+ },
56
+ isToken0: false,
312
57
  });
313
58
 
314
- it('should handle invalid vault address', async () => {
315
- publicClient.readContract = jest.fn().mockRejectedValue(
316
- new Error('Contract not found')
317
- );
318
-
319
- const params = {
320
- vault: '0x0000000000000000000000000000000000000000' as Address,
321
- originalAssets: parseEther('100'),
322
- swapAmount: parseEther('50'),
323
- swapResult: {
324
- amount0: -parseEther('50'),
325
- amount1: parseEther('50')
326
- },
327
- isToken0: true
328
- };
329
-
330
- const result = await estimateLpTokens(publicClient, params);
331
-
332
- expect(result.success).toBe(false);
333
- expect(result.error).toContain('Contract not found');
334
- });
59
+ expect(result.success).toBe(true);
60
+ expect(result.data?.lpTokens).toBe(parseEther('80'));
61
+ expect(result.data?.finalAmount0).toBe(parseEther('20'));
62
+ expect(result.data?.finalAmount1).toBe(parseEther('60'));
335
63
  });
336
64
 
337
- describe('edge cases and validations', () => {
338
- it('should handle negative swap amounts correctly', async () => {
339
- const mockTotalSupply = parseEther('1000');
340
- const mockToken0Balance = parseEther('500');
341
- const mockToken1Balance = parseEther('500');
342
-
343
- publicClient.readContract = jest.fn()
344
- .mockResolvedValueOnce(mockTotalSupply)
345
- .mockResolvedValueOnce(mockToken0Address)
346
- .mockResolvedValueOnce(mockToken1Address)
347
- .mockResolvedValueOnce(mockToken0Balance)
348
- .mockResolvedValueOnce(mockToken1Balance);
349
-
350
- const params = {
351
- vault: mockVaultAddress,
352
- originalAssets: parseEther('100'),
353
- swapAmount: parseEther('50'),
354
- swapResult: {
355
- amount0: parseEther('50'), // Positive amount0 (receiving)
356
- amount1: -parseEther('25') // Negative amount1 (giving)
357
- },
358
- isToken0: false // Depositing token1, swapping to token0
359
- };
360
-
361
- const result = await estimateLpTokens(publicClient, params);
362
-
363
- expect(result.success).toBe(true);
364
-
365
- // For token1 deposit: finalAmount0 = 0 + |amount0| = 50
366
- // finalAmount1 = originalAssets - swapAmount + |amount1| = 100 - 50 + 25 = 75
367
- expect(result.data?.finalAmount0).toBe(parseEther('50'));
368
- expect(result.data?.finalAmount1).toBe(parseEther('75'));
65
+ it('returns failure when on-chain reads fail', async () => {
66
+ publicClient.readContract.mockRejectedValue(new Error('Contract call failed'));
67
+
68
+ const result = await estimateLpTokens(publicClient, {
69
+ vault: mockVaultAddress,
70
+ originalAssets: parseEther('100'),
71
+ swapAmount: parseEther('50'),
72
+ swapResult: {
73
+ amount0: -parseEther('50'),
74
+ amount1: parseEther('50'),
75
+ sqrtPriceX96After: 0n,
76
+ },
77
+ isToken0: true,
369
78
  });
370
79
 
371
- it('should handle very large numbers', async () => {
372
- const largeSupply = parseEther('1000000000'); // 1 billion
373
- const largeBalance = parseEther('500000000'); // 500 million
374
-
375
- publicClient.readContract = jest.fn()
376
- .mockResolvedValueOnce(largeSupply)
377
- .mockResolvedValueOnce(mockToken0Address)
378
- .mockResolvedValueOnce(mockToken1Address)
379
- .mockResolvedValueOnce(largeBalance)
380
- .mockResolvedValueOnce(largeBalance);
381
-
382
- const params = {
383
- vault: mockVaultAddress,
384
- originalAssets: parseEther('1000000'), // 1 million
385
- swapAmount: parseEther('500000'), // 500k
386
- swapResult: {
387
- amount0: -parseEther('500000'),
388
- amount1: parseEther('500000')
389
- },
390
- isToken0: true
391
- };
392
-
393
- const result = await estimateLpTokens(publicClient, params);
80
+ expect(result.success).toBe(false);
81
+ expect(result.status).toBe(500);
82
+ expect(result.error).toBe('Contract call failed');
83
+ });
394
84
 
395
- expect(result.success).toBe(true);
396
- expect(result.data?.lpTokens).toBe(parseEther('1000000')); // Should get 1M LP tokens
85
+ it('returns failure when helper getShares reverts', async () => {
86
+ publicClient.readContract
87
+ .mockResolvedValueOnce(parseEther('1000'))
88
+ .mockResolvedValueOnce([parseEther('500'), parseEther('500')])
89
+ .mockRejectedValueOnce(new Error('getShares reverted'));
90
+
91
+ const result = await estimateLpTokens(publicClient, {
92
+ vault: mockVaultAddress,
93
+ originalAssets: parseEther('100'),
94
+ swapAmount: parseEther('50'),
95
+ swapResult: {
96
+ amount0: -parseEther('50'),
97
+ amount1: parseEther('50'),
98
+ sqrtPriceX96After: 0n,
99
+ },
100
+ isToken0: true,
397
101
  });
398
102
 
399
- it('should handle precision with small decimals', async () => {
400
- const mockTotalSupply = BigInt('1000000000000000000000'); // 1000 tokens with 18 decimals
401
- const mockToken0Balance = BigInt('500000000000000000000'); // 500 tokens
402
- const mockToken1Balance = BigInt('500000000000000000000'); // 500 tokens
403
-
404
- publicClient.readContract = jest.fn()
405
- .mockResolvedValueOnce(mockTotalSupply)
406
- .mockResolvedValueOnce(mockToken0Address)
407
- .mockResolvedValueOnce(mockToken1Address)
408
- .mockResolvedValueOnce(mockToken0Balance)
409
- .mockResolvedValueOnce(mockToken1Balance);
410
-
411
- // Very small amounts to test precision
412
- const params = {
413
- vault: mockVaultAddress,
414
- originalAssets: BigInt('1000000000000000'), // 0.001 tokens
415
- swapAmount: BigInt('500000000000000'), // 0.0005 tokens
416
- swapResult: {
417
- amount0: -BigInt('500000000000000'),
418
- amount1: BigInt('500000000000000')
419
- },
420
- isToken0: true
421
- };
422
-
423
- const result = await estimateLpTokens(publicClient, params);
424
-
425
- expect(result.success).toBe(true);
426
- expect(result.data?.lpTokens).toBeGreaterThan(BigInt('0'));
427
-
428
- // Should maintain precision
429
- const expectedFinalAmount0 = BigInt('500000000000000');
430
- const expectedFinalAmount1 = BigInt('500000000000000');
431
- expect(result.data?.finalAmount0).toBe(expectedFinalAmount0);
432
- expect(result.data?.finalAmount1).toBe(expectedFinalAmount1);
433
- });
103
+ expect(result.success).toBe(false);
104
+ expect(result.error).toBe('getShares reverted');
434
105
  });
435
106
  });
436
107
 
@@ -441,172 +112,36 @@ describe('getVaultReserves', () => {
441
112
  const mockToken1Address = '0x3456789012345678901234567890123456789012' as `0x${string}`;
442
113
 
443
114
  beforeEach(() => {
444
- const testClient = createTestClient({
445
- account: privateKeyToAccount("0x40199ba8875ac583658a7e936e16354f4bf1ea54dac73a2bc24fd17159ceb821"),
446
- chain: foundry,
447
- mode: 'anvil',
448
- transport: http(),
449
- }).extend(publicActions);
450
-
451
- publicClient = testClient;
115
+ publicClient = {
116
+ readContract: jest.fn(),
117
+ };
452
118
  });
453
119
 
454
- describe('successful reserve retrieval', () => {
455
- it('should get vault reserves correctly', async () => {
456
- const mockTotalSupply = parseEther('1000');
457
- const mockToken0Balance = parseEther('400');
458
- const mockToken1Balance = parseEther('600');
459
-
460
- publicClient.readContract = jest.fn()
461
- .mockResolvedValueOnce(mockTotalSupply) // totalSupply
462
- .mockResolvedValueOnce(mockToken0Address) // token0 address
463
- .mockResolvedValueOnce(mockToken1Address) // token1 address
464
- .mockResolvedValueOnce(mockToken0Balance) // token0 balanceOf
465
- .mockResolvedValueOnce(mockToken1Balance); // token1 balanceOf
466
-
467
- const result = await getVaultReserves(publicClient, mockVaultAddress);
120
+ it('gets vault reserves correctly', async () => {
121
+ publicClient.readContract
122
+ .mockResolvedValueOnce(parseEther('1000'))
123
+ .mockResolvedValueOnce(mockToken0Address)
124
+ .mockResolvedValueOnce(mockToken1Address)
125
+ .mockResolvedValueOnce(parseEther('400'))
126
+ .mockResolvedValueOnce(parseEther('600'));
468
127
 
469
- expect(result.success).toBe(true);
470
- expect(result.status).toBe(200);
471
- expect(result.data).toEqual({
472
- token0Balance: mockToken0Balance,
473
- token1Balance: mockToken1Balance,
474
- totalSupply: mockTotalSupply
475
- });
128
+ const result = await getVaultReserves(publicClient, mockVaultAddress);
476
129
 
477
- // Verify correct sequence of contract calls
478
- expect(publicClient.readContract).toHaveBeenCalledTimes(5);
479
- });
480
-
481
- it('should handle empty vault', async () => {
482
- const mockTotalSupply = BigInt('0');
483
- const mockToken0Balance = BigInt('0');
484
- const mockToken1Balance = BigInt('0');
485
-
486
- publicClient.readContract = jest.fn()
487
- .mockResolvedValueOnce(mockTotalSupply)
488
- .mockResolvedValueOnce(mockToken0Address)
489
- .mockResolvedValueOnce(mockToken1Address)
490
- .mockResolvedValueOnce(mockToken0Balance)
491
- .mockResolvedValueOnce(mockToken1Balance);
492
-
493
- const result = await getVaultReserves(publicClient, mockVaultAddress);
494
-
495
- expect(result.success).toBe(true);
496
- expect(result.data?.totalSupply).toBe(BigInt('0'));
497
- expect(result.data?.token0Balance).toBe(BigInt('0'));
498
- expect(result.data?.token1Balance).toBe(BigInt('0'));
499
- });
500
-
501
- it('should handle very large reserves', async () => {
502
- const largeTotalSupply = parseEther('1000000000'); // 1 billion
503
- const largeToken0Balance = parseEther('500000000');
504
- const largeToken1Balance = parseEther('750000000');
505
-
506
- publicClient.readContract = jest.fn()
507
- .mockResolvedValueOnce(largeTotalSupply)
508
- .mockResolvedValueOnce(mockToken0Address)
509
- .mockResolvedValueOnce(mockToken1Address)
510
- .mockResolvedValueOnce(largeToken0Balance)
511
- .mockResolvedValueOnce(largeToken1Balance);
512
-
513
- const result = await getVaultReserves(publicClient, mockVaultAddress);
514
-
515
- expect(result.success).toBe(true);
516
- expect(result.data?.totalSupply).toBe(largeTotalSupply);
517
- expect(result.data?.token0Balance).toBe(largeToken0Balance);
518
- expect(result.data?.token1Balance).toBe(largeToken1Balance);
519
- });
520
- });
521
-
522
- describe('error handling', () => {
523
- it('should handle vault contract errors', async () => {
524
- publicClient.readContract = jest.fn().mockRejectedValue(new Error('Vault contract error'));
525
-
526
- const result = await getVaultReserves(publicClient, mockVaultAddress);
527
-
528
- expect(result.success).toBe(false);
529
- expect(result.status).toBe(500);
530
- expect(result.error).toBe('Vault contract error');
531
- });
532
-
533
- it('should handle token contract errors', async () => {
534
- publicClient.readContract = jest.fn()
535
- .mockResolvedValueOnce(parseEther('1000')) // totalSupply succeeds
536
- .mockResolvedValueOnce(mockToken0Address) // token0 address succeeds
537
- .mockResolvedValueOnce(mockToken1Address) // token1 address succeeds
538
- .mockRejectedValue(new Error('Token contract error')); // balanceOf fails
539
-
540
- const result = await getVaultReserves(publicClient, mockVaultAddress);
541
-
542
- expect(result.success).toBe(false);
543
- expect(result.error).toBe('Token contract error');
544
- });
545
-
546
- it('should handle invalid vault address', async () => {
547
- const invalidVault = '0x0000000000000000000000000000000000000000' as `0x${string}`;
548
-
549
- publicClient.readContract = jest.fn().mockRejectedValue(
550
- new Error('Contract not found')
551
- );
552
-
553
- const result = await getVaultReserves(publicClient, invalidVault);
554
-
555
- expect(result.success).toBe(false);
556
- expect(result.error).toContain('Contract not found');
130
+ expect(result.success).toBe(true);
131
+ expect(result.data).toEqual({
132
+ token0Balance: parseEther('400'),
133
+ token1Balance: parseEther('600'),
134
+ totalSupply: parseEther('1000'),
557
135
  });
558
136
  });
559
137
 
560
- describe('integration scenarios', () => {
561
- it('should handle realistic vault data', async () => {
562
- // Simulate a realistic USDC/ETH vault
563
- const mockTotalSupply = parseEther('50000'); // 50k LP tokens
564
- const mockUsdcBalance = BigInt('25000000000'); // 25k USDC (6 decimals)
565
- const mockEthBalance = parseEther('12.5'); // 12.5 ETH (18 decimals)
566
-
567
- publicClient.readContract = jest.fn()
568
- .mockResolvedValueOnce(mockTotalSupply)
569
- .mockResolvedValueOnce(mockToken0Address) // USDC
570
- .mockResolvedValueOnce(mockToken1Address) // ETH
571
- .mockResolvedValueOnce(mockUsdcBalance)
572
- .mockResolvedValueOnce(mockEthBalance);
138
+ it('returns failure when vault calls fail', async () => {
139
+ publicClient.readContract.mockRejectedValue(new Error('Vault contract error'));
573
140
 
574
- const result = await getVaultReserves(publicClient, mockVaultAddress);
141
+ const result = await getVaultReserves(publicClient, mockVaultAddress);
575
142
 
576
- expect(result.success).toBe(true);
577
- expect(result.data?.token0Balance).toBe(mockUsdcBalance);
578
- expect(result.data?.token1Balance).toBe(mockEthBalance);
579
- expect(result.data?.totalSupply).toBe(mockTotalSupply);
580
- });
581
-
582
- it('should handle sequential calls correctly', async () => {
583
- const calls = [
584
- parseEther('1000'), // totalSupply
585
- mockToken0Address, // token0
586
- mockToken1Address, // token1
587
- parseEther('500'), // token0 balance
588
- parseEther('500') // token1 balance
589
- ];
590
-
591
- publicClient.readContract = jest.fn()
592
- .mockResolvedValueOnce(calls[0])
593
- .mockResolvedValueOnce(calls[1])
594
- .mockResolvedValueOnce(calls[2])
595
- .mockResolvedValueOnce(calls[3])
596
- .mockResolvedValueOnce(calls[4]);
597
-
598
- const result = await getVaultReserves(publicClient, mockVaultAddress);
599
-
600
- expect(result.success).toBe(true);
601
- expect(publicClient.readContract).toHaveBeenCalledTimes(5);
602
-
603
- // Verify the correct ABI functions were called
604
- const readContractCalls = (publicClient.readContract as jest.Mock).mock.calls;
605
- expect(readContractCalls[0][0].functionName).toBe('totalSupply');
606
- expect(readContractCalls[1][0].functionName).toBe('token0');
607
- expect(readContractCalls[2][0].functionName).toBe('token1');
608
- expect(readContractCalls[3][0].functionName).toBe('balanceOf');
609
- expect(readContractCalls[4][0].functionName).toBe('balanceOf');
610
- });
143
+ expect(result.success).toBe(false);
144
+ expect(result.status).toBe(500);
145
+ expect(result.error).toBe('Vault contract error');
611
146
  });
612
- });
147
+ });