@steerprotocol/sdk 1.29.2 → 1.30.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.
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.VaultClient = void 0;
18
18
  const api_sdk_1 = require("@steerprotocol/api-sdk");
19
19
  const const_1 = require("../const");
20
+ const ammConfig_js_1 = require("../const/amm/configs/ammConfig.js");
20
21
  const protocol_1 = require("../const/amm/utils/protocol");
21
22
  const chain_1 = require("../const/chain");
22
23
  const subgraph_1 = require("../const/subgraph");
@@ -162,8 +163,95 @@ class VaultClient extends SubgraphClient_js_1.SubgraphClient {
162
163
  this.subgraphVaultClient = new SubgraphVaultClient_1.SubgraphVaultClient();
163
164
  this.subgraphStudioKey = subgraphStudioKey || '';
164
165
  }
166
+ normalizeProtocolValue(value) {
167
+ return value.toLowerCase().replace(/[^a-z0-9]/g, '');
168
+ }
169
+ resolveProtocolEnum(protocol) {
170
+ if (!protocol) {
171
+ return null;
172
+ }
173
+ const normalizedProtocol = this.normalizeProtocolValue(protocol);
174
+ const matchedProtocol = Object.values(chain_1.Protocol).find(protocolValue => this.normalizeProtocolValue(protocolValue) === normalizedProtocol);
175
+ return matchedProtocol || null;
176
+ }
177
+ getProtocolBeaconNames(protocol) {
178
+ const resolvedProtocol = this.resolveProtocolEnum(protocol);
179
+ if (!resolvedProtocol) {
180
+ return [];
181
+ }
182
+ const protocolConfig = (0, ammConfig_js_1.getAmmConfig)(this.subgraphStudioKey)[resolvedProtocol];
183
+ const beaconNames = [];
184
+ if (protocolConfig?.beaconContract) {
185
+ beaconNames.push(protocolConfig.beaconContract);
186
+ }
187
+ if (protocolConfig?.beaconContractSushiManaged) {
188
+ beaconNames.push(protocolConfig.beaconContractSushiManaged);
189
+ }
190
+ if (resolvedProtocol === chain_1.Protocol.Blackhole) {
191
+ beaconNames.push(chain_1.MultiPositionManagers.MultiPositionBlackholeOld);
192
+ }
193
+ const beaconAlias = (0, const_1.getBeaconNameByProtocol)(resolvedProtocol);
194
+ if (beaconAlias) {
195
+ beaconNames.push(beaconAlias);
196
+ }
197
+ return [...new Set(beaconNames.filter(name => name.length > 0))];
198
+ }
199
+ getPrimaryProtocolBeaconName(protocol) {
200
+ const resolvedProtocol = this.resolveProtocolEnum(protocol);
201
+ if (!resolvedProtocol) {
202
+ return null;
203
+ }
204
+ const protocolConfig = (0, ammConfig_js_1.getAmmConfig)(this.subgraphStudioKey)[resolvedProtocol];
205
+ return protocolConfig?.beaconContract || null;
206
+ }
207
+ buildApiVaultFilter(filter) {
208
+ if (!filter) {
209
+ return undefined;
210
+ }
211
+ const { protocol, ...rest } = filter;
212
+ const apiFilter = { ...rest };
213
+ if (!apiFilter.beaconName && protocol) {
214
+ const primaryBeaconName = this.getPrimaryProtocolBeaconName(protocol);
215
+ if (primaryBeaconName) {
216
+ apiFilter.beaconName = primaryBeaconName;
217
+ }
218
+ }
219
+ return apiFilter;
220
+ }
221
+ vaultMatchesProtocolFilter(vault, protocolFilter, resolvedProtocol) {
222
+ const normalizedFilter = this.normalizeProtocolValue(protocolFilter);
223
+ const normalizedBeaconName = this.normalizeProtocolValue(vault.beaconName);
224
+ const resolvedVaultProtocol = (0, const_1.getProtocolTypeByBeacon)(vault.beaconName);
225
+ const directCandidates = [vault.protocol, vault.protocolBaseType, resolvedVaultProtocol || ''];
226
+ const hasDirectMatch = directCandidates.some(candidate => {
227
+ if (!candidate) {
228
+ return false;
229
+ }
230
+ return this.normalizeProtocolValue(candidate) === normalizedFilter;
231
+ });
232
+ if (hasDirectMatch) {
233
+ return true;
234
+ }
235
+ const expectedBeacon = resolvedProtocol
236
+ ? (0, const_1.getBeaconNameByProtocol)(resolvedProtocol)
237
+ : protocolFilter;
238
+ const normalizedExpectedBeacon = this.normalizeProtocolValue(expectedBeacon);
239
+ return normalizedExpectedBeacon.length > 0 && normalizedBeaconName.includes(normalizedExpectedBeacon);
240
+ }
241
+ applyProtocolFilter(vaultsConnection, protocol) {
242
+ if (!protocol) {
243
+ return vaultsConnection;
244
+ }
245
+ const resolvedProtocol = this.resolveProtocolEnum(protocol);
246
+ const filteredEdges = vaultsConnection.edges.filter(edge => this.vaultMatchesProtocolFilter(edge.node, protocol, resolvedProtocol));
247
+ return {
248
+ ...vaultsConnection,
249
+ edges: filteredEdges
250
+ };
251
+ }
165
252
  /**
166
253
  * Gets vaults with pagination support
254
+ * Fetches ALL data from both API (database) and subgraph in parallel, merges without duplicates, then paginates
167
255
  * @param filter - Optional filter criteria
168
256
  * @param first - Number of items to fetch (default: 50)
169
257
  * @param after - Cursor for pagination (null for first page)
@@ -198,90 +286,359 @@ class VaultClient extends SubgraphClient_js_1.SubgraphClient {
198
286
  * ```
199
287
  */
