diff --git a/src/datasources/staking-api/entities/defi-vault-stats.entity.ts b/src/datasources/staking-api/entities/defi-vault-stats.entity.ts index 664beabbd1..fd6e96b143 100644 --- a/src/datasources/staking-api/entities/defi-vault-stats.entity.ts +++ b/src/datasources/staking-api/entities/defi-vault-stats.entity.ts @@ -35,4 +35,6 @@ export const DefiVaultStatsSchema = z.object({ updated_at_block: z.number(), }); +export const DefiVaultsStateSchema = z.array(DefiVaultStatsSchema); + export type DefiVaultStats = z.infer; diff --git a/src/datasources/staking-api/entities/deployment.entity.ts b/src/datasources/staking-api/entities/deployment.entity.ts index 2f68bb553d..de41c11a15 100644 --- a/src/datasources/staking-api/entities/deployment.entity.ts +++ b/src/datasources/staking-api/entities/deployment.entity.ts @@ -22,4 +22,6 @@ export const DeploymentSchema = z.object({ product_fee: NumericStringSchema.nullish().default(null), }); +export const DeploymentsSchema = z.array(DeploymentSchema); + export type Deployment = z.infer; diff --git a/src/datasources/staking-api/entities/stake.entity.ts b/src/datasources/staking-api/entities/stake.entity.ts index f927aa2dca..506ddaf806 100644 --- a/src/datasources/staking-api/entities/stake.entity.ts +++ b/src/datasources/staking-api/entities/stake.entity.ts @@ -26,4 +26,6 @@ export const StakeSchema = z.object({ net_claimable_consensus_rewards: NumericStringSchema.nullish().default(null), }); +export const StakesSchema = z.array(StakeSchema); + export type Stake = z.infer; diff --git a/src/datasources/staking-api/kiln-api.service.ts b/src/datasources/staking-api/kiln-api.service.ts index 93fb2d6975..2d68c14f38 100644 --- a/src/datasources/staking-api/kiln-api.service.ts +++ b/src/datasources/staking-api/kiln-api.service.ts @@ -14,7 +14,12 @@ import type { PooledStakingStats } from '@/datasources/staking-api/entities/pool import type { Stake } from '@/datasources/staking-api/entities/stake.entity'; import type { TransactionStatus } from '@/datasources/staking-api/entities/transaction-status.entity'; import type { IStakingApi } from '@/domain/interfaces/staking-api.interface'; +import type { Raw } from '@/validation/entities/raw.entity'; +/** + * TODO: Move all usage of Raw to NetworkService after fully migrated + * to "Raw" type implementation. + */ export class KilnApi implements IStakingApi { public static DefiVaultStatsChains: { [key in (typeof DefiVaultStatsChains)[number]]: string; @@ -50,13 +55,13 @@ export class KilnApi implements IStakingApi { // Important: there is no hook which invalidates this endpoint, // Therefore, this data will live in cache until [stakingExpirationTimeInSeconds] - async getDeployments(): Promise> { + async getDeployments(): Promise>> { try { const url = `${this.baseUrl}/v1/deployments`; const cacheDir = CacheRouter.getStakingDeploymentsCacheDir(); // Note: Kiln always return { data: T } const { data } = await this.dataSource.get<{ - data: Array; + data: Raw>; }>({ cacheDir, url, @@ -76,12 +81,12 @@ export class KilnApi implements IStakingApi { // Important: there is no hook which invalidates this endpoint, // Therefore, this data will live in cache until [stakingExpirationTimeInSeconds] - async getNetworkStats(): Promise { + async getNetworkStats(): Promise> { try { const url = `${this.baseUrl}/v1/eth/network-stats`; const cacheDir = CacheRouter.getStakingNetworkStatsCacheDir(); // Note: Kiln always return { data: T } - const { data } = await this.dataSource.get<{ data: NetworkStats }>({ + const { data } = await this.dataSource.get<{ data: Raw }>({ cacheDir, url, networkRequest: { @@ -100,13 +105,13 @@ export class KilnApi implements IStakingApi { // Important: there is no hook which invalidates this endpoint, // Therefore, this data will live in cache until [stakingExpirationTimeInSeconds] - async getDedicatedStakingStats(): Promise { + async getDedicatedStakingStats(): Promise> { try { const url = `${this.baseUrl}/v1/eth/kiln-stats`; const cacheDir = CacheRouter.getStakingDedicatedStakingStatsCacheDir(); // Note: Kiln always return { data: T } const { data } = await this.dataSource.get<{ - data: DedicatedStakingStats; + data: Raw; }>({ cacheDir, url, @@ -128,13 +133,13 @@ export class KilnApi implements IStakingApi { // Therefore, this data will live in cache until [stakingExpirationTimeInSeconds] async getPooledStakingStats( pool: `0x${string}`, - ): Promise { + ): Promise> { try { const url = `${this.baseUrl}/v1/eth/onchain/v2/network-stats`; const cacheDir = CacheRouter.getStakingPooledStakingStatsCacheDir(pool); // Note: Kiln always return { data: T } const { data } = await this.dataSource.get<{ - data: PooledStakingStats; + data: Raw; }>({ cacheDir, url, @@ -159,7 +164,7 @@ export class KilnApi implements IStakingApi { // Therefore, this data will live in cache until [stakingExpirationTimeInSeconds] async getDefiVaultStats( vault: `0x${string}`, - ): Promise> { + ): Promise>> { try { const url = `${this.baseUrl}/v1/defi/network-stats`; const cacheDir = CacheRouter.getStakingDefiVaultStatsCacheDir({ @@ -168,7 +173,7 @@ export class KilnApi implements IStakingApi { }); // Note: Kiln always return { data: T } const { data } = await this.dataSource.get<{ - data: Array; + data: Raw>; }>({ cacheDir, url, @@ -203,7 +208,7 @@ export class KilnApi implements IStakingApi { async getStakes(args: { safeAddress: `0x${string}`; validatorsPublicKeys: Array<`0x${string}`>; - }): Promise { + }): Promise> { try { const url = `${this.baseUrl}/v1/eth/stakes`; const cacheDir = CacheRouter.getStakingStakesCacheDir({ @@ -213,7 +218,7 @@ export class KilnApi implements IStakingApi { }); // Note: Kiln always return { data: T } const { data } = await this.dataSource.get<{ - data: Array; + data: Raw>; }>({ cacheDir, url, @@ -251,7 +256,7 @@ export class KilnApi implements IStakingApi { async getTransactionStatus( txHash: `0x${string}`, - ): Promise { + ): Promise> { try { const url = `${this.baseUrl}/v1/eth/transaction/status`; const cacheDir = CacheRouter.getStakingTransactionStatusCacheDir({ @@ -260,7 +265,7 @@ export class KilnApi implements IStakingApi { }); // Note: Kiln always return { data: T } const { data } = await this.dataSource.get<{ - data: TransactionStatus; + data: Raw; }>({ cacheDir, url, diff --git a/src/domain/interfaces/staking-api.interface.ts b/src/domain/interfaces/staking-api.interface.ts index 3d5f5d0067..771c41e816 100644 --- a/src/domain/interfaces/staking-api.interface.ts +++ b/src/domain/interfaces/staking-api.interface.ts @@ -5,26 +5,27 @@ import type { PooledStakingStats } from '@/datasources/staking-api/entities/pool import type { DefiVaultStats } from '@/datasources/staking-api/entities/defi-vault-stats.entity'; import type { Stake } from '@/datasources/staking-api/entities/stake.entity'; import type { TransactionStatus } from '@/datasources/staking-api/entities/transaction-status.entity'; +import type { Raw } from '@/validation/entities/raw.entity'; export const IStakingApi = Symbol('IStakingApi'); export interface IStakingApi { - getDeployments(): Promise>; + getDeployments(): Promise>>; - getNetworkStats(): Promise; + getNetworkStats(): Promise>; - getDedicatedStakingStats(): Promise; + getDedicatedStakingStats(): Promise>; - getPooledStakingStats(pool: `0x${string}`): Promise; + getPooledStakingStats(pool: `0x${string}`): Promise>; - getDefiVaultStats(vault: `0x${string}`): Promise>; + getDefiVaultStats(vault: `0x${string}`): Promise>>; getStakes(args: { safeAddress: `0x${string}`; validatorsPublicKeys: Array<`0x${string}`>; - }): Promise; + }): Promise>; clearStakes(safeAddress: `0x${string}`): Promise; - getTransactionStatus(txHash: `0x${string}`): Promise; + getTransactionStatus(txHash: `0x${string}`): Promise>; } diff --git a/src/domain/staking/staking.repository.ts b/src/domain/staking/staking.repository.ts index c62616eeea..80b46088f7 100644 --- a/src/domain/staking/staking.repository.ts +++ b/src/domain/staking/staking.repository.ts @@ -15,15 +15,15 @@ import { } from '@/datasources/staking-api/entities/dedicated-staking-stats.entity'; import { Deployment, - DeploymentSchema, + DeploymentsSchema, } from '@/datasources/staking-api/entities/deployment.entity'; import { + DefiVaultsStateSchema, DefiVaultStats, - DefiVaultStatsSchema, } from '@/datasources/staking-api/entities/defi-vault-stats.entity'; import { Stake, - StakeSchema, + StakesSchema, } from '@/datasources/staking-api/entities/stake.entity'; import { TransactionStatus, @@ -57,7 +57,7 @@ export class StakingRepository implements IStakingRepository { private async getDeployments(chainId: string): Promise> { const stakingApi = await this.stakingApiFactory.getApi(chainId); const deployments = await stakingApi.getDeployments(); - return deployments.map((deployment) => DeploymentSchema.parse(deployment)); + return DeploymentsSchema.parse(deployments); } public async getNetworkStats(chainId: string): Promise { @@ -90,9 +90,7 @@ export class StakingRepository implements IStakingRepository { const stakingApi = await this.stakingApiFactory.getApi(args.chainId); const defiStats = await stakingApi.getDefiVaultStats(args.vault); // Cannot be >1 contract deployed at the same address so return first element - return defiStats.map((defiStats) => - DefiVaultStatsSchema.parse(defiStats), - )[0]; + return DefiVaultsStateSchema.parse(defiStats)[0]; } public async getStakes(args: { @@ -102,7 +100,7 @@ export class StakingRepository implements IStakingRepository { }): Promise { const stakingApi = await this.stakingApiFactory.getApi(args.chainId); const stakes = await stakingApi.getStakes(args); - return stakes.map((stake) => StakeSchema.parse(stake)); + return StakesSchema.parse(stakes); } public async clearStakes(args: {