Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use helper throughout KilnApi #2165

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
299 changes: 136 additions & 163 deletions src/datasources/staking-api/kiln-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ 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';
import { z } from 'zod';
import { z, ZodError } from 'zod';

export class KilnApi implements IStakingApi {
public static DefiVaultStatsChains: {
Expand Down Expand Up @@ -53,137 +53,112 @@ 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<Raw<Array<Deployment>>> {
try {
const url = `${this.baseUrl}/v1/deployments`;
const cacheDir = CacheRouter.getStakingDeploymentsCacheDir();
const { data } = await this.get<{
data: Array<Deployment>;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
const url = `${this.baseUrl}/v1/deployments`;
const cacheDir = CacheRouter.getStakingDeploymentsCacheDir();
return await this.get<{
data: Array<Deployment>;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
return data;
} catch (error) {
throw this.httpErrorFactory.from(error);
}
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
}

// Important: there is no hook which invalidates this endpoint,
// Therefore, this data will live in cache until [stakingExpirationTimeInSeconds]
async getNetworkStats(): Promise<Raw<NetworkStats>> {
try {
const url = `${this.baseUrl}/v1/eth/network-stats`;
const cacheDir = CacheRouter.getStakingNetworkStatsCacheDir();
const { data } = await this.get<{ data: NetworkStats }>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
const url = `${this.baseUrl}/v1/eth/network-stats`;
const cacheDir = CacheRouter.getStakingNetworkStatsCacheDir();
return await this.get<{ data: NetworkStats }>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
return data;
} catch (error) {
throw this.httpErrorFactory.from(error);
}
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
}

// Important: there is no hook which invalidates this endpoint,
// Therefore, this data will live in cache until [stakingExpirationTimeInSeconds]
async getDedicatedStakingStats(): Promise<Raw<DedicatedStakingStats>> {
try {
const url = `${this.baseUrl}/v1/eth/kiln-stats`;
const cacheDir = CacheRouter.getStakingDedicatedStakingStatsCacheDir();
const { data } = await this.get<{
data: DedicatedStakingStats;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
const url = `${this.baseUrl}/v1/eth/kiln-stats`;
const cacheDir = CacheRouter.getStakingDedicatedStakingStatsCacheDir();
return await this.get<{
data: DedicatedStakingStats;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
}).then((res) => z.object({ data: z.any() }).parse(res));
return data;
} catch (error) {
throw this.httpErrorFactory.from(error);
}
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
}

// Important: there is no hook which invalidates this endpoint,
// Therefore, this data will live in cache until [stakingExpirationTimeInSeconds]
async getPooledStakingStats(
pool: `0x${string}`,
): Promise<Raw<PooledStakingStats>> {
try {
const url = `${this.baseUrl}/v1/eth/onchain/v2/network-stats`;
const cacheDir = CacheRouter.getStakingPooledStakingStatsCacheDir(pool);
const { data } = await this.get<{
data: PooledStakingStats;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
params: {
integration: pool,
},
const url = `${this.baseUrl}/v1/eth/onchain/v2/network-stats`;
const cacheDir = CacheRouter.getStakingPooledStakingStatsCacheDir(pool);
return await this.get<{
data: PooledStakingStats;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
}).then((res) => z.object({ data: z.any() }).parse(res));
return data;
} catch (error) {
throw this.httpErrorFactory.from(error);
}
params: {
integration: pool,
},
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
}

// Important: there is no hook which invalidates this endpoint,
// Therefore, this data will live in cache until [stakingExpirationTimeInSeconds]
async getDefiVaultStats(
vault: `0x${string}`,
): Promise<Raw<Array<DefiVaultStats>>> {
try {
const url = `${this.baseUrl}/v1/defi/network-stats`;
const cacheDir = CacheRouter.getStakingDefiVaultStatsCacheDir({
chainId: this.chainId,
vault,
});
const { data } = await this.get<{
data: Array<DefiVaultStats>;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
params: {
vaults: this.getDefiVaultIdentifier(vault),
},
const url = `${this.baseUrl}/v1/defi/network-stats`;
const cacheDir = CacheRouter.getStakingDefiVaultStatsCacheDir({
chainId: this.chainId,
vault,
});
return await this.get<{
data: Array<DefiVaultStats>;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
}).then((res) => z.object({ data: z.any() }).parse(res));
return data;
} catch (error) {
throw this.httpErrorFactory.from(error);
}
params: {
vaults: this.getDefiVaultIdentifier(vault),
},
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
}

/**
Expand All @@ -201,35 +176,30 @@ export class KilnApi implements IStakingApi {
safeAddress: `0x${string}`;
validatorsPublicKeys: Array<`0x${string}`>;
}): Promise<Raw<Stake[]>> {
try {
const url = `${this.baseUrl}/v1/eth/stakes`;
const cacheDir = CacheRouter.getStakingStakesCacheDir({
chainId: this.chainId,
safeAddress: args.safeAddress,
validatorsPublicKeys: args.validatorsPublicKeys,
});
const { data } = await this.get<{
data: Array<Stake>;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
params: {
validators: args.validatorsPublicKeys.join(','),
// Adds net_claimable_consensus_rewards to response
onchain_v1_include_net_rewards: true,
},
const url = `${this.baseUrl}/v1/eth/stakes`;
const cacheDir = CacheRouter.getStakingStakesCacheDir({
chainId: this.chainId,
safeAddress: args.safeAddress,
validatorsPublicKeys: args.validatorsPublicKeys,
});
return await this.get<{
data: Array<Stake>;
}>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
}).then((res) => z.object({ data: z.any() }).parse(res));
return data;
} catch (error) {
throw this.httpErrorFactory.from(error);
}
params: {
validators: args.validatorsPublicKeys.join(','),
// Adds net_claimable_consensus_rewards to response
onchain_v1_include_net_rewards: true,
},
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
}

/**
Expand All @@ -248,30 +218,25 @@ export class KilnApi implements IStakingApi {
async getTransactionStatus(
txHash: `0x${string}`,
): Promise<Raw<TransactionStatus>> {
try {
const url = `${this.baseUrl}/v1/eth/transaction/status`;
const cacheDir = CacheRouter.getStakingTransactionStatusCacheDir({
chainId: this.chainId,
txHash,
});
const { data } = await this.get<TransactionStatus>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
params: {
tx_hash: txHash,
},
const url = `${this.baseUrl}/v1/eth/transaction/status`;
const cacheDir = CacheRouter.getStakingTransactionStatusCacheDir({
chainId: this.chainId,
txHash,
});
return await this.get<TransactionStatus>({
cacheDir,
url,
networkRequest: {
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
return data;
} catch (error) {
throw this.httpErrorFactory.from(error);
}
params: {
tx_hash: txHash,
},
},
notFoundExpireTimeSeconds: this.defaultNotFoundExpirationTimeSeconds,
expireTimeSeconds: this.stakingExpirationTimeInSeconds,
});
}

/**
Expand All @@ -281,15 +246,23 @@ export class KilnApi implements IStakingApi {
*/
private async get<T>(
args: Parameters<typeof this.dataSource.get>[0],
): Promise<{ data: Raw<T> }> {
return this.dataSource
.get<{
data: TransactionStatus;
}>(args)
.then((res) => {
// Ensuring response is { data: T }, the data is parsed in the domain
return z.object({ data: z.unknown() }).parse(res) as { data: Raw<T> };
});
): Promise<Raw<T>> {
try {
const { data } = await this.dataSource
.get<{
data: TransactionStatus;
}>(args)
.then((res) => {
// Ensuring response is { data: T }, the data is parsed in the domain
return z.object({ data: z.unknown() }).parse(res) as { data: Raw<T> };
});
return data;
} catch (error) {
if (error instanceof ZodError) {
throw error;
}
PooyaRaki marked this conversation as resolved.
Show resolved Hide resolved
throw this.httpErrorFactory.from(error);
}
}

/**
Expand Down