200
288
  async getVaults(filter, first = 50, after) {
201
- if (filter?.chainId !== chain_1.ChainId.Avalanche) {
202
- try {
203
- // First try the API client
204
- const response = await this.apiClient.vaults({
205
- filter,
206
- first,
207
- after
208
- });
209
- if (response.data?.vaults) {
210
- // Transform the response to match our interface
211
- const transformedData = {
212
- edges: response.data.vaults.edges.map(edge => ({
213
- cursor: edge.cursor,
214
- node: {
215
- id: edge.node.id,
216
- chainId: edge.node.chainId,
217
- vaultAddress: edge.node.vaultAddress,
218
- protocol: edge.node.protocol,
219
- beaconName: edge.node.beaconName,
220
- protocolBaseType: edge.node.protocolBaseType,
221
- name: edge.node.name || '',
222
- feeApr: edge.node.feeApr || undefined,
223
- stakingApr: edge.node.stakingApr || undefined,
224
- merklApr: edge.node.merklApr || undefined,
225
- pool: {
226
- id: edge.node.pool?.id || '',
227
- poolAddress: edge.node.pool?.poolAddress || '',
228
- feeTier: edge.node.pool?.feeTier || '',
229
- tick: undefined, // Not available in API response
230
- liquidity: undefined, // Not available in API response
231
- volumeUSD: undefined, // Not available in API response
232
- totalValueLockedUSD: undefined // Not available in API response
233
- },
234
- token0: {
235
- id: edge.node.token0?.id || '',
236
- symbol: edge.node.token0?.symbol || '',
237
- name: edge.node.token0?.name || '',
238
- decimals: edge.node.token0?.decimals || 0,
239
- address: edge.node.token0?.address || '',
240
- chainId: edge.node.token0?.chainId || 0
241
- },
242
- token1: {
243
- id: edge.node.token1?.id || '',
244
- symbol: edge.node.token1?.symbol || '',
245
- name: edge.node.token1?.name || '',
246
- decimals: edge.node.token1?.decimals || 0,
247
- address: edge.node.token1?.address || '',
248
- chainId: edge.node.token1?.chainId || 0
249
- }
250
- }
251
- })),
252
- pageInfo: {
253
- hasNextPage: response.data.vaults.pageInfo.hasNextPage,
254
- endCursor: response.data.vaults.pageInfo.endCursor ?? null
255
- },
256
- totalCount: response.data.vaults.totalCount
257
- };
289
+ const apiFilter = this.buildApiVaultFilter(filter);
290
+ // Fetch ALL vaults from both sources in parallel (no pagination at source level)
291
+ const [apiResult, subgraphResult] = await Promise.allSettled([
292
+ this.getAllVaultsFromApi(apiFilter),
293
+ filter?.chainId !== chain_1.ChainId.Avalanche ? this.getAllVaultsFromSubgraph(filter) : Promise.reject(new Error('Avalanche not supported'))
294
+ ]);
295
+ // Extract successful results
296
+ const apiVaults = apiResult.status === 'fulfilled' && apiResult.value.success && apiResult.value.data
297
+ ? apiResult.value.data
298
+ : [];
299
+ const subgraphVaults = subgraphResult.status === 'fulfilled' && subgraphResult.value.success && subgraphResult.value.data
300
+ ? subgraphResult.value.data
301
+ : [];
302
+ // If both failed, return error
303
+ if (apiVaults.length === 0 && subgraphVaults.length === 0) {
304
+ const apiError = apiResult.status === 'rejected' ? apiResult.reason : null;
305
+ const subgraphError = subgraphResult.status === 'rejected' ? subgraphResult.reason : null;
306
+ return {
307
+ data: null,
308
+ status: 500,
309
+ success: false,
310
+ error: `Both API and subgraph failed. API: ${apiError?.message || 'Unknown error'}. Subgraph: ${subgraphError?.message || 'Unknown error'}`
311
+ };
312
+ }
313
+ // Merge results and remove duplicates based on vaultAddress
314
+ const mergedVaults = this.mergeVaultResults(apiVaults, subgraphVaults);
315
+ // Apply protocol filter to merged results
316
+ const filteredVaults = mergedVaults.filter(edge => !filter?.protocol || this.vaultMatchesProtocolFilter(edge.node, filter.protocol, this.resolveProtocolEnum(filter.protocol)));
317
+ // Apply pagination to the complete merged and filtered dataset
318
+ const paginatedVaults = this.paginateVaults(filteredVaults, first, after);
319
+ return {
320
+ data: paginatedVaults,
321
+ status: 200,
322
+ success: true
323
+ };
324
+ }
325
+ /**
326
+ * Fetches ALL vaults from API (database) by auto-paginating
327
+ * @private
328
+ */
329
+ async getAllVaultsFromApi(apiFilter) {
330
+ try {
331
+ const allVaults = [];
332
+ let hasNextPage = true;
333
+ let cursor = null;
334
+ const batchSize = 100; // Fetch in batches of 100
335
+ while (hasNextPage) {
336
+ const response = await this.getVaultsFromApi(apiFilter, batchSize, cursor);
337
+ if (!response.success || !response.data) {
338
+ // If we already have some vaults, return them; otherwise return error
339
+ if (allVaults.length > 0) {
340
+ break;
341
+ }
258
342
  return {
259
- data: transformedData,
343
+ data: null,
260
344
  status: response.status,
261
- success: true
345
+ success: false,
346
+ error: response.error || 'Failed to fetch vaults from API'
262
347
  };
263
348
  }
349
+ allVaults.push(...response.data.edges);
350
+ hasNextPage = response.data.pageInfo.hasNextPage;
351
+ cursor = response.data.pageInfo.endCursor;
352
+ }
353
+ return {
354
+ data: allVaults,
355
+ status: 200,
356
+ success: true
357
+ };
358
+ }
359
+ catch (error) {
360
+ console.warn('Failed to fetch all vaults from API:', error);
361
+ return {
362
+ data: null,
363
+ status: 500,
364
+ success: false,
365
+ error: error instanceof Error ? error.message : 'Failed to fetch all vaults from API'
366
+ };
367
+ }
368
+ }
369
+ /**
370
+ * Fetches vaults from API (database) with pagination
371
+ * @private
372
+ */
373
+ async getVaultsFromApi(apiFilter, first = 50, after) {
374
+ try {
375
+ const response = await this.apiClient.vaults({
376
+ filter: apiFilter,
377
+ first,
378
+ after
379
+ });
380
+ if (!response.data?.vaults) {
381
+ return {
382
+ data: null,
383
+ status: response.status,
384
+ success: false,
385
+ error: 'No data returned from API'
386
+ };
387
+ }
388
+ // Transform the response to match our interface
389
+ const transformedData = {
390
+ edges: response.data.vaults.edges.map(edge => ({
391
+ cursor: edge.cursor,
392
+ node: {
393
+ id: edge.node.id,
394
+ chainId: edge.node.chainId,
395
+ vaultAddress: edge.node.vaultAddress,
396
+ protocol: edge.node.protocol,
397
+ beaconName: edge.node.beaconName,
398
+ protocolBaseType: edge.node.protocolBaseType,
399
+ name: edge.node.name || '',
400
+ feeApr: edge.node.feeApr || undefined,
401
+ stakingApr: edge.node.stakingApr || undefined,
402
+ merklApr: edge.node.merklApr || undefined,
403
+ pool: {
404
+ id: edge.node.pool?.id || '',
405
+ poolAddress: edge.node.pool?.poolAddress || '',
406
+ feeTier: edge.node.pool?.feeTier || '',
407
+ tick: undefined, // Not available in API response
408
+ liquidity: undefined, // Not available in API response
409
+ volumeUSD: undefined, // Not available in API response
410
+ totalValueLockedUSD: undefined // Not available in API response
411
+ },
412
+ token0: {
413
+ id: edge.node.token0?.id || '',
414
+ symbol: edge.node.token0?.symbol || '',
415
+ name: edge.node.token0?.name || '',
416
+ decimals: edge.node.token0?.decimals || 0,
417
+ address: edge.node.token0?.address || '',
418
+ chainId: edge.node.token0?.chainId || 0
419
+ },
420
+ token1: {
421
+ id: edge.node.token1?.id || '',
422
+ symbol: edge.node.token1?.symbol || '',
423
+ name: edge.node.token1?.name || '',
424
+ decimals: edge.node.token1?.decimals || 0,
425
+ address: edge.node.token1?.address || '',
426
+ chainId: edge.node.token1?.chainId || 0
427
+ }
428
+ }
429
+ })),
430
+ pageInfo: {
431
+ hasNextPage: response.data.vaults.pageInfo.hasNextPage,
432
+ endCursor: response.data.vaults.pageInfo.endCursor ?? null
433
+ },
434
+ totalCount: response.data.vaults.totalCount
435
+ };
436
+ return {
437
+ data: transformedData,
438
+ status: response.status,
439
+ success: true
440
+ };
441
+ }
442
+ catch (error) {
443
+ console.warn('API client failed:', error);
444
+ return {
445
+ data: null,
446
+ status: 500,
447
+ success: false,
448
+ error: error instanceof Error ? error.message : 'API request failed'
449
+ };
450
+ }
451
+ }
452
+ /**
453
+ * Merges vault results from API and subgraph, removing duplicates
454
+ * Prioritizes API data when duplicates are found
455
+ * Generates consistent cursors for the merged dataset
456
+ * @private
457
+ */
458
+ mergeVaultResults(apiVaults, subgraphVaults) {
459
+ const vaultMap = new Map();
460
+ // Add API vaults first (they take priority)
461
+ apiVaults.forEach(edge => {
462
+ const key = edge.node.vaultAddress.toLowerCase();
463
+ vaultMap.set(key, edge);
464
+ });
465
+ // Add subgraph vaults only if not already present
466
+ subgraphVaults.forEach(edge => {
467
+ const key = edge.node.vaultAddress.toLowerCase();
468
+ if (!vaultMap.has(key)) {
469
+ vaultMap.set(key, edge);
470
+ }
471
+ else {
472
+ // Merge additional data from subgraph if available (like pool details)
473
+ const existing = vaultMap.get(key);
474
+ const merged = {
475
+ ...existing,
476
+ node: {
477
+ ...existing.node,
478
+ // Merge pool data - prefer subgraph data for pool details if API doesn't have it
479
+ pool: {
480
+ id: existing.node.pool.id || edge.node.pool.id,
481
+ poolAddress: existing.node.pool.poolAddress || edge.node.pool.poolAddress,
482
+ feeTier: existing.node.pool.feeTier || edge.node.pool.feeTier,
483
+ tick: existing.node.pool.tick || edge.node.pool.tick,
484
+ liquidity: existing.node.pool.liquidity || edge.node.pool.liquidity,
485
+ volumeUSD: existing.node.pool.volumeUSD || edge.node.pool.volumeUSD,
486
+ totalValueLockedUSD: existing.node.pool.totalValueLockedUSD || edge.node.pool.totalValueLockedUSD
487
+ },
488
+ // Prefer API APR data, but use subgraph if API doesn't have it
489
+ feeApr: existing.node.feeApr ?? edge.node.feeApr,
490
+ stakingApr: existing.node.stakingApr ?? edge.node.stakingApr,
491
+ merklApr: existing.node.merklApr ?? edge.node.merklApr
492
+ }
493
+ };
494
+ vaultMap.set(key, merged);
264
495
  }
265
- catch (apiError) {
266
- console.warn('API client failed, falling back to subgraph:', apiError);
496
+ });
497
+ // Convert to array and regenerate cursors for consistent pagination
498
+ const mergedArray = Array.from(vaultMap.values());
499
+ return mergedArray.map((edge, index) => ({
500
+ ...edge,
501
+ cursor: `merged_${edge.node.chainId}_${index}_${edge.node.vaultAddress.toLowerCase()}`
502
+ }));
503
+ }
504
+ /**
505
+ * Applies pagination to vault results
506
+ * @private
507
+ */
508
+ paginateVaults(vaults, first, after) {
509
+ let startIndex = 0;
510
+ // If cursor is provided, find the starting position
511
+ if (after) {
512
+ const cursorIndex = vaults.findIndex(edge => edge.cursor === after);
513
+ if (cursorIndex !== -1) {
514
+ startIndex = cursorIndex + 1;
267
515
  }
268
516
  }
269
- // Fallback to subgraph if API fails or returns no data
517
+ // Get the slice of vaults for this page
518
+ const paginatedEdges = vaults.slice(startIndex, startIndex + first);
519
+ const hasNextPage = startIndex + first < vaults.length;
520
+ const endCursor = paginatedEdges.length > 0 ? paginatedEdges[paginatedEdges.length - 1].cursor : null;
521
+ return {
522
+ edges: paginatedEdges,
523
+ pageInfo: {
524
+ hasNextPage,
525
+ endCursor
526
+ },
527
+ totalCount: vaults.length
528
+ };
529
+ }
530
+ /**
531
+ * Fetches ALL vaults from subgraph (no pagination)
532
+ * @param filter - Optional filter criteria
533
+ * @returns Promise resolving to all vaults data from subgraph
534
+ * @private
535
+ */
536
+ async getAllVaultsFromSubgraph(filter) {
270
537
  try {
271
- return await this.getVaultsFromSubgraph(filter, first, after);
538
+ // Extract chainId from filter
539
+ const chainId = filter?.chainId;
540
+ if (!chainId) {
541
+ throw new Error('ChainId is required for subgraph');
542
+ }
543
+ // Get chain enum from chainId
544
+ const chain = (0, const_1.chainIdToName)(chainId);
545
+ if (!chain) {
546
+ throw new Error(`Unsupported chainId: ${chainId}`);
547
+ }
548
+ // Get subgraph URL for this chain
549
+ const subgraphUrl = subgraph_1.steerSubgraphConfig[chain];
550
+ if (!subgraphUrl) {
551
+ throw new Error(`No subgraph configured for chain: ${chain}`);
552
+ }
553
+ const beaconNames = this.getProtocolBeaconNames(filter?.protocol);
554
+ if (filter?.beaconName) {
555
+ beaconNames.push(filter.beaconName);
556
+ }
557
+ const uniqueBeaconNames = [...new Set(beaconNames.filter(name => name.length > 0))];
558
+ // Fetch all vaults from subgraph
559
+ const subgraphVaults = await this.subgraphVaultClient.getAllVaultsFromSubgraph({
560
+ subgraphUrl,
561
+ chainId,
562
+ showDeprecated: false,
563
+ showCurrentProtocol: uniqueBeaconNames.length > 0,
564
+ beaconNames: uniqueBeaconNames
565
+ });
566
+ // Get all supported protocols for this chain
567
+ const supportedProtocols = (0, protocol_1.getProtocolsForChainId)(chainId, this.subgraphStudioKey);
568
+ // Fetch APR data for all protocols in parallel
569
+ const aprPromises = supportedProtocols.map(protocol => this.getAprs({ chainId, protocol }).catch(error => {
570
+ console.warn(`Failed to fetch APR for protocol ${protocol}:`, error);
571
+ return { success: false, data: null };
572
+ }));
573
+ const aprResults = await Promise.all(aprPromises);
574
+ // Create a map of vault address to APR for quick lookup
575
+ const aprMap = new Map();
576
+ aprResults && aprResults.forEach(aprResult => {
577
+ if (aprResult.success && aprResult.data) {
578
+ aprResult?.data?.vaults && aprResult.data.vaults.forEach(vaultApr => {
579
+ aprMap.set(vaultApr.vaultAddress.toLowerCase(), vaultApr.apr.apr);
580
+ });
581
+ }
582
+ });
583
+ // Transform to VaultEdge array with APR data
584
+ const vaultEdges = subgraphVaults.map((vault, index) => ({
585
+ cursor: `subgraph_${chainId}_${index}`,
586
+ node: {
587
+ id: vault.id,
588
+ chainId: chainId,
589
+ vaultAddress: vault.id,
590
+ protocol: vault.beaconName || '',
591
+ beaconName: vault.beaconName || '',
592
+ protocolBaseType: vault.beaconName || '',
593
+ name: `${vault.token0Symbol}/${vault.token1Symbol}`,
594
+ feeApr: aprMap.get(vault.id.toLowerCase()),
595
+ stakingApr: undefined,
596
+ merklApr: undefined,
597
+ pool: {
598
+ id: vault.pool || '',
599
+ poolAddress: vault.pool || '',
600
+ feeTier: vault.feeTier || '',
601
+ tick: undefined,
602
+ liquidity: undefined,
603
+ volumeUSD: undefined,
604
+ totalValueLockedUSD: undefined
605
+ },
606
+ token0: {
607
+ id: vault.token0,
608
+ symbol: vault.token0Symbol,
609
+ name: vault.token0Symbol, // Use symbol as name since subgraph doesn't provide name
610
+ decimals: parseInt(vault.token0Decimals) || 18,
611
+ address: vault.token0,
612
+ chainId: chainId
613
+ },
614
+ token1: {
615
+ id: vault.token1,
616
+ symbol: vault.token1Symbol,
617
+ name: vault.token1Symbol, // Use symbol as name since subgraph doesn't provide name
618
+ decimals: parseInt(vault.token1Decimals) || 18,
619
+ address: vault.token1,
620
+ chainId: chainId
621
+ }
622
+ }
623
+ }));
624
+ return {
625
+ data: vaultEdges,
626
+ status: 200,
627
+ success: true
628
+ };
272
629
  }
273
- catch (subgraphError) {
274
- console.error('Both API and subgraph failed:', subgraphError);
630
+ catch (error) {
631
+ console.error('Subgraph vault fetch failed:', error);
275
632
  return {
276
633
  data: null,
277
634
  status: 500,
278
635
  success: false,
279
- error: subgraphError instanceof Error ? subgraphError.message : 'Both API and subgraph requests failed'
636
+ error: error instanceof Error ? error.message : 'Failed to fetch vaults from subgraph'
280
637
  };
281
638
  }
282
639
  }
283
640
  /**
284
- * Fallback method to fetch vaults from subgraph
641
+ * Fallback method to fetch vaults from subgraph with pagination
285
642
  * @param filter - Optional filter criteria
286
643
  * @param first - Number of items to fetch (default: 50)
287
644
  * @param after - Cursor for pagination (null for first page)
@@ -305,24 +662,18 @@ class VaultClient extends SubgraphClient_js_1.SubgraphClient {
305
662
  if (!subgraphUrl) {
306
663
  throw new Error(`No subgraph configured for chain: ${chain}`);
307
664
  }
308
- const beaconNames = [];
309
- if (filter?.protocol) {
310
- const beacon = (0, const_1.getBeaconNameByProtocol)(filter.protocol);
311
- beaconNames.push(beacon);
312
- if (filter?.protocol === chain_1.Protocol.Blackhole) {
313
- beaconNames.push(chain_1.MultiPositionManagers.MultiPositionBlackholeOld);
314
- }
315
- }
665
+ const beaconNames = this.getProtocolBeaconNames(filter?.protocol);
316
666
  if (filter?.beaconName) {
317
667
  beaconNames.push(filter.beaconName);
318
668
  }
669
+ const uniqueBeaconNames = [...new Set(beaconNames.filter(name => name.length > 0))];
319
670
  // Fetch all vaults from subgraph
320
671
  const subgraphVaults = await this.subgraphVaultClient.getAllVaultsFromSubgraph({
321
672
  subgraphUrl,
322
673
  chainId,
323
674
  showDeprecated: false,
324
- showCurrentProtocol: false,
325
- beaconNames: beaconNames
675
+ showCurrentProtocol: uniqueBeaconNames.length > 0,
676
+ beaconNames: uniqueBeaconNames
326
677
  });
327
678
  // Get all supported protocols for this chain
328
679
  const supportedProtocols = (0, protocol_1.getProtocolsForChainId)(chainId, this.subgraphStudioKey);
@@ -353,8 +704,9 @@ class VaultClient extends SubgraphClient_js_1.SubgraphClient {
353
704
  }
354
705
  }));
355
706
  }
707
+ const filteredVaultsConnection = this.applyProtocolFilter(vaultsConnection, filter?.protocol);
356
708
  return {
357
- data: vaultsConnection,
709
+ data: filteredVaultsConnection,
358
710
  status: 200,
359
711
  success: true
360
712
  };