@steerprotocol/sdk 1.30.8-test-algebra-plugins.2 → 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.
- package/dist/cjs/base/PoolClient.js +137 -0
- package/dist/cjs/base/PoolClient.js.map +1 -1
- package/dist/cjs/base/VaultClient.js +111 -2
- package/dist/cjs/base/VaultClient.js.map +1 -1
- package/dist/cjs/const/feeManagerContracts.js +25 -0
- package/dist/cjs/const/feeManagerContracts.js.map +1 -0
- package/dist/cjs/const/network.js +7 -0
- package/dist/cjs/const/network.js.map +1 -1
- package/dist/cjs/const/protocol.js +68 -92
- package/dist/cjs/const/protocol.js.map +1 -1
- package/dist/cjs/scripts/processDeployments.js +1 -0
- package/dist/cjs/scripts/processDeployments.js.map +1 -1
- package/dist/esm/base/PoolClient.js +137 -0
- package/dist/esm/base/PoolClient.js.map +1 -1
- package/dist/esm/base/VaultClient.js +111 -2
- package/dist/esm/base/VaultClient.js.map +1 -1
- package/dist/esm/const/feeManagerContracts.js +25 -0
- package/dist/esm/const/feeManagerContracts.js.map +1 -0
- package/dist/esm/const/network.js +7 -0
- package/dist/esm/const/network.js.map +1 -1
- package/dist/esm/const/protocol.js +68 -92
- package/dist/esm/const/protocol.js.map +1 -1
- package/dist/esm/scripts/processDeployments.js +1 -0
- package/dist/esm/scripts/processDeployments.js.map +1 -1
- package/dist/types/base/PoolClient.d.ts +22 -0
- package/dist/types/base/PoolClient.d.ts.map +1 -1
- package/dist/types/base/VaultClient.d.ts +20 -0
- package/dist/types/base/VaultClient.d.ts.map +1 -1
- package/dist/types/const/feeManagerContracts.d.ts +6 -0
- package/dist/types/const/feeManagerContracts.d.ts.map +1 -0
- package/dist/types/const/network.d.ts +1 -0
- package/dist/types/const/network.d.ts.map +1 -1
- package/dist/types/const/protocol.d.ts +4 -19
- package/dist/types/const/protocol.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/__tests__/base/PoolClient.test.ts +355 -104
- package/src/__tests__/base/StakingClient.test.ts +72 -72
- package/src/__tests__/base/VaultClient.protocol-filter.test.ts +64 -137
- package/src/__tests__/base/VaultClient.test.ts +460 -60
- package/src/__tests__/base/vault/single-asset/calculateLimitPrice.test.ts +32 -14
- package/src/__tests__/base/vault/single-asset/calculateSwapAmount.test.ts +7 -4
- package/src/__tests__/base/vault/single-asset/estimateLpTokens.test.ts +105 -570
- package/src/__tests__/base/vault/single-asset/simulateSwap.test.ts +45 -66
- package/src/__tests__/base/vault/single-asset/singleAssetDepositClient.test.ts +178 -381
- package/src/__tests__/const/network.feeManager.test.ts +47 -0
- package/src/__tests__/fixtures/live/single-asset.fixture.json +116 -0
- package/src/__tests__/fixtures/live/staking-pools.fixture.json +353 -0
- package/src/__tests__/fixtures/live/vaults.fixture.json +5392 -0
- package/src/base/PoolClient.ts +200 -1
- package/src/base/VaultClient.ts +169 -2
- package/src/const/feeManagerContracts.ts +28 -0
- package/src/const/network.ts +10 -1
- package/src/const/protocol.ts +18 -39
- package/src/scripts/processDeployments.ts +1 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
1
3
|
import { createTestClient, http, publicActions, walletActions } from 'viem';
|
|
2
4
|
import { foundry } from 'viem/chains';
|
|
3
5
|
import { StakingClient } from '../../base/StakingClient.js';
|
|
@@ -5,7 +7,24 @@ import { privateKeyToAccount } from 'viem/accounts';
|
|
|
5
7
|
import { createPublicClient, createWalletClient } from 'viem';
|
|
6
8
|
import { kava } from 'viem/chains';
|
|
7
9
|
import { SteerClient } from '../../client.js';
|
|
8
|
-
import { StakingProtocol } from '../../const/protocol.js';
|
|
10
|
+
import { StakingProtocol, isValidStakingProtocol, normalizeProtocol } from '../../const/protocol.js';
|
|
11
|
+
|
|
12
|
+
const stakingPoolsFixturePath = resolve(__dirname, '../fixtures/live/staking-pools.fixture.json');
|
|
13
|
+
const stakingPoolsFixture = JSON.parse(readFileSync(stakingPoolsFixturePath, 'utf8')) as {
|
|
14
|
+
livePools: any[];
|
|
15
|
+
selectedPools: any[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const dedupedFixturePools = [...stakingPoolsFixture.livePools, ...stakingPoolsFixture.selectedPools].filter(
|
|
19
|
+
(pool, index, pools) => pools.findIndex((item) => item.stakingPool === pool.stakingPool) === index,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const normalizedFixturePools = dedupedFixturePools
|
|
23
|
+
.filter((pool) => isValidStakingProtocol(pool.protocol))
|
|
24
|
+
.map((pool) => ({
|
|
25
|
+
...pool,
|
|
26
|
+
protocol: normalizeProtocol(pool.protocol),
|
|
27
|
+
}));
|
|
9
28
|
|
|
10
29
|
describe('StakingClient', () => {
|
|
11
30
|
let client: StakingClient;
|
|
@@ -28,131 +47,104 @@ describe('StakingClient', () => {
|
|
|
28
47
|
});
|
|
29
48
|
|
|
30
49
|
describe('getStakingPools', () => {
|
|
31
|
-
// const mockStakingPools = [
|
|
32
|
-
// {
|
|
33
|
-
// chainId: 137,
|
|
34
|
-
// stakingPool: '0x1234567890123456789012345678901234567890',
|
|
35
|
-
// protocol: 'forge', // lowercase protocol
|
|
36
|
-
// isDualFactory: true,
|
|
37
|
-
// dailyEmissionRewardA: 657.6,
|
|
38
|
-
// dailyEmissionRewardB: 11234.624,
|
|
39
|
-
// rewardTokenA: '0xD4949664cD82660AaE99bEdc034a0deA8A0bd517',
|
|
40
|
-
// rewardTokenB: '0x98fAFD9F714CE0B4bB2870527076F2F314aAed82',
|
|
41
|
-
// periodFinish: (Math.floor(Date.now() / 1000) + 86400).toString(), // 24 hours from now
|
|
42
|
-
// rewardsDuration: '604800'
|
|
43
|
-
// },
|
|
44
|
-
// {
|
|
45
|
-
// chainId: 1,
|
|
46
|
-
// stakingPool: '0x2234567890123456789012345678901234567890',
|
|
47
|
-
// protocol: 'ARTHSWAP', // uppercase protocol
|
|
48
|
-
// isDualFactory: false,
|
|
49
|
-
// dailyEmissionRewardA: 100,
|
|
50
|
-
// dailyEmissionRewardB: 0,
|
|
51
|
-
// rewardTokenA: '0xD4949664cD82660AaE99bEdc034a0deA8A0bd517',
|
|
52
|
-
// rewardTokenB: '',
|
|
53
|
-
// periodFinish: (Math.floor(Date.now() / 1000) - 86400).toString(), // 24 hours ago
|
|
54
|
-
// rewardsDuration: '604800'
|
|
55
|
-
// },
|
|
56
|
-
// {
|
|
57
|
-
// chainId: 137,
|
|
58
|
-
// stakingPool: '0x3234567890123456789012345678901234567890',
|
|
59
|
-
// protocol: 'Forge', // correct case protocol
|
|
60
|
-
// isDualFactory: true,
|
|
61
|
-
// dailyEmissionRewardA: 1000,
|
|
62
|
-
// dailyEmissionRewardB: 2000,
|
|
63
|
-
// rewardTokenA: '0xD4949664cD82660AaE99bEdc034a0deA8A0bd517',
|
|
64
|
-
// rewardTokenB: '0x98fAFD9F714CE0B4bB2870527076F2F314aAed82',
|
|
65
|
-
// periodFinish: (Math.floor(Date.now() / 1000) + 86400).toString(), // 24 hours from now
|
|
66
|
-
// rewardsDuration: '604800'
|
|
67
|
-
// }
|
|
68
|
-
// ];
|
|
69
|
-
|
|
70
50
|
beforeEach(() => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
51
|
+
global.fetch = jest.fn().mockResolvedValue({
|
|
52
|
+
ok: true,
|
|
53
|
+
json: async () => ({ pools: dedupedFixturePools }),
|
|
54
|
+
});
|
|
75
55
|
});
|
|
76
56
|
|
|
77
57
|
it('should fetch all staking pools without filters', async () => {
|
|
78
58
|
const response = await client.getStakingPools();
|
|
79
59
|
expect(response.success).toBe(true);
|
|
80
60
|
expect(response.status).toBe(200);
|
|
81
|
-
expect(response.data).toHaveLength(
|
|
61
|
+
expect(response.data).toHaveLength(normalizedFixturePools.length);
|
|
82
62
|
});
|
|
83
63
|
|
|
84
64
|
it('should filter pools by chainId', async () => {
|
|
65
|
+
const expected = normalizedFixturePools.filter((pool) => pool.chainId === 2222);
|
|
85
66
|
const response = await client.getStakingPools({
|
|
86
|
-
chainId:
|
|
67
|
+
chainId: 2222
|
|
87
68
|
});
|
|
88
69
|
expect(response.success).toBe(true);
|
|
89
|
-
expect(response.data).toHaveLength(
|
|
90
|
-
expect(response.data!.every(pool => pool.chainId ===
|
|
70
|
+
expect(response.data).toHaveLength(expected.length);
|
|
71
|
+
expect(response.data!.every(pool => pool.chainId === 2222)).toBe(true);
|
|
91
72
|
});
|
|
92
73
|
|
|
93
74
|
it('should filter pools by chainId and protocol', async () => {
|
|
75
|
+
const expected = normalizedFixturePools.filter(
|
|
76
|
+
(pool) => pool.chainId === 2222 && pool.protocol === StakingProtocol.Kinetix,
|
|
77
|
+
);
|
|
94
78
|
const response = await client.getStakingPools({
|
|
95
79
|
chainId: 2222,
|
|
96
80
|
protocol: StakingProtocol.Kinetix
|
|
97
81
|
});
|
|
98
82
|
expect(response.success).toBe(true);
|
|
99
|
-
expect(response.data).toHaveLength(
|
|
83
|
+
expect(response.data).toHaveLength(expected.length);
|
|
100
84
|
expect(response.data!.every(pool =>
|
|
101
|
-
pool.chainId ===
|
|
85
|
+
pool.chainId === 2222 && pool.protocol === StakingProtocol.Kinetix
|
|
102
86
|
)).toBe(true);
|
|
103
87
|
});
|
|
104
88
|
|
|
105
89
|
it('should filter live pools', async () => {
|
|
90
|
+
const now = Math.floor(Date.now() / 1000);
|
|
91
|
+
const expected = normalizedFixturePools.filter((pool) => parseInt(pool.periodFinish) > now);
|
|
106
92
|
const response = await client.getStakingPools({
|
|
107
93
|
isLive: true
|
|
108
94
|
});
|
|
109
95
|
expect(response.success).toBe(true);
|
|
110
|
-
expect(response.data!.length).toBe(
|
|
96
|
+
expect(response.data!.length).toBe(expected.length);
|
|
111
97
|
expect(response.data!.every(pool => {
|
|
112
|
-
const now = Math.floor(Date.now() / 1000);
|
|
113
98
|
return parseInt(pool.periodFinish) > now;
|
|
114
99
|
})).toBe(true);
|
|
115
100
|
});
|
|
116
101
|
|
|
117
102
|
it('should filter by chainId and live status', async () => {
|
|
103
|
+
const now = Math.floor(Date.now() / 1000);
|
|
104
|
+
const expected = normalizedFixturePools.filter(
|
|
105
|
+
(pool) => pool.chainId === 8453 && parseInt(pool.periodFinish) > now,
|
|
106
|
+
);
|
|
118
107
|
const response = await client.getStakingPools({
|
|
119
|
-
chainId:
|
|
108
|
+
chainId: 8453,
|
|
120
109
|
isLive: true
|
|
121
110
|
});
|
|
122
111
|
expect(response.success).toBe(true);
|
|
123
|
-
expect(response.data!.length).toBe(
|
|
112
|
+
expect(response.data!.length).toBe(expected.length);
|
|
124
113
|
expect(response.data!.every(pool => {
|
|
125
|
-
|
|
126
|
-
return pool.chainId === 137 && parseInt(pool.periodFinish) > now;
|
|
114
|
+
return pool.chainId === 8453 && parseInt(pool.periodFinish) > now;
|
|
127
115
|
})).toBe(true);
|
|
128
116
|
});
|
|
129
117
|
|
|
130
118
|
it('should filter using multiple criteria', async () => {
|
|
119
|
+
const expected = normalizedFixturePools.filter(
|
|
120
|
+
(pool) =>
|
|
121
|
+
pool.chainId === 2222 &&
|
|
122
|
+
pool.protocol === StakingProtocol.Kinetix &&
|
|
123
|
+
pool.isDualFactory === true,
|
|
124
|
+
);
|
|
131
125
|
const response = await client.getStakingPools({
|
|
132
|
-
chainId:
|
|
133
|
-
protocol: StakingProtocol.
|
|
134
|
-
isLive: true,
|
|
126
|
+
chainId: 2222,
|
|
127
|
+
protocol: StakingProtocol.Kinetix,
|
|
135
128
|
isDualRewards: true
|
|
136
129
|
});
|
|
137
130
|
|
|
138
131
|
expect(response.success).toBe(true);
|
|
139
|
-
expect(response.data!.length).toBe(
|
|
132
|
+
expect(response.data!.length).toBe(expected.length);
|
|
140
133
|
expect(response.data!.every(pool => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
pool.protocol === StakingProtocol.Forge &&
|
|
144
|
-
parseInt(pool.periodFinish) > now &&
|
|
134
|
+
return pool.chainId === 2222 &&
|
|
135
|
+
pool.protocol === StakingProtocol.Kinetix &&
|
|
145
136
|
pool.isDualFactory === true;
|
|
146
137
|
})).toBe(true);
|
|
147
138
|
});
|
|
148
139
|
|
|
149
140
|
it('should filter by minimum daily emissions', async () => {
|
|
141
|
+
const expected = normalizedFixturePools.filter((pool) => pool.dailyEmissionRewardA >= 800);
|
|
150
142
|
const response = await client.getStakingPools({
|
|
151
143
|
minDailyEmissionA: 800
|
|
152
144
|
});
|
|
153
145
|
|
|
154
146
|
expect(response.success).toBe(true);
|
|
155
|
-
expect(response.data!.length).toBe(
|
|
147
|
+
expect(response.data!.length).toBe(expected.length);
|
|
156
148
|
expect(response.data!.every(pool => pool.dailyEmissionRewardA >= 800)).toBe(true);
|
|
157
149
|
});
|
|
158
150
|
|
|
@@ -170,7 +162,7 @@ describe('StakingClient', () => {
|
|
|
170
162
|
|
|
171
163
|
it('should return empty array when no pools match filters', async () => {
|
|
172
164
|
const response = await client.getStakingPools({
|
|
173
|
-
chainId: 999,
|
|
165
|
+
chainId: 999,
|
|
174
166
|
protocol: StakingProtocol.ArthSwap
|
|
175
167
|
});
|
|
176
168
|
|
|
@@ -179,12 +171,13 @@ describe('StakingClient', () => {
|
|
|
179
171
|
});
|
|
180
172
|
|
|
181
173
|
it('should handle case-insensitive protocol matching', async () => {
|
|
174
|
+
const expected = normalizedFixturePools.filter((pool) => pool.protocol === StakingProtocol.Forge);
|
|
182
175
|
const response = await client.getStakingPools({
|
|
183
176
|
protocol: StakingProtocol.Forge
|
|
184
177
|
});
|
|
185
178
|
|
|
186
179
|
expect(response.success).toBe(true);
|
|
187
|
-
expect(response.data!.length).toBe(
|
|
180
|
+
expect(response.data!.length).toBe(expected.length);
|
|
188
181
|
expect(response.data!.every(pool => pool.protocol === StakingProtocol.Forge)).toBe(true);
|
|
189
182
|
});
|
|
190
183
|
|
|
@@ -192,9 +185,10 @@ describe('StakingClient', () => {
|
|
|
192
185
|
const response = await client.getStakingPools();
|
|
193
186
|
|
|
194
187
|
expect(response.success).toBe(true);
|
|
195
|
-
expect(response.data!.length).toBe(
|
|
188
|
+
expect(response.data!.length).toBe(normalizedFixturePools.length);
|
|
196
189
|
expect(response.data!.find(pool => pool.protocol === StakingProtocol.ArthSwap)).toBeDefined();
|
|
197
|
-
expect(response.data!.
|
|
190
|
+
expect(response.data!.find(pool => pool.protocol === StakingProtocol.Kinetix)).toBeDefined();
|
|
191
|
+
expect(response.data!.find(pool => pool.protocol === StakingProtocol.QuickSwapV3)).toBeDefined();
|
|
198
192
|
});
|
|
199
193
|
});
|
|
200
194
|
|
|
@@ -427,7 +421,10 @@ describe('StakingClient', () => {
|
|
|
427
421
|
expect(poolsResponse.success).toBe(true);
|
|
428
422
|
expect(poolsResponse.data).toBeDefined();
|
|
429
423
|
expect(Array.isArray(poolsResponse.data)).toBe(true);
|
|
430
|
-
|
|
424
|
+
if (poolsResponse.data!.length === 0) {
|
|
425
|
+
console.log('No active staking pools found on Polygon');
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
431
428
|
|
|
432
429
|
// Log the number of active pools found
|
|
433
430
|
console.log(`Found ${poolsResponse.data!.length} active staking pools on Polygon`);
|
|
@@ -504,7 +501,10 @@ describe('StakingClient', () => {
|
|
|
504
501
|
});
|
|
505
502
|
|
|
506
503
|
expect(poolsResponse.success).toBe(true);
|
|
507
|
-
|
|
504
|
+
if (poolsResponse.data!.length === 0) {
|
|
505
|
+
console.log('No active pools found to test totalSupply and balanceOf');
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
508
|
|
|
509
509
|
// Check first active pool
|
|
510
510
|
const testPool = poolsResponse.data![0];
|
|
@@ -769,4 +769,4 @@ describe('StakingClient', () => {
|
|
|
769
769
|
afterEach(() => {
|
|
770
770
|
jest.restoreAllMocks();
|
|
771
771
|
});
|
|
772
|
-
});
|
|
772
|
+
});
|
|
@@ -1,104 +1,25 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
1
3
|
import type { PublicClient, WalletClient } from 'viem';
|
|
2
|
-
import { VaultClient } from '../../base/VaultClient.js';
|
|
4
|
+
import { VaultClient, type VaultEdge, type VaultNode } from '../../base/VaultClient.js';
|
|
3
5
|
import { ChainId } from '../../const/chain.js';
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
vaultAddress: string;
|
|
11
|
-
protocol: string;
|
|
12
|
-
beaconName: string;
|
|
13
|
-
protocolBaseType: string;
|
|
14
|
-
name: string;
|
|
15
|
-
feeApr?: number | null;
|
|
16
|
-
stakingApr?: number | null;
|
|
17
|
-
merklApr?: number | null;
|
|
18
|
-
pool?: {
|
|
19
|
-
id?: string;
|
|
20
|
-
poolAddress?: string;
|
|
21
|
-
feeTier?: string;
|
|
22
|
-
};
|
|
23
|
-
token0?: {
|
|
24
|
-
id?: string;
|
|
25
|
-
symbol?: string;
|
|
26
|
-
name?: string;
|
|
27
|
-
decimals?: number;
|
|
28
|
-
address?: string;
|
|
29
|
-
chainId?: number;
|
|
30
|
-
};
|
|
31
|
-
token1?: {
|
|
32
|
-
id?: string;
|
|
33
|
-
symbol?: string;
|
|
34
|
-
name?: string;
|
|
35
|
-
decimals?: number;
|
|
36
|
-
address?: string;
|
|
37
|
-
chainId?: number;
|
|
38
|
-
};
|
|
39
|
-
};
|
|
7
|
+
const fixture = JSON.parse(
|
|
8
|
+
readFileSync(resolve(__dirname, '../fixtures/live/vaults.fixture.json'), 'utf8'),
|
|
9
|
+
) as {
|
|
10
|
+
selectedForProtocolFilter: VaultNode[];
|
|
11
|
+
selectedForPagination: VaultNode[];
|
|
40
12
|
};
|
|
41
13
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
beaconName: string = `MultiPosition${protocol}`
|
|
46
|
-
): ApiVaultEdge => ({
|
|
47
|
-
cursor: id,
|
|
48
|
-
node: {
|
|
49
|
-
id,
|
|
50
|
-
chainId: ChainId.Polygon,
|
|
51
|
-
vaultAddress: `0x${id.padEnd(40, '0').slice(0, 40)}`,
|
|
52
|
-
protocol,
|
|
53
|
-
beaconName,
|
|
54
|
-
protocolBaseType: protocol,
|
|
55
|
-
name: `${protocol} vault`,
|
|
56
|
-
pool: {
|
|
57
|
-
id: `pool-${id}`,
|
|
58
|
-
poolAddress: `pool-${id}`,
|
|
59
|
-
feeTier: '3000',
|
|
60
|
-
},
|
|
61
|
-
token0: {
|
|
62
|
-
id: 'token0',
|
|
63
|
-
symbol: 'USDC',
|
|
64
|
-
name: 'USD Coin',
|
|
65
|
-
decimals: 6,
|
|
66
|
-
address: '0x0000000000000000000000000000000000000001',
|
|
67
|
-
chainId: ChainId.Polygon,
|
|
68
|
-
},
|
|
69
|
-
token1: {
|
|
70
|
-
id: 'token1',
|
|
71
|
-
symbol: 'WETH',
|
|
72
|
-
name: 'Wrapped Ether',
|
|
73
|
-
decimals: 18,
|
|
74
|
-
address: '0x0000000000000000000000000000000000000002',
|
|
75
|
-
chainId: ChainId.Polygon,
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const buildApiVaultsResponse = (
|
|
81
|
-
edges: ApiVaultEdge[],
|
|
82
|
-
hasNextPage: boolean,
|
|
83
|
-
endCursor: string | null,
|
|
84
|
-
totalCount: number = edges.length
|
|
85
|
-
) => ({
|
|
86
|
-
status: 200,
|
|
87
|
-
data: {
|
|
88
|
-
vaults: {
|
|
89
|
-
edges,
|
|
90
|
-
pageInfo: {
|
|
91
|
-
hasNextPage,
|
|
92
|
-
endCursor,
|
|
93
|
-
},
|
|
94
|
-
totalCount,
|
|
95
|
-
},
|
|
96
|
-
},
|
|
14
|
+
const toEdge = (node: VaultNode, index: number): VaultEdge => ({
|
|
15
|
+
cursor: `fixture_${index}_${node.vaultAddress.toLowerCase()}`,
|
|
16
|
+
node,
|
|
97
17
|
});
|
|
98
18
|
|
|
99
19
|
describe('VaultClient protocol filtering', () => {
|
|
100
20
|
let vaultClient: VaultClient;
|
|
101
|
-
let
|
|
21
|
+
let getAllVaultsFromApiSpy: jest.SpyInstance;
|
|
22
|
+
let getAllVaultsFromSubgraphSpy: jest.SpyInstance;
|
|
102
23
|
|
|
103
24
|
beforeEach(() => {
|
|
104
25
|
vaultClient = new VaultClient(
|
|
@@ -106,74 +27,80 @@ describe('VaultClient protocol filtering', () => {
|
|
|
106
27
|
{} as WalletClient,
|
|
107
28
|
'production'
|
|
108
29
|
);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
(vaultClient as unknown as { apiClient: { vaults: jest.Mock } }).apiClient = {
|
|
112
|
-
vaults: vaultsMock,
|
|
113
|
-
};
|
|
30
|
+
getAllVaultsFromApiSpy = jest.spyOn(vaultClient as any, 'getAllVaultsFromApi');
|
|
31
|
+
getAllVaultsFromSubgraphSpy = jest.spyOn(vaultClient as any, 'getAllVaultsFromSubgraph');
|
|
114
32
|
});
|
|
115
33
|
|
|
116
34
|
it('filters getVaults results by protocol even when API returns mixed protocols', async () => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
35
|
+
const protocolFixtureNodes = (fixture.selectedForProtocolFilter as VaultNode[]).map((vault) => ({
|
|
36
|
+
...vault,
|
|
37
|
+
chainId: ChainId.Polygon,
|
|
38
|
+
}));
|
|
39
|
+
const protocolEdges = protocolFixtureNodes.map(toEdge);
|
|
40
|
+
|
|
41
|
+
getAllVaultsFromApiSpy.mockResolvedValue({
|
|
42
|
+
success: true,
|
|
43
|
+
status: 200,
|
|
44
|
+
data: protocolEdges.slice(0, 2),
|
|
45
|
+
});
|
|
46
|
+
getAllVaultsFromSubgraphSpy.mockResolvedValue({
|
|
47
|
+
success: true,
|
|
48
|
+
status: 200,
|
|
49
|
+
data: protocolEdges.slice(2),
|
|
50
|
+
});
|
|
127
51
|
|
|
128
52
|
const response = await vaultClient.getVaults({
|
|
129
53
|
chainId: ChainId.Polygon,
|
|
130
54
|
protocol: 'sushi',
|
|
131
55
|
});
|
|
132
56
|
|
|
57
|
+
const expectedSushi = protocolFixtureNodes.filter((vault) =>
|
|
58
|
+
String(vault.beaconName || '').toLowerCase().includes('sushi'),
|
|
59
|
+
);
|
|
60
|
+
|
|
133
61
|
expect(response.success).toBe(true);
|
|
134
62
|
expect(response.status).toBe(200);
|
|
135
|
-
expect(response.data?.edges).toHaveLength(
|
|
136
|
-
expect(response.data?.edges
|
|
137
|
-
expect(
|
|
63
|
+
expect(response.data?.edges).toHaveLength(expectedSushi.length);
|
|
64
|
+
expect(response.data?.edges.every((edge) => edge.node.beaconName.toLowerCase().includes('sushi'))).toBe(true);
|
|
65
|
+
expect(getAllVaultsFromApiSpy).toHaveBeenCalledTimes(1);
|
|
66
|
+
expect(getAllVaultsFromSubgraphSpy).toHaveBeenCalledTimes(1);
|
|
138
67
|
});
|
|
139
68
|
|
|
140
69
|
it('filters all pages in getAllVaults by protocol', async () => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
buildApiVaultEdge('vault-sushi-2', 'Sushi', 'MultiPositionSushiManaged'),
|
|
158
|
-
],
|
|
159
|
-
false,
|
|
160
|
-
'cursor-2',
|
|
161
|
-
4
|
|
162
|
-
)
|
|
163
|
-
);
|
|
70
|
+
const paginationFixtureNodes = (fixture.selectedForPagination as VaultNode[]).slice(0, 120).map((vault) => ({
|
|
71
|
+
...vault,
|
|
72
|
+
chainId: ChainId.Polygon,
|
|
73
|
+
}));
|
|
74
|
+
const paginationEdges = paginationFixtureNodes.map(toEdge);
|
|
75
|
+
|
|
76
|
+
getAllVaultsFromApiSpy.mockResolvedValue({
|
|
77
|
+
success: true,
|
|
78
|
+
status: 200,
|
|
79
|
+
data: paginationEdges,
|
|
80
|
+
});
|
|
81
|
+
getAllVaultsFromSubgraphSpy.mockResolvedValue({
|
|
82
|
+
success: true,
|
|
83
|
+
status: 200,
|
|
84
|
+
data: [],
|
|
85
|
+
});
|
|
164
86
|
|
|
165
87
|
const response = await vaultClient.getAllVaults(
|
|
166
88
|
{
|
|
167
89
|
chainId: ChainId.Polygon,
|
|
168
90
|
protocol: 'Sushi',
|
|
169
91
|
},
|
|
170
|
-
|
|
92
|
+
25
|
|
171
93
|
);
|
|
172
94
|
|
|
95
|
+
const expectedSushiCount = paginationFixtureNodes.filter((vault) =>
|
|
96
|
+
String(vault.beaconName || '').toLowerCase().includes('sushi'),
|
|
97
|
+
).length;
|
|
98
|
+
|
|
173
99
|
expect(response.success).toBe(true);
|
|
174
100
|
expect(response.status).toBe(200);
|
|
175
|
-
expect(response.data).toHaveLength(
|
|
176
|
-
expect(response.data?.
|
|
177
|
-
expect(
|
|
101
|
+
expect(response.data).toHaveLength(expectedSushiCount);
|
|
102
|
+
expect(response.data?.every((vault) => vault.beaconName.toLowerCase().includes('sushi'))).toBe(true);
|
|
103
|
+
expect(getAllVaultsFromApiSpy).toHaveBeenCalled();
|
|
104
|
+
expect(getAllVaultsFromSubgraphSpy).toHaveBeenCalled();
|
|
178
105
|
});
|
|
179
106
|
});
|