From b31c2a5bee866c505bcc6e5a46b14b253886fbff Mon Sep 17 00:00:00 2001 From: Redm4x <2829180+Redm4x@users.noreply.github.com> Date: Tue, 19 Mar 2024 02:37:11 -0400 Subject: [PATCH 1/7] Improve api typings --- api/src/caching/memoryCacheEngine.ts | 70 ++++----- api/src/db/dbConnection.ts | 2 +- api/src/middlewares/privateMiddleware.ts | 4 +- api/src/routers/internalRouter.ts | 11 +- api/src/routes/v1/graphData.ts | 24 +-- api/src/services/db/deploymentService.ts | 10 +- api/src/services/db/providerDataService.ts | 10 +- api/src/services/db/statsService.ts | 44 +++++- api/src/services/db/templateService.ts | 4 +- api/src/services/db/transactionsService.ts | 4 +- api/src/services/external/apiNodeService.ts | 53 ++++--- .../services/external/templateReposService.ts | 137 +++++++++++------- .../types/rest/cosmosBankSupplyResponse.ts | 7 + ...cosmosDistributionCommunityPoolResponse.ts | 3 + .../rest/cosmosDistributionParamsResponse.ts | 8 + ...istributionValidatorsCommissionResponse.ts | 5 + .../types/rest/cosmosMintInflationResponse.ts | 3 + .../types/rest/cosmosStakingPoolResponse.ts | 6 + api/src/utils/map/provider.ts | 8 +- api/src/utils/templateReposLogos.ts | 2 +- 20 files changed, 250 insertions(+), 165 deletions(-) create mode 100644 api/src/types/rest/cosmosBankSupplyResponse.ts create mode 100644 api/src/types/rest/cosmosDistributionCommunityPoolResponse.ts create mode 100644 api/src/types/rest/cosmosDistributionParamsResponse.ts create mode 100644 api/src/types/rest/cosmosDistributionValidatorsCommissionResponse.ts create mode 100644 api/src/types/rest/cosmosMintInflationResponse.ts create mode 100644 api/src/types/rest/cosmosStakingPoolResponse.ts diff --git a/api/src/caching/memoryCacheEngine.ts b/api/src/caching/memoryCacheEngine.ts index 9c6db08b5..81177ecdf 100644 --- a/api/src/caching/memoryCacheEngine.ts +++ b/api/src/caching/memoryCacheEngine.ts @@ -1,38 +1,38 @@ import mcache from "memory-cache"; -export default function MemoryCacheEngine() {} +export default class MemoryCacheEngine { + /** + * Used to retrieve data from memcache + * @param {*} key + */ + getFromCache = (key: string) => { + const cachedBody = mcache.get(key); + if (cachedBody) { + return cachedBody; + } + return false; + }; -/** - * Used to retrieve data from memcache - * @param {*} key - */ -MemoryCacheEngine.prototype.getFromCache = (key) => { - const cachedBody = mcache.get(key); - if (cachedBody) { - return cachedBody; - } - return false; -}; - -/** - * Used to store data in a memcache - * @param {*} key - * @param {*} data - * @param {*} duration - */ -MemoryCacheEngine.prototype.storeInCache = (key, data, duration) => { - mcache.put(key, data, duration); -}; -/** - * Used to delete all keys in a memcache - */ -MemoryCacheEngine.prototype.clearAllKeyInCache = () => { - mcache.clear(); -}; -/** - * Used to delete specific key from memcache - * @param {*} key - */ - MemoryCacheEngine.prototype.clearAllKeyInCache = (key) => { - mcache.del(key); -}; \ No newline at end of file + /** + * Used to store data in a memcache + * @param {*} key + * @param {*} data + * @param {*} duration + */ + storeInCache = (key: string, data: any, duration?: number) => { + mcache.put(key, data, duration); + }; + /** + * Used to delete all keys in a memcache + */ + clearAllKeyInCache = () => { + mcache.clear(); + }; + /** + * Used to delete specific key from memcache + * @param {*} key + */ + clearKeyInCache = (key: string) => { + mcache.del(key); + }; +} diff --git a/api/src/db/dbConnection.ts b/api/src/db/dbConnection.ts index a51983e70..0cd8abed3 100644 --- a/api/src/db/dbConnection.ts +++ b/api/src/db/dbConnection.ts @@ -6,7 +6,7 @@ import { chainModels, getChainModels, userModels } from "@shared/dbSchemas"; import { Template, TemplateFavorite, UserAddressName, UserSetting } from "@shared/dbSchemas/user"; import { chainDefinitions } from "@shared/chainDefinitions"; -const csMap = { +const csMap: { [key: string]: string } = { mainnet: env.AkashDatabaseCS, testnet: env.AkashTestnetDatabaseCS, sandbox: env.AkashSandboxDatabaseCS diff --git a/api/src/middlewares/privateMiddleware.ts b/api/src/middlewares/privateMiddleware.ts index 97e875382..2149455d9 100644 --- a/api/src/middlewares/privateMiddleware.ts +++ b/api/src/middlewares/privateMiddleware.ts @@ -1,7 +1,7 @@ import { env } from "@src/utils/env"; -import { Context } from "hono"; +import { Context, Next } from "hono"; -export async function privateMiddleware(c: Context, next) { +export async function privateMiddleware(c: Context, next: Next) { if (!env.SecretToken) { await next(); } else if (c.req.query("token") === env.SecretToken) { diff --git a/api/src/routers/internalRouter.ts b/api/src/routers/internalRouter.ts index 48f015c3e..7ceebd94c 100644 --- a/api/src/routers/internalRouter.ts +++ b/api/src/routers/internalRouter.ts @@ -46,10 +46,13 @@ internalRouter.get("/provider-versions", async (c) => { .filter((x) => x.version !== nullVersionName) // Remove version for sorting .sort((a, b) => semver.compare(b.version, a.version)) .concat(results.filter((x) => x.version === nullVersionName)) // Add back version at the end - .reduce((acc, x) => { - acc[x.version] = x; - return acc; - }, {}); + .reduce( + (acc, x) => { + acc[x.version] = x; + return acc; + }, + {} as { [key: string]: (typeof results)[number] } + ); return c.json(sorted); }); diff --git a/api/src/routes/v1/graphData.ts b/api/src/routes/v1/graphData.ts index 7fad24382..fbeb90f43 100644 --- a/api/src/routes/v1/graphData.ts +++ b/api/src/routes/v1/graphData.ts @@ -1,21 +1,5 @@ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi"; -import { getGraphData } from "@src/services/db/statsService"; - -const authorizedDataNames = [ - "dailyUAktSpent", - "dailyUUsdcSpent", - "dailyUUsdSpent", - "dailyLeaseCount", - "totalUAktSpent", - "totalUUsdcSpent", - "totalUUsdSpent", - "activeLeaseCount", - "totalLeaseCount", - "activeCPU", - "activeGPU", - "activeMemory", - "activeStorage" -]; +import { AuthorizedGraphDataNames, getGraphData, isValidGraphDataName } from "@src/services/db/statsService"; const route = createRoute({ method: "get", @@ -23,7 +7,7 @@ const route = createRoute({ tags: ["Analytics"], request: { params: z.object({ - dataName: z.string().openapi({ example: "dailyUAktSpent", enum: authorizedDataNames }) + dataName: z.string().openapi({ example: "dailyUAktSpent", enum: Array.from(AuthorizedGraphDataNames) }) }) }, responses: { @@ -53,9 +37,9 @@ const route = createRoute({ export default new OpenAPIHono().openapi(route, async (c) => { const dataName = c.req.valid("param").dataName; - if (!authorizedDataNames.includes(dataName)) { + if (!isValidGraphDataName(dataName)) { console.log("Rejected graph request: " + dataName); - return c.text("Graph not found", 404); + return c.text("Graph not found: " + dataName, 404); } const graphData = await getGraphData(dataName); diff --git a/api/src/services/db/deploymentService.ts b/api/src/services/db/deploymentService.ts index c9224cd2c..ed92d544c 100644 --- a/api/src/services/db/deploymentService.ts +++ b/api/src/services/db/deploymentService.ts @@ -3,7 +3,7 @@ import * as v2 from "@src/proto/akash/v1beta2"; import { decodeMsg } from "@src/utils/protobuf"; import { Transaction } from "@shared/dbSchemas/base"; import { Deployment, Lease } from "@shared/dbSchemas/akash"; -import { Op } from "sequelize"; +import { Op, WhereOptions } from "sequelize"; import { Block, Message } from "@shared/dbSchemas"; export async function getDeploymentRelatedMessages(owner: string, dseq: string) { @@ -71,9 +71,9 @@ export async function getDeploymentRelatedMessages(owner: string, dseq: string) } export async function getProviderDeploymentsCount(provider: string, status?: "active" | "closed") { - const leaseFilter = { providerAddress: provider }; + const leaseFilter: WhereOptions = { providerAddress: provider }; if (status) { - leaseFilter["closedHeight"] = status === "active" ? null : { [Op.ne]: null }; + leaseFilter.closedHeight = status === "active" ? null : { [Op.ne]: null }; } const result = await Deployment.count({ @@ -84,10 +84,10 @@ export async function getProviderDeploymentsCount(provider: string, status?: "ac } export async function getProviderDeployments(provider: string, skip: number, limit: number, status?: "active" | "closed") { - const leaseFilter = { providerAddress: provider }; + const leaseFilter: WhereOptions = { providerAddress: provider }; if (status) { - leaseFilter["closedHeight"] = status === "active" ? null : { [Op.ne]: null }; + leaseFilter.closedHeight = status === "active" ? null : { [Op.ne]: null }; } const deploymentDseqs = await Deployment.findAll({ diff --git a/api/src/services/db/providerDataService.ts b/api/src/services/db/providerDataService.ts index f2c6749b4..0d6d36d69 100644 --- a/api/src/services/db/providerDataService.ts +++ b/api/src/services/db/providerDataService.ts @@ -5,15 +5,15 @@ export async function getProviderRegions() { const providerAttributesSchema = await getProviderAttributesSchema(); const regions = providerAttributesSchema["location-region"].values; - const providerRegions = await Provider.findAll({ + const providers = await Provider.findAll({ attributes: ["owner"], - include: [{ model: ProviderAttribute, attributes: [["value", "location_region"]], where: { key: "location-region" } }], - raw: true + include: [{ model: ProviderAttribute, attributes: ["value"], where: { key: "location-region" } }] }); + console.log(JSON.stringify(providers, null, 2)); const result = regions.map((region) => { - const providers = providerRegions.filter((x) => x["providerAttributes.location_region"] === region.key).map((x) => x.owner); - return { ...region, providers }; + const filteredProviders = providers.filter((p) => p.providerAttributes.some((attr) => attr.value === region.key)).map((x) => x.owner); + return { ...region, providers: filteredProviders }; }); return result; diff --git a/api/src/services/db/statsService.ts b/api/src/services/db/statsService.ts index 9d60d2242..8f572228b 100644 --- a/api/src/services/db/statsService.ts +++ b/api/src/services/db/statsService.ts @@ -75,12 +75,34 @@ export const getDashboardData = async () => { }; }; -export async function getGraphData(dataName: string): Promise { +export const AuthorizedGraphDataNames = [ + "dailyUAktSpent", + "dailyUUsdcSpent", + "dailyUUsdSpent", + "dailyLeaseCount", + "totalUAktSpent", + "totalUUsdcSpent", + "totalUUsdSpent", + "activeLeaseCount", + "totalLeaseCount", + "activeCPU", + "activeGPU", + "activeMemory", + "activeStorage" +] as const; + +type AuthorizedGraphDataName = (typeof AuthorizedGraphDataNames)[number]; + +export function isValidGraphDataName(x: any): x is AuthorizedGraphDataName { + return AuthorizedGraphDataNames.includes(x); +} + +export async function getGraphData(dataName: AuthorizedGraphDataName): Promise { console.log("getGraphData: " + dataName); - let attributes = [dataName]; + let attributes: (keyof Block)[] = []; let isRelative = false; - let getter = (block: Block) => block[dataName] as number; + let getter: (block: Block) => number = null; switch (dataName) { case "dailyUAktSpent": @@ -107,6 +129,9 @@ export async function getGraphData(dataName: string): Promise { attributes = ["activeEphemeralStorage", "activePersistentStorage"]; getter = (block: Block) => block.activeEphemeralStorage + block.activePersistentStorage; break; + default: + attributes = [dataName]; + getter = (block: Block) => block[dataName]; } const result = await Day.findAll({ @@ -158,7 +183,7 @@ export const getProviderGraphData = async (dataName: ProviderStatsKey) => { 60 * 5, // 5 minutes cacheKeys.getProviderGraphData, async () => { - return (await chainDb.query( + return await chainDb.query( `SELECT d."date", (SUM("activeCPU") + SUM("pendingCPU") + SUM("availableCPU")) AS "cpu", (SUM("activeGPU") + SUM("pendingGPU") + SUM("availableGPU")) AS "gpu", (SUM("activeMemory") + SUM("pendingMemory") + SUM("availableMemory")) AS memory, (SUM("activeStorage") + SUM("pendingStorage") + SUM("availableStorage")) as storage, COUNT(*) as count FROM "day" d INNER JOIN ( @@ -174,7 +199,7 @@ export const getProviderGraphData = async (dataName: ProviderStatsKey) => { { type: QueryTypes.SELECT } - )) as ProviderStats[]; + ); }, true ); @@ -183,12 +208,15 @@ export const getProviderGraphData = async (dataName: ProviderStatsKey) => { return { currentValue: 0, compareValue: 0, - snapshots: [] + snapshots: [] as { + date: string; + value: number; + }[] }; } - const currentValue = result[result.length - 1] as ProviderStats; - const compareValue = result[result.length - 2] as ProviderStats; + const currentValue = result[result.length - 1]; + const compareValue = result[result.length - 2]; const stats = result.map((day) => ({ date: day.date, diff --git a/api/src/services/db/templateService.ts b/api/src/services/db/templateService.ts index 8e9ddc3f1..524ddb5f7 100644 --- a/api/src/services/db/templateService.ts +++ b/api/src/services/db/templateService.ts @@ -104,7 +104,7 @@ export async function saveTemplateDesc(id: string, userId: string, description: }); if (!id || !template) { - return null; + return; } template.description = description; @@ -140,7 +140,7 @@ export async function addTemplateFavorite(userId: string, templateId: string) { }); if (template) { - return null; + return; } await TemplateFavorite.create({ diff --git a/api/src/services/db/transactionsService.ts b/api/src/services/db/transactionsService.ts index ae26a3064..54011f092 100644 --- a/api/src/services/db/transactionsService.ts +++ b/api/src/services/db/transactionsService.ts @@ -98,7 +98,7 @@ export async function getTransactionByAddress(address: string, skip: number, lim where: { address: address } }); - const txIdsQuery = chainDb.query( + const txIdsQuery = chainDb.query<{ transactionId: string }>( `SELECT "transactionId" FROM ( SELECT DISTINCT ON(af."transactionId") * FROM "addressReference" af @@ -117,7 +117,7 @@ export async function getTransactionByAddress(address: string, skip: number, lim const txs = await Transaction.findAll({ include: [{ model: Block, required: true }, { model: Message }, { model: AddressReference, required: true, where: { address: address } }], - where: { id: txIds.map((x) => x["transactionId"]) }, + where: { id: txIds.map((x) => x.transactionId) }, order: [ ["height", "DESC"], ["index", "DESC"] diff --git a/api/src/services/external/apiNodeService.ts b/api/src/services/external/apiNodeService.ts index 74eda8d18..ff6e6a59b 100644 --- a/api/src/services/external/apiNodeService.ts +++ b/api/src/services/external/apiNodeService.ts @@ -23,8 +23,14 @@ import { RestCosmosStakingDelegatorsRedelegationsResponse } from "@src/types/rest"; import { Block } from "@shared/dbSchemas"; - -const defaultNodeUrlMapping = { +import { CosmosDistributionCommunityPoolResponse } from "@src/types/rest/cosmosDistributionCommunityPoolResponse"; +import { CosmosStakingPoolResponse } from "@src/types/rest/cosmosStakingPoolResponse"; +import { CosmosBankSupplyResponse } from "@src/types/rest/cosmosBankSupplyResponse"; +import { CosmosMintInflationResponse } from "@src/types/rest/cosmosMintInflationResponse"; +import { CosmosDistributionParamsResponse } from "@src/types/rest/cosmosDistributionParamsResponse"; +import { CosmosDistributionValidatorsCommissionResponse } from "@src/types/rest/cosmosDistributionValidatorsCommissionResponse"; + +const defaultNodeUrlMapping: { [key: string]: string } = { mainnet: "https://rest.cosmos.directory/akash", sandbox: "https://api.sandbox-01.aksh.pw", testnet: "https://api.testnet-02.aksh.pw" @@ -39,11 +45,11 @@ export async function getChainStats() { 60 * 5, // 5 minutes cacheKeys.getChainStats, async () => { - const bondedTokensQuery = axios.get(`${apiNodeUrl}/cosmos/staking/v1beta1/pool`); - const supplyQuery = axios.get(`${apiNodeUrl}/cosmos/bank/v1beta1/supply`); - const communityPoolQuery = axios.get(`${apiNodeUrl}/cosmos/distribution/v1beta1/community_pool`); - const inflationQuery = axios.get(`${apiNodeUrl}/cosmos/mint/v1beta1/inflation`); - const distributionQuery = axios.get(`${apiNodeUrl}/cosmos/distribution/v1beta1/params`); + const bondedTokensQuery = axios.get(`${apiNodeUrl}/cosmos/staking/v1beta1/pool`); + const supplyQuery = axios.get(`${apiNodeUrl}/cosmos/bank/v1beta1/supply`); + const communityPoolQuery = axios.get(`${apiNodeUrl}/cosmos/distribution/v1beta1/community_pool`); + const inflationQuery = axios.get(`${apiNodeUrl}/cosmos/mint/v1beta1/inflation`); + const distributionQuery = axios.get(`${apiNodeUrl}/cosmos/distribution/v1beta1/params`); const [bondedTokensResponse, supplyResponse, communityPoolResponse, inflationResponse, distributionResponse] = await Promise.all([ bondedTokensQuery, @@ -95,9 +101,10 @@ export async function getAddressBalance(address: string) { let commission = 0; if (validatorFromDb?.operatorAddress) { - const commissionQuery = await fetch(`${apiNodeUrl}/cosmos/distribution/v1beta1/validators/${validatorFromDb?.operatorAddress}/commission`); - const commissionData = await commissionQuery.json(); - const coin = commissionData.commission.commission.find((x) => x.denom === "uakt"); + const commissionData = await axios.get( + `${apiNodeUrl}/cosmos/distribution/v1beta1/validators/${validatorFromDb.operatorAddress}/commission` + ); + const coin = commissionData.data.commission.commission.find((x) => x.denom === "uakt"); commission = coin ? parseFloat(coin.amount) : 0; } @@ -272,18 +279,18 @@ export async function getProposal(id: number) { try { const { data } = await axios.get(`${apiNodeUrl}/cosmos/gov/v1beta1/proposals/${id}`); - const proposer = null; // TODO: Fix - if (id > 3) { - // const proposerResponse = await fetch(`${apiNodeUrl}/gov/proposals/${id}/proposer`); - // const proposerData = await proposerResponse.json(); - // const validatorFromDb = await Validator.findOne({ where: { accountAddress: proposerData.result.proposer } }); - // proposer = { - // address: proposer, - // moniker: validatorFromDb?.moniker, - // operatorAddress: validatorFromDb?.operatorAddress, - // avatarUrl: validatorFromDb?.keybaseAvatarUrl - // }; - } + // const proposer = null; // TODO: Fix + // if (id > 3) { + // const proposerResponse = await fetch(`${apiNodeUrl}/gov/proposals/${id}/proposer`); + // const proposerData = await proposerResponse.json(); + // const validatorFromDb = await Validator.findOne({ where: { accountAddress: proposerData.result.proposer } }); + // proposer = { + // address: proposer, + // moniker: validatorFromDb?.moniker, + // operatorAddress: validatorFromDb?.operatorAddress, + // avatarUrl: validatorFromDb?.keybaseAvatarUrl + // }; + // } let tally = null; @@ -314,7 +321,7 @@ export async function getProposal(id: number) { votingStartTime: data.proposal.voting_start_time, votingEndTime: data.proposal.voting_end_time, totalDeposit: parseInt(data.proposal.total_deposit[0].amount), - proposer: proposer, + //proposer: proposer, tally: { ...tally, total: tally.yes + tally.abstain + tally.no + tally.noWithVeto }, paramChanges: (data.proposal.content.changes || []).map((change) => ({ subspace: change.subspace, diff --git a/api/src/services/external/templateReposService.ts b/api/src/services/external/templateReposService.ts index 39011448a..30cef871b 100644 --- a/api/src/services/external/templateReposService.ts +++ b/api/src/services/external/templateReposService.ts @@ -1,18 +1,18 @@ import fetch from "node-fetch"; -import { markdownToTxt } from "markdown-to-txt"; import path from "path"; +import { markdownToTxt } from "markdown-to-txt"; import { getOctokit } from "./githubService"; import { isUrlAbsolute } from "@src/utils/urls"; -import * as fs from "fs"; import { Octokit } from "@octokit/rest"; import { dataFolderPath } from "@src/utils/constants"; import { GithubChainRegistryChainResponse } from "@src/types"; import { GithubDirectoryItem } from "@src/types/github"; import { getLogoFromPath } from "@src/utils/templateReposLogos"; +import * as fs from "fs"; -const generatingTasks = {}; -let lastServedData = null; -let githubRequestsRemaining = null; +const generatingTasks: { [key: string]: Promise } = {}; +let lastServedData: FinalCategory[] | null = null; +let githubRequestsRemaining: string | null = null; if (!fs.existsSync(dataFolderPath)) { fs.mkdirSync(dataFolderPath); @@ -21,16 +21,16 @@ if (!fs.existsSync(dataFolderPath)) { type Category = { title: string; description?: string; + templateSources: TemplateSource[]; templates: Template[]; }; +type FinalCategory = Omit; + type Template = { id?: string; name: string; path: string; - repoOwner?: string; - repoName?: string; - repoVersion?: string; readme?: string; summary: string; logoUrl: string; @@ -40,8 +40,23 @@ type Template = { persistentStorageEnabled?: boolean; }; +type TemplateSource = { + name: string; + path: string; + repoOwner: string; + repoName: string; + repoVersion: string; + summary?: string; + logoUrl?: string; +}; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -async function getTemplatesFromRepo(octokit: Octokit, repoOwner: string, repoName: string, fetcher: (ocktokit: Octokit, version: string) => Promise) { +async function getTemplatesFromRepo( + octokit: Octokit, + repoOwner: string, + repoName: string, + fetcher: (ocktokit: Octokit, version: string) => Promise +) { const repoVersion = await fetchRepoVersion(octokit, repoOwner, repoName); const cacheFilePath = `${dataFolderPath}/templates/${repoOwner}-${repoName}-${repoVersion}.json`; @@ -93,7 +108,9 @@ export const getTemplateGallery = async () => { linuxServerTemplatesTask ]); - const templateGallery = mergeTemplateCategories(omnibusTemplates, awesomeAkashTemplates, linuxServerTemplates); + const templateGallery = mergeTemplateCategories(omnibusTemplates, awesomeAkashTemplates, linuxServerTemplates).map( + ({ templateSources, ...category }) => category + ); lastServedData = templateGallery; @@ -145,7 +162,7 @@ async function fetchOmnibusTemplates(octokit: Octokit, repoVersion: string) { if (!Array.isArray(response.data)) throw "Could not fetch list of files from akash-network/cosmos-omnibus"; const folders = response.data.filter((f) => f.type === "dir" && !f.name.startsWith(".") && !f.name.startsWith("_")); - const templates = folders.map((x) => ({ + const templateSources: TemplateSource[] = folders.map((x) => ({ name: x.name, path: x.path, logoUrl: null, @@ -156,18 +173,18 @@ async function fetchOmnibusTemplates(octokit: Octokit, repoVersion: string) { repoVersion: repoVersion })); - for (const template of templates) { + for (const templateSource of templateSources) { try { - const chainResponse = await fetch(`https://raw.githubusercontent.com/cosmos/chain-registry/master/${template.path}/chain.json`); + const chainResponse = await fetch(`https://raw.githubusercontent.com/cosmos/chain-registry/master/${templateSource.path}/chain.json`); - if (chainResponse.status !== 200) throw "Could not fetch chain.json for " + template.path; + if (chainResponse.status !== 200) throw "Could not fetch chain.json for " + templateSource.path; const chainData = (await chainResponse.json()) as GithubChainRegistryChainResponse; - template.name = chainData.pretty_name; - template.summary = chainData.description ?? template.summary; - template.logoUrl = Object.values(chainData.logo_URIs ?? {})[0]; + templateSource.name = chainData.pretty_name; + templateSource.summary = chainData.description ?? templateSource.summary; + templateSource.logoUrl = Object.values(chainData.logo_URIs ?? {})[0]; } catch (err) { - console.log("Could not fetch chain for", template.path); + console.log("Could not fetch chain for", templateSource.path); console.error(err); } } @@ -175,7 +192,8 @@ async function fetchOmnibusTemplates(octokit: Octokit, repoVersion: string) { const categories: Category[] = [ { title: "Blockchain", - templates: templates + templateSources: templateSources, + templates: [] } ]; @@ -204,7 +222,7 @@ async function fetchAwesomeAkashTemplates(octokit: Octokit, repoVersion: string) const categoryRegex = /### (.+)\n*([\w ]+)?\n*((?:- \[(?:.+)]\((?:.+)\)\n?)*)/gm; const templateRegex = /(- \[(.+)]\((.+)\)\n?)/gm; - const categories = []; + const categories: Category[] = []; // Looping through categories const matches = data.matchAll(categoryRegex); @@ -219,11 +237,11 @@ async function fetchAwesomeAkashTemplates(octokit: Octokit, repoVersion: string) } // Extracting templates - const templates = []; + const templateSources: TemplateSource[] = []; if (templatesStr) { const templateMatches = templatesStr.matchAll(templateRegex); for (const templateMatch of templateMatches) { - templates.push({ + templateSources.push({ name: templateMatch[2], path: templateMatch[3], repoOwner: "akash-network", @@ -236,7 +254,8 @@ async function fetchAwesomeAkashTemplates(octokit: Octokit, repoVersion: string) categories.push({ title: title, description: description, - templates: templates + templateSources: templateSources, + templates: [] }); } @@ -265,7 +284,7 @@ async function fetchLinuxServerTemplates(octokit: Octokit, repoVersion: string) const categoryRegex = /### (.+)\n*([\w ]+)?\n*((?:- \[(?:.+)]\((?:.+)\)\n?)*)/gm; const templateRegex = /(- \[(.+)]\((.+)\)\n?)/gm; - const categories = []; + const categories: Category[] = []; // Looping through categories const matches = data.matchAll(categoryRegex); @@ -280,11 +299,11 @@ async function fetchLinuxServerTemplates(octokit: Octokit, repoVersion: string) } // Extracting templates - const templates = []; + const templatesSources: TemplateSource[] = []; if (templatesStr) { const templateMatches = templatesStr.matchAll(templateRegex); for (const templateMatch of templateMatches) { - templates.push({ + templatesSources.push({ name: templateMatch[2], path: templateMatch[3], repoOwner: "cryptoandcoffee", @@ -297,7 +316,8 @@ async function fetchLinuxServerTemplates(octokit: Octokit, repoVersion: string) categories.push({ title: title, description: description, - templates: templates + templateSources: templatesSources, + templates: [] }); } @@ -306,19 +326,19 @@ async function fetchLinuxServerTemplates(octokit: Octokit, repoVersion: string) export async function fetchLinuxServerTemplatesInfo(octokit: Octokit, categories: Category[]) { for (const category of categories) { - for (const template of category.templates) { + for (const templateSource of category.templateSources) { try { // Ignoring templates that are not in the awesome-akash repo - if (template.path.startsWith("http:") || template.path.startsWith("https:")) { + if (templateSource.path.startsWith("http:") || templateSource.path.startsWith("https:")) { throw "Absolute URL"; } // Fetching file list in template folder const response = await octokit.rest.repos.getContent({ - repo: template.repoName, - owner: template.repoOwner, - ref: template.repoVersion, - path: template.path, + repo: templateSource.repoName, + owner: templateSource.repoOwner, + ref: templateSource.repoVersion, + path: templateSource.path, mediaType: { format: "raw" } @@ -337,6 +357,7 @@ export async function fetchLinuxServerTemplatesInfo(octokit: Octokit, categories "container is not meant for public consumption", "Not for public consumption" ]; + if (ignoreList.map((x) => x.toLowerCase()).some((x) => readme.toLowerCase().includes(x))) { continue; } @@ -344,7 +365,14 @@ export async function fetchLinuxServerTemplatesInfo(octokit: Octokit, categories const deploy = await findFileContentAsync(["deploy.yaml", "deploy.yml"], response.data); const guide = await findFileContentAsync("GUIDE.md", response.data); - template.readme = removeComments(replaceLinks(readme, template.repoOwner, template.repoName, template.repoVersion, template.path)); + const template: Template = { + name: templateSource.name, + path: templateSource.path, + logoUrl: templateSource.logoUrl, + summary: templateSource.summary + }; + + template.readme = removeComments(replaceLinks(readme, templateSource.repoOwner, templateSource.repoName, templateSource.repoVersion, template.path)); if (template.readme.startsWith("undefined")) { template.readme = template.readme.substring("undefined".length); @@ -353,7 +381,7 @@ export async function fetchLinuxServerTemplatesInfo(octokit: Octokit, categories template.deploy = deploy; template.persistentStorageEnabled = deploy && (deploy.includes("persistent: true") || deploy.includes("persistent:true")); template.guide = guide; - template.githubUrl = `https://github.com/${template.repoOwner}/${template.repoName}/blob/${template.repoVersion}/${template.path}`; + template.githubUrl = `https://github.com/${templateSource.repoOwner}/${templateSource.repoName}/blob/${templateSource.repoVersion}/${templateSource.path}`; if (!template.logoUrl) { template.logoUrl = getLogoFromPath(template.path); @@ -363,16 +391,14 @@ export async function fetchLinuxServerTemplatesInfo(octokit: Octokit, categories template.summary = getLinuxServerTemplateSummary(readme); } - template.id = `${template.repoOwner}-${template.repoName}-${template.path}`; + template.id = `${templateSource.repoOwner}-${templateSource.repoName}-${templateSource.path}`; template.path = template.id; // For compatibility with old deploy tool versions (TODO: remove in future) - delete template.repoOwner; - delete template.repoName; - delete template.repoVersion; + category.templates.push(template); console.log(category.title + " - " + template.name); } catch (err) { - console.warn(`Skipped ${template.name} because of error: ${err.message || err}`); + console.warn(`Skipped ${templateSource.name} because of error: ${err.message || err}`); } } } @@ -390,19 +416,19 @@ export async function fetchLinuxServerTemplatesInfo(octokit: Octokit, categories export async function fetchTemplatesInfo(octokit: Octokit, categories: Category[]) { for (const category of categories) { - for (const template of category.templates) { + for (const templateSource of category.templateSources) { try { // Ignoring templates that are not in the awesome-akash repo - if (template.path.startsWith("http:") || template.path.startsWith("https:")) { + if (templateSource.path.startsWith("http:") || templateSource.path.startsWith("https:")) { throw "Absolute URL"; } // Fetching file list in template folder const response = await octokit.rest.repos.getContent({ - repo: template.repoName, - owner: template.repoOwner, - ref: template.repoVersion, - path: template.path, + repo: templateSource.repoName, + owner: templateSource.repoOwner, + ref: templateSource.repoVersion, + path: templateSource.path, mediaType: { format: "raw" } @@ -416,11 +442,18 @@ export async function fetchTemplatesInfo(octokit: Octokit, categories: Category[ const deploy = await findFileContentAsync(["deploy.yaml", "deploy.yml"], response.data); const guide = await findFileContentAsync("GUIDE.md", response.data); - template.readme = readme && replaceLinks(readme, template.repoOwner, template.repoName, template.repoVersion, template.path); + const template: Template = { + name: templateSource.name, + path: templateSource.path, + logoUrl: templateSource.logoUrl, + summary: templateSource.summary + }; + + template.readme = readme && replaceLinks(readme, templateSource.repoOwner, templateSource.repoName, templateSource.repoVersion, templateSource.path); template.deploy = deploy; template.persistentStorageEnabled = deploy && (deploy.includes("persistent: true") || deploy.includes("persistent:true")); template.guide = guide; - template.githubUrl = `https://github.com/${template.repoOwner}/${template.repoName}/blob/${template.repoVersion}/${template.path}`; + template.githubUrl = `https://github.com/${templateSource.repoOwner}/${templateSource.repoName}/blob/${templateSource.repoVersion}/${templateSource.path}`; if (!template.logoUrl) { template.logoUrl = getLogoFromPath(template.path); @@ -430,16 +463,14 @@ export async function fetchTemplatesInfo(octokit: Octokit, categories: Category[ template.summary = getTemplateSummary(readme); } - template.id = `${template.repoOwner}-${template.repoName}-${template.path}`; + template.id = `${templateSource.repoOwner}-${templateSource.repoName}-${templateSource.path}`; template.path = template.id; // For compatibility with old deploy tool versions (TODO: remove in future) - delete template.repoOwner; - delete template.repoName; - delete template.repoVersion; + category.templates.push(template); console.log(category.title + " - " + template.name); } catch (err) { - console.warn(`Skipped ${template.name} because of error: ${err.message || err}`); + console.warn(`Skipped ${templateSource.name} because of error: ${err.message || err}`); } } } diff --git a/api/src/types/rest/cosmosBankSupplyResponse.ts b/api/src/types/rest/cosmosBankSupplyResponse.ts new file mode 100644 index 000000000..45c764eb9 --- /dev/null +++ b/api/src/types/rest/cosmosBankSupplyResponse.ts @@ -0,0 +1,7 @@ +export type CosmosBankSupplyResponse = { + supply: { denom: string; amount: string }[]; + pagination: { + next_key: string | null; + total: string; + }; +}; diff --git a/api/src/types/rest/cosmosDistributionCommunityPoolResponse.ts b/api/src/types/rest/cosmosDistributionCommunityPoolResponse.ts new file mode 100644 index 000000000..703fe8f59 --- /dev/null +++ b/api/src/types/rest/cosmosDistributionCommunityPoolResponse.ts @@ -0,0 +1,3 @@ +export type CosmosDistributionCommunityPoolResponse = { + pool: { denom: string; amount: string }[]; +}; diff --git a/api/src/types/rest/cosmosDistributionParamsResponse.ts b/api/src/types/rest/cosmosDistributionParamsResponse.ts new file mode 100644 index 000000000..c9e81390d --- /dev/null +++ b/api/src/types/rest/cosmosDistributionParamsResponse.ts @@ -0,0 +1,8 @@ +export type CosmosDistributionParamsResponse = { + params: { + community_tax: string; + base_proposer_reward: string; + bonus_proposer_reward: string; + withdraw_addr_enabled: boolean; + }; +}; diff --git a/api/src/types/rest/cosmosDistributionValidatorsCommissionResponse.ts b/api/src/types/rest/cosmosDistributionValidatorsCommissionResponse.ts new file mode 100644 index 000000000..ca6b463ac --- /dev/null +++ b/api/src/types/rest/cosmosDistributionValidatorsCommissionResponse.ts @@ -0,0 +1,5 @@ +export type CosmosDistributionValidatorsCommissionResponse = { + commission: { + commission: { denom: string; amount: string }[]; + }; +}; diff --git a/api/src/types/rest/cosmosMintInflationResponse.ts b/api/src/types/rest/cosmosMintInflationResponse.ts new file mode 100644 index 000000000..fa80257c3 --- /dev/null +++ b/api/src/types/rest/cosmosMintInflationResponse.ts @@ -0,0 +1,3 @@ +export type CosmosMintInflationResponse = { + inflation: string; +}; diff --git a/api/src/types/rest/cosmosStakingPoolResponse.ts b/api/src/types/rest/cosmosStakingPoolResponse.ts new file mode 100644 index 000000000..7e6815413 --- /dev/null +++ b/api/src/types/rest/cosmosStakingPoolResponse.ts @@ -0,0 +1,6 @@ +export type CosmosStakingPoolResponse = { + pool: { + not_bonded_tokens: string; + bonded_tokens: string; + }; +}; diff --git a/api/src/utils/map/provider.ts b/api/src/utils/map/provider.ts index fde8321f3..353db4479 100644 --- a/api/src/utils/map/provider.ts +++ b/api/src/utils/map/provider.ts @@ -94,18 +94,18 @@ export const getProviderAttributeValue = ( switch (providerAttributeSchema[key].type) { case "string": - values = + return ( provider.providerAttributes .filter((x) => x.key === _key) .map((x) => x.value) - .join(",") || null; - return values; + .join(",") || null + ); case "number": values = provider.providerAttributes .filter((x) => x.key === _key) .map((x) => x.value) - .join(",") || 0; + .join(",") || "0"; return parseFloat(values); case "boolean": values = diff --git a/api/src/utils/templateReposLogos.ts b/api/src/utils/templateReposLogos.ts index 8524be58c..c164b3cd0 100644 --- a/api/src/utils/templateReposLogos.ts +++ b/api/src/utils/templateReposLogos.ts @@ -3,7 +3,7 @@ export function getLogoFromPath(path: string) { } const logoBaseUrl = "https://storage.googleapis.com/akashlytics-deploy-public/template_logos/"; -const logos = { +const logos: { [key: string]: string } = { "speedtest-cli": "speedtest-by-ookla.jpg", fast: "fast.svg", geekbench: "geekbench.png", From d786e25a209a8644ab20e0207535c7e05ce2dc8a Mon Sep 17 00:00:00 2001 From: Redm4x <2829180+Redm4x@users.noreply.github.com> Date: Tue, 19 Mar 2024 02:37:32 -0400 Subject: [PATCH 2/7] Remove unused proposal code in deploy-web --- deploy-web/src/queries/useProposalsQuery.ts | 14 --------- deploy-web/src/types/index.ts | 1 - deploy-web/src/types/proposal.ts | 35 --------------------- 3 files changed, 50 deletions(-) delete mode 100644 deploy-web/src/queries/useProposalsQuery.ts delete mode 100644 deploy-web/src/types/proposal.ts diff --git a/deploy-web/src/queries/useProposalsQuery.ts b/deploy-web/src/queries/useProposalsQuery.ts deleted file mode 100644 index c085a1c87..000000000 --- a/deploy-web/src/queries/useProposalsQuery.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { UseQueryOptions, useQuery, QueryKey } from "react-query"; -import axios from "axios"; -import { QueryKeys } from "./queryKeys"; -import { ProposalSummary } from "@src/types/proposal"; -import { ApiUrlService } from "@src/utils/apiUtils"; - -async function getProposals(): Promise { - const response = await axios.get(ApiUrlService.proposals()); - return response.data; -} - -export function useProposals(options?: Omit, "queryKey" | "queryFn">) { - return useQuery(QueryKeys.getProposalsKey(), () => getProposals(), options); -} diff --git a/deploy-web/src/types/index.ts b/deploy-web/src/types/index.ts index aa9475f77..f4e256a30 100644 --- a/deploy-web/src/types/index.ts +++ b/deploy-web/src/types/index.ts @@ -4,7 +4,6 @@ export * from "./transaction"; export * from "./coin"; export * from "./address"; export * from "./snapshots"; -export * from "./proposal"; export * from "./sdlBuilder"; export * from "./billing"; export * from "./templates"; diff --git a/deploy-web/src/types/proposal.ts b/deploy-web/src/types/proposal.ts deleted file mode 100644 index fe0ed5863..000000000 --- a/deploy-web/src/types/proposal.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { IValidatorAddess } from "./validator"; - -export interface ProposalSummary { - id: number; - title: string; - status: string; - submitTime: string; - votingStartTime: string; - votingEndTime: string; - totalDeposit: number; -} - -export interface ProposalDetail { - id: number; - title: string; - proposer: IValidatorAddess; - description: string; - status: string; - submitTime: string; - votingStartTime: string; - votingEndTime: string; - totalDeposit: number; - tally: { - yes: number; - abstain: number; - no: number; - noWithVeto: number; - total: number; - }; - paramChanges: { - subspace: string; - key: string; - value: any; - }[]; -} From 0a188e6c17a9b5ef1dd3cc37f1367ec5c9aa5e07 Mon Sep 17 00:00:00 2001 From: Redm4x <2829180+Redm4x@users.noreply.github.com> Date: Tue, 19 Mar 2024 02:38:09 -0400 Subject: [PATCH 3/7] Enable noImplicitAny in tsconfig --- api/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/tsconfig.json b/api/tsconfig.json index 0d209c16f..a63492999 100644 --- a/api/tsconfig.json +++ b/api/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "module": "commonjs", - "noImplicitAny": false, + "noImplicitAny": true, "noEmitOnError": false, "removeComments": false, "sourceMap": true, From e32695f412720921f3b712d4500a3d6f4692c82e Mon Sep 17 00:00:00 2001 From: Redm4x <2829180+Redm4x@users.noreply.github.com> Date: Tue, 19 Mar 2024 02:45:53 -0400 Subject: [PATCH 4/7] Fix eslint errors --- api/src/caching/memoryCacheEngine.ts | 16 ++++++++-------- api/src/services/db/statsService.ts | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api/src/caching/memoryCacheEngine.ts b/api/src/caching/memoryCacheEngine.ts index 81177ecdf..21ec19551 100644 --- a/api/src/caching/memoryCacheEngine.ts +++ b/api/src/caching/memoryCacheEngine.ts @@ -5,13 +5,13 @@ export default class MemoryCacheEngine { * Used to retrieve data from memcache * @param {*} key */ - getFromCache = (key: string) => { + getFromCache(key: string) { const cachedBody = mcache.get(key); if (cachedBody) { return cachedBody; } return false; - }; + } /** * Used to store data in a memcache @@ -19,20 +19,20 @@ export default class MemoryCacheEngine { * @param {*} data * @param {*} duration */ - storeInCache = (key: string, data: any, duration?: number) => { + storeInCache(key: string, data: T, duration?: number) { mcache.put(key, data, duration); - }; + } /** * Used to delete all keys in a memcache */ - clearAllKeyInCache = () => { + clearAllKeyInCache() { mcache.clear(); - }; + } /** * Used to delete specific key from memcache * @param {*} key */ - clearKeyInCache = (key: string) => { + clearKeyInCache(key: string) { mcache.del(key); - }; + } } diff --git a/api/src/services/db/statsService.ts b/api/src/services/db/statsService.ts index 8f572228b..6ef437ec4 100644 --- a/api/src/services/db/statsService.ts +++ b/api/src/services/db/statsService.ts @@ -93,8 +93,8 @@ export const AuthorizedGraphDataNames = [ type AuthorizedGraphDataName = (typeof AuthorizedGraphDataNames)[number]; -export function isValidGraphDataName(x: any): x is AuthorizedGraphDataName { - return AuthorizedGraphDataNames.includes(x); +export function isValidGraphDataName(x: string): x is AuthorizedGraphDataName { + return AuthorizedGraphDataNames.includes(x as AuthorizedGraphDataName); } export async function getGraphData(dataName: AuthorizedGraphDataName): Promise { From 4f256155dc83c2577a405411956b19765c581415 Mon Sep 17 00:00:00 2001 From: Redm4x <2829180+Redm4x@users.noreply.github.com> Date: Tue, 19 Mar 2024 03:15:09 -0400 Subject: [PATCH 5/7] Add missing typing for axios calls --- api/src/routes/v1/nodes/mainnet.ts | 4 +++- api/src/routes/v1/nodes/sandbox.ts | 4 +++- api/src/routes/v1/nodes/testnet.ts | 4 +++- api/src/routes/v1/version/mainnet.ts | 2 +- api/src/routes/v1/version/sandbox.ts | 2 +- api/src/routes/v1/version/testnet.ts | 2 +- api/src/services/external/githubService.ts | 8 ++++---- api/src/services/external/marketDataService.ts | 13 +++++++------ api/src/types/coingeckoCoinsResponse.ts | 13 +++++++++++++ 9 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 api/src/types/coingeckoCoinsResponse.ts diff --git a/api/src/routes/v1/nodes/mainnet.ts b/api/src/routes/v1/nodes/mainnet.ts index fb6d72c86..6aa920a56 100644 --- a/api/src/routes/v1/nodes/mainnet.ts +++ b/api/src/routes/v1/nodes/mainnet.ts @@ -27,7 +27,9 @@ const route = createRoute({ export default new OpenAPIHono().openapi(route, async (c) => { const response = await cacheResponse(60 * 2, cacheKeys.getMainnetNodes, async () => { - const res = await axios.get("https://raw.githubusercontent.com/akash-network/cloudmos/main/config/mainnet-nodes.json"); //TODO: Add typing + const res = await axios.get<{ id: string; api: string; rpc: string }[]>( + "https://raw.githubusercontent.com/akash-network/cloudmos/main/config/mainnet-nodes.json" + ); return res.data; }); return c.json(response); diff --git a/api/src/routes/v1/nodes/sandbox.ts b/api/src/routes/v1/nodes/sandbox.ts index d092b55d9..610600c3d 100644 --- a/api/src/routes/v1/nodes/sandbox.ts +++ b/api/src/routes/v1/nodes/sandbox.ts @@ -27,7 +27,9 @@ const route = createRoute({ export default new OpenAPIHono().openapi(route, async (c) => { const response = await cacheResponse(60 * 2, cacheKeys.getSandboxNodes, async () => { - const res = await axios.get("https://raw.githubusercontent.com/akash-network/cloudmos/main/config/sandbox-nodes.json"); + const res = await axios.get<{ id: string; api: string; rpc: string }[]>( + "https://raw.githubusercontent.com/akash-network/cloudmos/main/config/sandbox-nodes.json" + ); return res.data; }); return c.json(response); diff --git a/api/src/routes/v1/nodes/testnet.ts b/api/src/routes/v1/nodes/testnet.ts index b63fe8cb4..d9cc58131 100644 --- a/api/src/routes/v1/nodes/testnet.ts +++ b/api/src/routes/v1/nodes/testnet.ts @@ -27,7 +27,9 @@ const route = createRoute({ export default new OpenAPIHono().openapi(route, async (c) => { const response = await cacheResponse(60 * 2, cacheKeys.getTestnetNodes, async () => { - const res = await axios.get("https://raw.githubusercontent.com/akash-network/cloudmos/main/config/testnet-nodes.json"); + const res = await axios.get<{ id: string; api: string; rpc: string }[]>( + "https://raw.githubusercontent.com/akash-network/cloudmos/main/config/testnet-nodes.json" + ); return res.data; }); return c.json(response); diff --git a/api/src/routes/v1/version/mainnet.ts b/api/src/routes/v1/version/mainnet.ts index fc801030b..9c5f1ae5f 100644 --- a/api/src/routes/v1/version/mainnet.ts +++ b/api/src/routes/v1/version/mainnet.ts @@ -18,7 +18,7 @@ const route = createRoute({ export default new OpenAPIHono().openapi(route, async (c) => { const response = await cacheResponse(60 * 5, cacheKeys.getMainnetVersion, async () => { - const res = await axios.get("https://raw.githubusercontent.com/akash-network/net/master/mainnet/version.txt"); + const res = await axios.get("https://raw.githubusercontent.com/akash-network/net/master/mainnet/version.txt"); return res.data; }); return c.text(response); diff --git a/api/src/routes/v1/version/sandbox.ts b/api/src/routes/v1/version/sandbox.ts index 7861cba5b..2d32742e5 100644 --- a/api/src/routes/v1/version/sandbox.ts +++ b/api/src/routes/v1/version/sandbox.ts @@ -18,7 +18,7 @@ const route = createRoute({ export default new OpenAPIHono().openapi(route, async (c) => { const response = await cacheResponse(60 * 5, cacheKeys.getSandboxVersion, async () => { - const res = await axios.get("https://raw.githubusercontent.com/akash-network/net/master/sandbox/version.txt"); + const res = await axios.get("https://raw.githubusercontent.com/akash-network/net/master/sandbox/version.txt"); return res.data; }); return c.text(response); diff --git a/api/src/routes/v1/version/testnet.ts b/api/src/routes/v1/version/testnet.ts index 46a4e04b7..c51f0e167 100644 --- a/api/src/routes/v1/version/testnet.ts +++ b/api/src/routes/v1/version/testnet.ts @@ -18,7 +18,7 @@ const route = createRoute({ export default new OpenAPIHono().openapi(route, async (c) => { const response = await cacheResponse(60 * 5, cacheKeys.getTestnetVersion, async () => { - const res = await axios.get("https://raw.githubusercontent.com/akash-network/net/master/testnet-02/version.txt"); + const res = await axios.get("https://raw.githubusercontent.com/akash-network/net/master/testnet-02/version.txt"); return res.data; }); return c.text(response); diff --git a/api/src/services/external/githubService.ts b/api/src/services/external/githubService.ts index 3488de2f0..9aeeab818 100644 --- a/api/src/services/external/githubService.ts +++ b/api/src/services/external/githubService.ts @@ -1,6 +1,6 @@ import { Octokit } from "@octokit/rest"; import { cacheKeys, cacheResponse } from "@src/caching/helpers"; -import { ProviderAttributesSchema } from "@src/types/provider"; +import { Auditor, ProviderAttributesSchema } from "@src/types/provider"; import { env } from "@src/utils/env"; import axios from "axios"; @@ -23,7 +23,7 @@ export const getProviderAttributesSchema = async (): Promise await axios.get("https://raw.githubusercontent.com/akash-network/cloudmos/main/config/provider-attributes.json") + async () => await axios.get("https://raw.githubusercontent.com/akash-network/cloudmos/main/config/provider-attributes.json") ); return response.data; @@ -31,9 +31,9 @@ export const getProviderAttributesSchema = async (): Promise { - const res = await axios.get("https://raw.githubusercontent.com/akash-network/cloudmos/main/config/auditors.json"); + const res = await axios.get("https://raw.githubusercontent.com/akash-network/cloudmos/main/config/auditors.json"); return res.data; }); return response; -} \ No newline at end of file +} diff --git a/api/src/services/external/marketDataService.ts b/api/src/services/external/marketDataService.ts index 719d5eed5..484c5933c 100644 --- a/api/src/services/external/marketDataService.ts +++ b/api/src/services/external/marketDataService.ts @@ -1,3 +1,4 @@ +import { CoinGeckoCoinsResponse } from "@src/types/coingeckoCoinsResponse"; import axios from "axios"; interface AktMarketData { @@ -13,14 +14,14 @@ export async function getMarketData(): Promise { const endpointUrl = "https://api.coingecko.com/api/v3/coins/akash-network"; // TODO USDC https://api.coingecko.com/api/v3/coins/usd-coin console.log("Fetching latest market data from " + endpointUrl); - const response = await axios.get(endpointUrl); + const response = await axios.get(endpointUrl); return { - price: parseFloat(response.data.market_data.current_price.usd), - volume: parseInt(response.data.market_data.total_volume.usd), - marketCap: parseInt(response.data.market_data.market_cap.usd), + price: response.data.market_data.current_price.usd, + volume: response.data.market_data.total_volume.usd, + marketCap: response.data.market_data.market_cap.usd, marketCapRank: response.data.market_cap_rank, - priceChange24h: parseFloat(response.data.market_data.price_change_24h), - priceChangePercentage24: parseFloat(response.data.market_data.price_change_percentage_24h) + priceChange24h: response.data.market_data.price_change_24h, + priceChangePercentage24: response.data.market_data.price_change_percentage_24h }; } diff --git a/api/src/types/coingeckoCoinsResponse.ts b/api/src/types/coingeckoCoinsResponse.ts new file mode 100644 index 000000000..d8f30282a --- /dev/null +++ b/api/src/types/coingeckoCoinsResponse.ts @@ -0,0 +1,13 @@ +export type CoinGeckoCoinsResponse = { + id: string; + symbol: string; + name: string; + market_cap_rank: number; + market_data: { + current_price: { usd: number }; + total_volume: { usd: number }; + market_cap: { usd: number }; + price_change_24h: number; + price_change_percentage_24h: number; + }; +}; From 580d1eda0b847042c9e196d72b33f796e605222c Mon Sep 17 00:00:00 2001 From: Redm4x <2829180+Redm4x@users.noreply.github.com> Date: Tue, 19 Mar 2024 03:33:06 -0400 Subject: [PATCH 6/7] Remove eslint-disable-next-line --- api/src/services/external/templateReposService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/api/src/services/external/templateReposService.ts b/api/src/services/external/templateReposService.ts index 30cef871b..58099a9c0 100644 --- a/api/src/services/external/templateReposService.ts +++ b/api/src/services/external/templateReposService.ts @@ -50,7 +50,6 @@ type TemplateSource = { logoUrl?: string; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any async function getTemplatesFromRepo( octokit: Octokit, repoOwner: string, From fb9f5deebc646732a35f3568689d75f3931bb703 Mon Sep 17 00:00:00 2001 From: Redm4x <2829180+Redm4x@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:02:56 -0400 Subject: [PATCH 7/7] PR Fixes --- api/src/db/dbConnection.ts | 8 ++++++-- api/src/routes/v1/graphData.ts | 2 +- api/src/services/db/statsService.ts | 21 +++++++++++++++++---- indexer/src/indexers/akashStatsIndexer.ts | 3 +-- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/api/src/db/dbConnection.ts b/api/src/db/dbConnection.ts index 0cd8abed3..f3f9796cd 100644 --- a/api/src/db/dbConnection.ts +++ b/api/src/db/dbConnection.ts @@ -6,13 +6,17 @@ import { chainModels, getChainModels, userModels } from "@shared/dbSchemas"; import { Template, TemplateFavorite, UserAddressName, UserSetting } from "@shared/dbSchemas/user"; import { chainDefinitions } from "@shared/chainDefinitions"; -const csMap: { [key: string]: string } = { +function isValidNetwork(network: string): network is keyof typeof csMap { + return network in csMap; +} + +const csMap = { mainnet: env.AkashDatabaseCS, testnet: env.AkashTestnetDatabaseCS, sandbox: env.AkashSandboxDatabaseCS }; -if (!(env.Network in csMap)) { +if (!isValidNetwork(env.Network)) { throw new Error(`Invalid network: ${env.Network}`); } diff --git a/api/src/routes/v1/graphData.ts b/api/src/routes/v1/graphData.ts index fbeb90f43..51e63da42 100644 --- a/api/src/routes/v1/graphData.ts +++ b/api/src/routes/v1/graphData.ts @@ -7,7 +7,7 @@ const route = createRoute({ tags: ["Analytics"], request: { params: z.object({ - dataName: z.string().openapi({ example: "dailyUAktSpent", enum: Array.from(AuthorizedGraphDataNames) }) + dataName: z.string().openapi({ example: "dailyUAktSpent", enum: AuthorizedGraphDataNames }) }) }, responses: { diff --git a/api/src/services/db/statsService.ts b/api/src/services/db/statsService.ts index 6ef437ec4..71d09c5f1 100644 --- a/api/src/services/db/statsService.ts +++ b/api/src/services/db/statsService.ts @@ -75,7 +75,22 @@ export const getDashboardData = async () => { }; }; -export const AuthorizedGraphDataNames = [ +type AuthorizedGraphDataName = + | "dailyUAktSpent" + | "dailyUUsdcSpent" + | "dailyUUsdSpent" + | "dailyLeaseCount" + | "totalUAktSpent" + | "totalUUsdcSpent" + | "totalUUsdSpent" + | "activeLeaseCount" + | "totalLeaseCount" + | "activeCPU" + | "activeGPU" + | "activeMemory" + | "activeStorage"; + +export const AuthorizedGraphDataNames: AuthorizedGraphDataName[] = [ "dailyUAktSpent", "dailyUUsdcSpent", "dailyUUsdSpent", @@ -89,9 +104,7 @@ export const AuthorizedGraphDataNames = [ "activeGPU", "activeMemory", "activeStorage" -] as const; - -type AuthorizedGraphDataName = (typeof AuthorizedGraphDataNames)[number]; +]; export function isValidGraphDataName(x: string): x is AuthorizedGraphDataName { return AuthorizedGraphDataNames.includes(x as AuthorizedGraphDataName); diff --git a/indexer/src/indexers/akashStatsIndexer.ts b/indexer/src/indexers/akashStatsIndexer.ts index 1725fd895..06000be86 100644 --- a/indexer/src/indexers/akashStatsIndexer.ts +++ b/indexer/src/indexers/akashStatsIndexer.ts @@ -23,8 +23,7 @@ import { ProviderSnapshotNodeGPU } from "@shared/dbSchemas/akash"; import { AkashBlock as Block, AkashMessage as Message } from "@shared/dbSchemas/akash"; -import { Op, Transaction as DbTransaction, QueryTypes } from "sequelize"; -import { sequelize } from "@src/db/dbConnection"; +import { Op, Transaction as DbTransaction } from "sequelize"; class ITotalResources { count: number;