@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.
- 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
package/src/base/PoolClient.ts
CHANGED
|
@@ -67,10 +67,18 @@ export interface PoolFilter {
|
|
|
67
67
|
chainId?: number;
|
|
68
68
|
/** Protocol to filter pools by */
|
|
69
69
|
protocol?: Protocol;
|
|
70
|
+
/** Exact pool address/id to look up */
|
|
71
|
+
poolAddress?: string;
|
|
70
72
|
/** Minimum volume in USD to filter pools */
|
|
71
73
|
minVolumeUSD?: number;
|
|
72
74
|
/** Token address to find pools containing this token */
|
|
73
75
|
tokenAddress?: string;
|
|
76
|
+
/** Multiple token addresses to find pools for */
|
|
77
|
+
tokenAddresses?: string[];
|
|
78
|
+
/** Token symbol to find pools containing this token */
|
|
79
|
+
tokenSymbol?: string;
|
|
80
|
+
/** Multiple token symbols to find pools for */
|
|
81
|
+
tokenSymbols?: string[];
|
|
74
82
|
/** Maximum number of pools to return */
|
|
75
83
|
limit?: number;
|
|
76
84
|
}
|
|
@@ -207,6 +215,93 @@ export class PoolClient extends SubgraphClient {
|
|
|
207
215
|
};
|
|
208
216
|
}
|
|
209
217
|
|
|
218
|
+
private normalizeAddress(value?: string): string {
|
|
219
|
+
return value?.toLowerCase() || '';
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private normalizeSymbol(value?: string): string {
|
|
223
|
+
return value?.trim().toLowerCase() || '';
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private dedupePools(pools: GraphQLPoolData[]): GraphQLPoolData[] {
|
|
227
|
+
const seen = new Set<string>();
|
|
228
|
+
const deduped: GraphQLPoolData[] = [];
|
|
229
|
+
|
|
230
|
+
pools.forEach((pool) => {
|
|
231
|
+
const key = this.normalizeAddress(pool.id);
|
|
232
|
+
if (!key || seen.has(key)) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
seen.add(key);
|
|
237
|
+
deduped.push(pool);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
return deduped;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private filterPoolsBySymbols(
|
|
244
|
+
pools: GraphQLPoolData[],
|
|
245
|
+
symbols: string[],
|
|
246
|
+
): GraphQLPoolData[] {
|
|
247
|
+
if (symbols.length === 0) {
|
|
248
|
+
return pools;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const normalizedSymbols = new Set(
|
|
252
|
+
symbols.map((symbol) => this.normalizeSymbol(symbol)).filter(Boolean),
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
return pools.filter((pool) => {
|
|
256
|
+
const token0Symbol = this.normalizeSymbol(pool.token0?.symbol);
|
|
257
|
+
const token1Symbol = this.normalizeSymbol(pool.token1?.symbol);
|
|
258
|
+
|
|
259
|
+
return normalizedSymbols.has(token0Symbol) || normalizedSymbols.has(token1Symbol);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private applyPoolSearchResultFilters(
|
|
264
|
+
pools: GraphQLPoolData[],
|
|
265
|
+
filter: PoolFilter,
|
|
266
|
+
): GraphQLPoolData[] {
|
|
267
|
+
let filteredPools = this.dedupePools(pools);
|
|
268
|
+
|
|
269
|
+
if (typeof filter.minVolumeUSD === 'number') {
|
|
270
|
+
filteredPools = filteredPools.filter((pool) => {
|
|
271
|
+
const volumeUSD = parseFloat(pool.volumeUSD || pool.volumeUsd || '0');
|
|
272
|
+
return !Number.isNaN(volumeUSD) && volumeUSD >= filter.minVolumeUSD!;
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (typeof filter.limit === 'number' && filter.limit >= 0) {
|
|
277
|
+
filteredPools = filteredPools.slice(0, filter.limit);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return filteredPools;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private async searchPoolsBySymbols(
|
|
284
|
+
filter: Required<Pick<PoolFilter, 'chainId' | 'protocol'>> & PoolFilter,
|
|
285
|
+
symbols: string[],
|
|
286
|
+
): Promise<SteerResponse<GraphQLPoolData[]>> {
|
|
287
|
+
// Symbol relation filtering is not portable across all supported AMM subgraphs.
|
|
288
|
+
// Use bounded top-pools fetch plus local symbol filtering as the baseline path.
|
|
289
|
+
const boundedLimit = Math.min(Math.max(filter.limit ?? 200, 1), 500);
|
|
290
|
+
const topPools = await this.getTopPools(boundedLimit, filter.protocol, filter.chainId);
|
|
291
|
+
|
|
292
|
+
if (!topPools.success || !topPools.data) {
|
|
293
|
+
return topPools;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const symbolMatches = this.filterPoolsBySymbols(topPools.data, symbols);
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
data: this.applyPoolSearchResultFilters(symbolMatches, filter),
|
|
300
|
+
status: 200,
|
|
301
|
+
success: true,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
210
305
|
/**
|
|
211
306
|
* Fetches data from GraphQL endpoint with retry logic for rate limits
|
|
212
307
|
*
|
|
@@ -675,4 +770,108 @@ export class PoolClient extends SubgraphClient {
|
|
|
675
770
|
return true;
|
|
676
771
|
});
|
|
677
772
|
}
|
|
678
|
-
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Searches pools using exact-address lookups where supported and local symbol
|
|
776
|
+
* filtering as a portable fallback.
|
|
777
|
+
*
|
|
778
|
+
* Symbol-based matching is best-effort because not every downstream AMM
|
|
779
|
+
* subgraph exposes portable nested token-symbol filters.
|
|
780
|
+
*/
|
|
781
|
+
public async searchPools(
|
|
782
|
+
filter: PoolFilter,
|
|
783
|
+
): Promise<SteerResponse<GraphQLPoolData[]>> {
|
|
784
|
+
const { chainId, protocol } = filter;
|
|
785
|
+
|
|
786
|
+
if (!chainId || !protocol) {
|
|
787
|
+
return {
|
|
788
|
+
data: null,
|
|
789
|
+
status: 400,
|
|
790
|
+
success: false,
|
|
791
|
+
error: 'searchPools requires both chainId and protocol',
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const normalizedPoolAddress = this.normalizeAddress(filter.poolAddress);
|
|
796
|
+
const normalizedTokenAddress = this.normalizeAddress(filter.tokenAddress);
|
|
797
|
+
const normalizedTokenAddresses = (filter.tokenAddresses || [])
|
|
798
|
+
.map((address) => this.normalizeAddress(address))
|
|
799
|
+
.filter(Boolean);
|
|
800
|
+
const tokenSymbols = [
|
|
801
|
+
...(filter.tokenSymbol ? [filter.tokenSymbol] : []),
|
|
802
|
+
...(filter.tokenSymbols || []),
|
|
803
|
+
].filter(Boolean);
|
|
804
|
+
|
|
805
|
+
if (
|
|
806
|
+
!normalizedPoolAddress &&
|
|
807
|
+
!normalizedTokenAddress &&
|
|
808
|
+
normalizedTokenAddresses.length === 0 &&
|
|
809
|
+
tokenSymbols.length === 0
|
|
810
|
+
) {
|
|
811
|
+
return {
|
|
812
|
+
data: null,
|
|
813
|
+
status: 400,
|
|
814
|
+
success: false,
|
|
815
|
+
error: 'searchPools requires at least one of poolAddress, tokenAddress, tokenAddresses, tokenSymbol, or tokenSymbols',
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
const collectedPools: GraphQLPoolData[] = [];
|
|
820
|
+
|
|
821
|
+
if (normalizedPoolAddress) {
|
|
822
|
+
const exactPool = await this.getPoolById(normalizedPoolAddress, protocol, chainId);
|
|
823
|
+
if (!exactPool.success) {
|
|
824
|
+
return {
|
|
825
|
+
data: null,
|
|
826
|
+
status: exactPool.status,
|
|
827
|
+
success: false,
|
|
828
|
+
error: exactPool.error,
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
if (exactPool.data) {
|
|
833
|
+
collectedPools.push(exactPool.data);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
if (normalizedTokenAddress) {
|
|
838
|
+
const tokenPools = await this.fetchPoolsForToken(normalizedTokenAddress, protocol, chainId);
|
|
839
|
+
if (!tokenPools.success) {
|
|
840
|
+
return tokenPools;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
collectedPools.push(...(tokenPools.data || []));
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
if (normalizedTokenAddresses.length > 0) {
|
|
847
|
+
const batchPools = await this.fetchPoolsForTokensBatch(
|
|
848
|
+
normalizedTokenAddresses,
|
|
849
|
+
protocol,
|
|
850
|
+
chainId,
|
|
851
|
+
);
|
|
852
|
+
if (!batchPools.success) {
|
|
853
|
+
return batchPools;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
collectedPools.push(...(batchPools.data || []));
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if (tokenSymbols.length > 0) {
|
|
860
|
+
const symbolPools = await this.searchPoolsBySymbols(
|
|
861
|
+
{ ...filter, chainId, protocol },
|
|
862
|
+
tokenSymbols,
|
|
863
|
+
);
|
|
864
|
+
if (!symbolPools.success) {
|
|
865
|
+
return symbolPools;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
collectedPools.push(...(symbolPools.data || []));
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
return {
|
|
872
|
+
data: this.applyPoolSearchResultFilters(collectedPools, filter),
|
|
873
|
+
status: 200,
|
|
874
|
+
success: true,
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
}
|
package/src/base/VaultClient.ts
CHANGED
|
@@ -218,6 +218,12 @@ export interface VaultFilter {
|
|
|
218
218
|
protocol?: string;
|
|
219
219
|
isActive?: boolean;
|
|
220
220
|
beaconName?: string;
|
|
221
|
+
poolAddress?: string;
|
|
222
|
+
vaultAddress?: string;
|
|
223
|
+
tokenAddress?: string;
|
|
224
|
+
tokenAddresses?: string[];
|
|
225
|
+
tokenSymbol?: string;
|
|
226
|
+
tokenSymbols?: string[];
|
|
221
227
|
}
|
|
222
228
|
|
|
223
229
|
// API-specific filter that excludes protocol field
|
|
@@ -225,6 +231,7 @@ export interface ApiVaultFilter {
|
|
|
225
231
|
chainId?: number;
|
|
226
232
|
isActive?: boolean;
|
|
227
233
|
beaconName?: string;
|
|
234
|
+
pool?: string;
|
|
228
235
|
}
|
|
229
236
|
|
|
230
237
|
export interface TokenFilter {
|
|
@@ -464,8 +471,16 @@ export class VaultClient extends SubgraphClient {
|
|
|
464
471
|
return undefined;
|
|
465
472
|
}
|
|
466
473
|
|
|
467
|
-
const { protocol,
|
|
468
|
-
const apiFilter: ApiVaultFilter = {
|
|
474
|
+
const { protocol, poolAddress, chainId, isActive, beaconName } = filter;
|
|
475
|
+
const apiFilter: ApiVaultFilter = {
|
|
476
|
+
chainId,
|
|
477
|
+
isActive,
|
|
478
|
+
beaconName,
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
if (poolAddress) {
|
|
482
|
+
apiFilter.pool = poolAddress;
|
|
483
|
+
}
|
|
469
484
|
|
|
470
485
|
if (!apiFilter.beaconName && protocol) {
|
|
471
486
|
const primaryBeaconName = this.getPrimaryProtocolBeaconName(protocol);
|
|
@@ -522,6 +537,88 @@ export class VaultClient extends SubgraphClient {
|
|
|
522
537
|
};
|
|
523
538
|
}
|
|
524
539
|
|
|
540
|
+
private normalizeAddress(value?: string): string {
|
|
541
|
+
return value?.toLowerCase() || '';
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
private normalizeSymbol(value?: string): string {
|
|
545
|
+
return value?.trim().toLowerCase() || '';
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
private matchesAnyAddress(candidates: Array<string | undefined>, filterValues: string[]): boolean {
|
|
549
|
+
if (filterValues.length === 0) {
|
|
550
|
+
return true;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
const normalizedCandidates = new Set(
|
|
554
|
+
candidates.map((candidate) => this.normalizeAddress(candidate)).filter(Boolean),
|
|
555
|
+
);
|
|
556
|
+
|
|
557
|
+
return filterValues.some((value) => normalizedCandidates.has(value));
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
private matchesAnySymbol(candidates: Array<string | undefined>, filterValues: string[]): boolean {
|
|
561
|
+
if (filterValues.length === 0) {
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const normalizedCandidates = new Set(
|
|
566
|
+
candidates.map((candidate) => this.normalizeSymbol(candidate)).filter(Boolean),
|
|
567
|
+
);
|
|
568
|
+
|
|
569
|
+
return filterValues.some((value) => normalizedCandidates.has(value));
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
private filterVaultNodes(vaults: VaultNode[], filter: VaultFilter): VaultNode[] {
|
|
573
|
+
const vaultAddress = this.normalizeAddress(filter.vaultAddress);
|
|
574
|
+
const poolAddress = this.normalizeAddress(filter.poolAddress);
|
|
575
|
+
const tokenAddressFilters = [
|
|
576
|
+
...(filter.tokenAddress ? [filter.tokenAddress] : []),
|
|
577
|
+
...(filter.tokenAddresses || []),
|
|
578
|
+
]
|
|
579
|
+
.map((address) => this.normalizeAddress(address))
|
|
580
|
+
.filter(Boolean);
|
|
581
|
+
const tokenSymbolFilters = [
|
|
582
|
+
...(filter.tokenSymbol ? [filter.tokenSymbol] : []),
|
|
583
|
+
...(filter.tokenSymbols || []),
|
|
584
|
+
]
|
|
585
|
+
.map((symbol) => this.normalizeSymbol(symbol))
|
|
586
|
+
.filter(Boolean);
|
|
587
|
+
|
|
588
|
+
return vaults.filter((vault) => {
|
|
589
|
+
if (vaultAddress && this.normalizeAddress(vault.vaultAddress) !== vaultAddress) {
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (
|
|
594
|
+
poolAddress &&
|
|
595
|
+
!this.matchesAnyAddress([vault.pool.poolAddress, vault.pool.id], [poolAddress])
|
|
596
|
+
) {
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (
|
|
601
|
+
!this.matchesAnyAddress(
|
|
602
|
+
[vault.token0.address, vault.token0.id, vault.token1.address, vault.token1.id],
|
|
603
|
+
tokenAddressFilters,
|
|
604
|
+
)
|
|
605
|
+
) {
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (
|
|
610
|
+
!this.matchesAnySymbol(
|
|
611
|
+
[vault.token0.symbol, vault.token1.symbol],
|
|
612
|
+
tokenSymbolFilters,
|
|
613
|
+
)
|
|
614
|
+
) {
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
return true;
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
|
|
525
622
|
/**
|
|
526
623
|
* Gets vaults with pagination support
|
|
527
624
|
* Fetches ALL data from both API (database) and subgraph in parallel, merges without duplicates, then paginates
|
|
@@ -1414,6 +1511,76 @@ export class VaultClient extends SubgraphClient {
|
|
|
1414
1511
|
}
|
|
1415
1512
|
}
|
|
1416
1513
|
|
|
1514
|
+
/**
|
|
1515
|
+
* Searches vaults by combining verified API-supported filters with local
|
|
1516
|
+
* filtering over the merged vault result set for unsupported server-side fields.
|
|
1517
|
+
*/
|
|
1518
|
+
public async searchVaults(
|
|
1519
|
+
filter?: VaultFilter,
|
|
1520
|
+
): Promise<SteerResponse<VaultNode[]>> {
|
|
1521
|
+
const response = await this.getAllVaults(filter);
|
|
1522
|
+
|
|
1523
|
+
if (!response.success || !response.data) {
|
|
1524
|
+
return response;
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
return {
|
|
1528
|
+
data: this.filterVaultNodes(response.data, filter || {}),
|
|
1529
|
+
status: 200,
|
|
1530
|
+
success: true,
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
public async getVaultByAddress(
|
|
1535
|
+
vaultAddress: string,
|
|
1536
|
+
filter?: VaultFilter,
|
|
1537
|
+
): Promise<SteerResponse<VaultNode | null>> {
|
|
1538
|
+
const response = await this.searchVaults({
|
|
1539
|
+
...filter,
|
|
1540
|
+
vaultAddress,
|
|
1541
|
+
});
|
|
1542
|
+
|
|
1543
|
+
if (!response.success || !response.data) {
|
|
1544
|
+
return {
|
|
1545
|
+
data: null,
|
|
1546
|
+
status: response.status,
|
|
1547
|
+
success: response.success,
|
|
1548
|
+
error: response.error,
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
return {
|
|
1553
|
+
data: response.data[0] || null,
|
|
1554
|
+
status: 200,
|
|
1555
|
+
success: true,
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
public async getVaultsForPool(
|
|
1560
|
+
poolAddress: string,
|
|
1561
|
+
filter?: VaultFilter,
|
|
1562
|
+
): Promise<SteerResponse<VaultNode[]>> {
|
|
1563
|
+
return this.searchVaults({
|
|
1564
|
+
...filter,
|
|
1565
|
+
poolAddress,
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
public async getVaultsForToken(
|
|
1570
|
+
tokenAddressOrSymbol: string,
|
|
1571
|
+
filter?: VaultFilter,
|
|
1572
|
+
): Promise<SteerResponse<VaultNode[]>> {
|
|
1573
|
+
const normalizedValue = tokenAddressOrSymbol.trim();
|
|
1574
|
+
const isAddress = /^0x[a-fA-F0-9]{40}$/.test(normalizedValue);
|
|
1575
|
+
|
|
1576
|
+
return this.searchVaults({
|
|
1577
|
+
...filter,
|
|
1578
|
+
...(isAddress
|
|
1579
|
+
? { tokenAddress: normalizedValue }
|
|
1580
|
+
: { tokenSymbol: normalizedValue }),
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1417
1584
|
/**
|
|
1418
1585
|
* Gets APR data for vaults from the Steer Finance API
|
|
1419
1586
|
* @param filter - Filter containing chainId and protocol
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// This file is generated from @steerprotocol/contracts deployment JSON.
|
|
2
|
+
// It is intentionally scoped to FeeManager addresses only.
|
|
3
|
+
export interface FeeManagerDeployment {
|
|
4
|
+
address: string;
|
|
5
|
+
startBlock?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const feeManagerContractsByChainId: Record<number, FeeManagerDeployment> = {
|
|
9
|
+
14: { address: '0xb944789b5C962f1096Ce8674456E68fb0F2e3BB7' },
|
|
10
|
+
30: { address: '0xAa4448AeF5f5967693751BFB67197946BB6D1dC0' },
|
|
11
|
+
40: { address: '0xE431A1dE6F37cD08AAA8821F83bD2157857E8172' },
|
|
12
|
+
146: { address: '0x51aC65B177F084455750131A81706C32b466101D' },
|
|
13
|
+
199: { address: '0xdca3251Ebe8f85458E8d95813bCb816460e4bef1' },
|
|
14
|
+
314: { address: '0x0C5c5BEB833fD382b04e039f151942DC3D9A60ce' },
|
|
15
|
+
1284: { address: '0xfF42cD42d8a5812CB38fb3C0720Dfc490912f48B' },
|
|
16
|
+
1301: { address: '0xEd3420D9A8D42FAA8D054D284ed2bdd17a6Bca2b' },
|
|
17
|
+
1329: { address: '0x9790aFEc5d23a840bC0597D9F54584057254d190' },
|
|
18
|
+
8453: { address: '0xac4D51669B80D09d8Cc5EeFF50026c4d1D3290e6' },
|
|
19
|
+
33139: { address: '0xd47CE509bE01e62cd4629E2f1eb22BA04e7dA192' },
|
|
20
|
+
34443: { address: '0x7Daa68204232a78dBF1Dd853a4018330EE934A39' },
|
|
21
|
+
43114: { address: '0x391cf3047db983caB8dD95B16c4e6C3918d72d23' },
|
|
22
|
+
48900: { address: '0x0C5c5BEB833fD382b04e039f151942DC3D9A60ce' },
|
|
23
|
+
59144: { address: '0xBcD427Ff26b70E73149858C4898DFa60107bedBe' },
|
|
24
|
+
80084: { address: '0x0D3Ea88C8C3cb26EF21ab9E9ac6D178602Ef2779' },
|
|
25
|
+
81457: { address: '0x7Daa68204232a78dBF1Dd853a4018330EE934A39' },
|
|
26
|
+
167000: { address: '0x254d37F5eD7E96fc2d242CB06B17FAe1EE9E1ADA' },
|
|
27
|
+
534352: { address: '0xa4a2f232C92f2DE7181E9fe4d46297FbBb4afaaA' },
|
|
28
|
+
};
|
package/src/const/network.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { peaqAddresses } from "./deployments/peaq.js";
|
|
|
11
11
|
import { roninAddresses } from "./deployments/ronin.js";
|
|
12
12
|
import { nibiruAddresses } from "./deployments/nibiru.js";
|
|
13
13
|
import { hyperevmAddresses } from "./deployments/hyperevm.js";
|
|
14
|
+
import { feeManagerContractsByChainId } from './feeManagerContracts.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Interface representing a smart contract with its address and optional start block
|
|
@@ -56,6 +57,7 @@ export interface ContractAddresses {
|
|
|
56
57
|
Helper?:Contract
|
|
57
58
|
|
|
58
59
|
SingleAssetDeposit?:Contract
|
|
60
|
+
FeeManager?: Contract
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
/**
|
|
@@ -538,6 +540,13 @@ export const networks: Networks = {
|
|
|
538
540
|
}
|
|
539
541
|
};
|
|
540
542
|
|
|
543
|
+
for (const network of Object.values(networks) as NetworkConfig[]) {
|
|
544
|
+
const feeManagerDeployment = feeManagerContractsByChainId[network.chainId];
|
|
545
|
+
if (feeManagerDeployment) {
|
|
546
|
+
network.FeeManager = feeManagerDeployment;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
541
550
|
|
|
542
551
|
/**
|
|
543
552
|
* Retrieves a contract address for a specific chain ID and contract name.
|
|
@@ -632,4 +641,4 @@ export function isSingleAssetDepositSupported(chainId: number) {
|
|
|
632
641
|
const supportedChains = [ChainId.Polygon, ChainId.Hyperevm, ChainId.Peaq, ChainId.Arbitrum, ChainId.Katana, ChainId.Base, ChainId.Saga, ChainId.Mainnet, ChainId.Nibiru];
|
|
633
642
|
|
|
634
643
|
return supportedChains.indexOf(chainId) > -1;
|
|
635
|
-
}
|
|
644
|
+
}
|
package/src/const/protocol.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AMMType } from '../base/vault/single-asset/types';
|
|
2
|
-
import { SupportedProtocol
|
|
3
|
-
import { Protocol
|
|
1
|
+
import { AMMType } from '../base/vault/single-asset/types.js';
|
|
2
|
+
import { SupportedProtocol } from '../types.js';
|
|
3
|
+
import { Protocol } from './chain.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Enum representing supported staking protocols
|
|
@@ -30,10 +30,15 @@ export enum StakingProtocol {
|
|
|
30
30
|
* }
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
|
-
export function isValidStakingProtocol(protocol: string): protocol is StakingProtocol {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
export function isValidStakingProtocol(protocol: string | null | undefined): protocol is StakingProtocol {
|
|
34
|
+
if (!protocol || typeof protocol !== 'string') {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const normalizedProtocol = Object.values(StakingProtocol).find(
|
|
39
|
+
(value) => value.toLowerCase() === protocol.toLowerCase(),
|
|
40
|
+
);
|
|
41
|
+
return Boolean(normalizedProtocol);
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
/**
|
|
@@ -49,11 +54,13 @@ export function isValidStakingProtocol(protocol: string): protocol is StakingPro
|
|
|
49
54
|
* ```
|
|
50
55
|
*/
|
|
51
56
|
export function normalizeProtocol(protocol: string): StakingProtocol {
|
|
52
|
-
const normalizedProtocol =
|
|
53
|
-
|
|
57
|
+
const normalizedProtocol = Object.values(StakingProtocol).find(
|
|
58
|
+
(value) => value.toLowerCase() === protocol.toLowerCase(),
|
|
59
|
+
);
|
|
60
|
+
if (!normalizedProtocol || !isValidStakingProtocol(normalizedProtocol)) {
|
|
54
61
|
throw new Error(`Invalid protocol: ${protocol}`);
|
|
55
62
|
}
|
|
56
|
-
return normalizedProtocol
|
|
63
|
+
return normalizedProtocol;
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
/**
|
|
@@ -229,32 +236,4 @@ export const getProtcolTypeByAmmType = (ammType: AMMType): Protocol => {
|
|
|
229
236
|
}
|
|
230
237
|
|
|
231
238
|
throw Error('Protocol type not found')
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Checks if a protocol supports algebraHook for a given chain.
|
|
236
|
-
*
|
|
237
|
-
* @param protocolInfo - The protocol information object
|
|
238
|
-
* @param chain - The chain to check for algebraHook support
|
|
239
|
-
* @returns True if the protocol supports algebraHook on the given chain, false otherwise
|
|
240
|
-
* @example
|
|
241
|
-
* ```typescript
|
|
242
|
-
* const protocolInfo = `getProtocolInfoBy`Name('QuickSwapIntegral', 'api-key');
|
|
243
|
-
* if (isAlgebraHookSupported(protocolInfo, Chain.Base)) {
|
|
244
|
-
* // Protocol supports algebraHook on Base chain
|
|
245
|
-
* }
|
|
246
|
-
* ```
|
|
247
|
-
*/
|
|
248
|
-
export const isAlgebraHookSupported = (protocolInfo: ProtocolInfo | undefined, chain: Chain): boolean => {
|
|
249
|
-
if (!protocolInfo) {
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Check if the protocol has algebraHook supported chains defined
|
|
254
|
-
if (protocolInfo.algebraHookSupportedChains && Array.isArray(protocolInfo.algebraHookSupportedChains)) {
|
|
255
|
-
return protocolInfo.algebraHookSupportedChains.includes(chain);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Fallback: if no specific chains are defined but beaconAlgebraHook exists, assume it's supported
|
|
259
|
-
return !!protocolInfo.beaconAlgebraHook;
|
|
260
|
-
}
|
|
239
|
+
}
|