diff --git a/apps/api/env/.env.functional.test b/apps/api/env/.env.functional.test index 9c441a76a..060a5554f 100644 --- a/apps/api/env/.env.functional.test +++ b/apps/api/env/.env.functional.test @@ -1,5 +1,4 @@ -AKASH_SANDBOX_DATABASE_CS=postgres://postgres:password@localhost:5432/console-akash-sandbox -USER_DATABASE_CS=postgres://postgres:password@localhost:5432/console-users +CHAIN_INDEXER_POSTGRES_DB_URI=postgres://postgres:password@localhost:5432/console-akash-sandbox POSTGRES_DB_URI=postgres://postgres:password@localhost:5432/console-users MASTER_WALLET_MNEMONIC="motion isolate mother convince snack twenty tumble boost elbow bundle modify balcony" UAKT_TOP_UP_MASTER_WALLET_MNEMONIC="since bread kind field rookie stairs elephant tent horror rice gain tongue collect goose rural garment cover client biology toe ability boat afford mind" @@ -23,4 +22,6 @@ ALLOWED_CHECKOUT_REFERRERS=["http://localhost:3000"] STRIPE_CHECKOUT_REDIRECT_URL=http://localhost:3000 AUTH0_M2M_DOMAIN=AUTH0_M2M_DOMAIN AUTH0_M2M_SECRET=AUTH0_SECRET -AUTH0_M2M_CLIENT_ID=AUTH0_CLIENT_ID \ No newline at end of file +AUTH0_M2M_CLIENT_ID=AUTH0_CLIENT_ID +STD_OUT_LOG_FORMAT=pretty +SQL_LOG_FORMAT=pretty \ No newline at end of file diff --git a/apps/api/env/.env.local.sample b/apps/api/env/.env.local.sample index 2a0f14599..65252a7cb 100644 --- a/apps/api/env/.env.local.sample +++ b/apps/api/env/.env.local.sample @@ -1,8 +1,6 @@ NETWORK=sandbox DB_HOST_WITH_DEFAULT=${DB_HOST:-localhost} -AKASH_DATABASE_CS=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-akash-sandbox -AKASH_SANDBOX_DATABASE_CS=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-akash-sandbox -USER_DATABASE_CS=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-users +CHAIN_INDEXER_POSTGRES_DB_URI=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-akash-sandbox POSTGRES_DB_URI=postgres://postgres:password@${DB_HOST_WITH_DEFAULT}:5432/console-users ANONYMOUS_USER_TOKEN_SECRET=ANONYMOUS_USER_TOKEN_SECRET MASTER_WALLET_MNEMONIC=MASTER_WALLET_MNEMONIC diff --git a/apps/api/env/.env.sample b/apps/api/env/.env.sample index e7ed98cb2..df72596f9 100644 --- a/apps/api/env/.env.sample +++ b/apps/api/env/.env.sample @@ -1,15 +1,14 @@ # Secrets -AKASH_DATABASE_CS= +POSTGRES_DB_URI= +CHAIN_INDEXER_POSTGRES_DB_URI= GITHUB_PAT= ANONYMOUS_USER_TOKEN_SECRET= HealthChecks_SyncAKTMarketData= MASTER_WALLET_MNEMONIC= -POSTGRES_DB_URI= SECRET_TOKEN= SENTRY_DSN= STRIPE_SECRET_KEY= STRIPE_PRODUCT_ID= -USER_DATABASE_CS= # Configuration CORS_WEBSITE_URLS= diff --git a/apps/api/env/.env.unit.test b/apps/api/env/.env.unit.test index 1abebe90f..20c1a9062 100644 --- a/apps/api/env/.env.unit.test +++ b/apps/api/env/.env.unit.test @@ -1,5 +1,4 @@ -AKASH_SANDBOX_DATABASE_CS=postgres://postgres:password@localhost:5432/console-akash-sandbox -USER_DATABASE_CS=postgres://postgres:password@localhost:5432/console-users +CHAIN_INDEXER_POSTGRES_DB_URI=postgres://postgres:password@localhost:5432/console-akash-sandbox POSTGRES_DB_URI=postgres://postgres:password@localhost:5432/console-users MASTER_WALLET_MNEMONIC="motion isolate mother convince snack twenty tumble boost elbow bundle modify balcony" UAKT_TOP_UP_MASTER_WALLET_MNEMONIC="since bread kind field rookie stairs elephant tent horror rice gain tongue collect goose rural garment cover client biology toe ability boat afford mind" diff --git a/apps/api/jest.config.js b/apps/api/jest.config.js index ebaac8ad9..cf4b99b15 100644 --- a/apps/api/jest.config.js +++ b/apps/api/jest.config.js @@ -5,7 +5,7 @@ const MAP_ALIASES = { const common = { transform: { - "^.+\\.(t|j)s$": ["ts-jest", { tsconfig: "./tsconfig.json" }] + "^.+\\.(t|j)s$": ["ts-jest", { tsconfig: "./test/tsconfig.json" }] }, rootDir: ".", moduleNameMapper: { diff --git a/apps/api/src/chain/config/env.config.ts b/apps/api/src/chain/config/env.config.ts new file mode 100644 index 000000000..ee2b04216 --- /dev/null +++ b/apps/api/src/chain/config/env.config.ts @@ -0,0 +1,5 @@ +import { z } from "zod"; + +export const envSchema = z.object({ + CHAIN_INDEXER_POSTGRES_DB_URI: z.string() +}); diff --git a/apps/api/src/chain/services/chain-config/chain-config.service.ts b/apps/api/src/chain/services/chain-config/chain-config.service.ts new file mode 100644 index 000000000..fd5bc7763 --- /dev/null +++ b/apps/api/src/chain/services/chain-config/chain-config.service.ts @@ -0,0 +1,11 @@ +import { singleton } from "tsyringe"; + +import { envSchema } from "@src/chain/config/env.config"; +import { ConfigService } from "@src/core/services/config/config.service"; + +@singleton() +export class ChainConfigService extends ConfigService { + constructor() { + super({ envSchema }); + } +} diff --git a/apps/api/src/core/config/env.config.ts b/apps/api/src/core/config/env.config.ts index 58d3b8395..0ea37a5bc 100644 --- a/apps/api/src/core/config/env.config.ts +++ b/apps/api/src/core/config/env.config.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -const envSchema = z.object({ +export const envSchema = z.object({ LOG_LEVEL: z.enum(["fatal", "error", "warn", "info", "debug", "trace"]).optional().default("info"), STD_OUT_LOG_FORMAT: z.enum(["json", "pretty"]).optional().default("json"), SQL_LOG_FORMAT: z.enum(["raw", "pretty"]).optional().default("raw"), diff --git a/apps/api/src/core/services/core-config/core-config.service.ts b/apps/api/src/core/services/core-config/core-config.service.ts new file mode 100644 index 000000000..21b5adb42 --- /dev/null +++ b/apps/api/src/core/services/core-config/core-config.service.ts @@ -0,0 +1,11 @@ +import { singleton } from "tsyringe"; + +import { envSchema } from "@src/core/config/env.config"; +import { ConfigService } from "@src/core/services/config/config.service"; + +@singleton() +export class CoreConfigService extends ConfigService { + constructor() { + super({ envSchema }); + } +} diff --git a/apps/api/src/db/dbConnection.ts b/apps/api/src/db/dbConnection.ts index be9581578..5ce25d29d 100644 --- a/apps/api/src/db/dbConnection.ts +++ b/apps/api/src/db/dbConnection.ts @@ -1,37 +1,23 @@ -import { chainDefinitions } from "@akashnetwork/database/chainDefinitions"; -import { chainModels, getChainModels, userModels } from "@akashnetwork/database/dbSchemas"; +import { chainModels, userModels } from "@akashnetwork/database/dbSchemas"; import { Template, TemplateFavorite, UserSetting } from "@akashnetwork/database/dbSchemas/user"; import pg from "pg"; import { Transaction as DbTransaction } from "sequelize"; import { Sequelize } from "sequelize-typescript"; +import { container } from "tsyringe"; -import { config } from "@src/core/config"; +import { ChainConfigService } from "@src/chain/services/chain-config/chain-config.service"; +import { CoreConfigService } from "@src/core/services/core-config/core-config.service"; import { PostgresLoggerService } from "@src/core/services/postgres-logger/postgres-logger.service"; -import { env } from "@src/utils/env"; -function isValidNetwork(network: string): network is keyof typeof csMap { - return network in csMap; -} - -const csMap = { - mainnet: env.AKASH_DATABASE_CS, - testnet: env.AKASH_TESTNET_DATABASE_CS, - sandbox: env.AKASH_SANDBOX_DATABASE_CS -}; - -if (!isValidNetwork(env.NETWORK)) { - throw new Error(`Invalid network: ${env.NETWORK}`); -} +const indexerDbUri = container.resolve(ChainConfigService).get("CHAIN_INDEXER_POSTGRES_DB_URI"); +const coreConfig = container.resolve(CoreConfigService); +const dbUri = coreConfig.get("POSTGRES_DB_URI"); -if (!csMap[env.NETWORK]) { - throw new Error(`Missing connection string for network: ${env.NETWORK}`); -} - -const logger = new PostgresLoggerService({ orm: "sequelize", useFormat: config.SQL_LOG_FORMAT === "pretty" }); +const logger = new PostgresLoggerService({ orm: "sequelize", useFormat: coreConfig.get("SQL_LOG_FORMAT") === "pretty" }); const logging = (msg: string) => logger.write(msg); pg.defaults.parseInt8 = true; -export const chainDb = new Sequelize(csMap[env.NETWORK], { +export const chainDb = new Sequelize(indexerDbUri, { dialectModule: pg, logging, logQueryParameters: true, @@ -43,28 +29,7 @@ export const chainDb = new Sequelize(csMap[env.NETWORK], { models: chainModels }); -export const chainDbs: { [key: string]: Sequelize } = Object.keys(chainDefinitions) - .filter(x => chainDefinitions[x].connectionString) - .reduce( - (obj, chain) => ({ - ...obj, - [chain]: new Sequelize(chainDefinitions[chain].connectionString, { - dialectModule: pg, - logging, - logQueryParameters: true, - repositoryMode: true, - transactionType: DbTransaction.TYPES.IMMEDIATE, - define: { - timestamps: false, - freezeTableName: true - }, - models: getChainModels(chain) - }) - }), - {} - ); - -export const userDb = new Sequelize(env.USER_DATABASE_CS, { +export const userDb = new Sequelize(dbUri, { dialectModule: pg, logging, logQueryParameters: true, @@ -82,4 +47,4 @@ export async function syncUserSchema() { await TemplateFavorite.sync(); } -export const closeConnections = async () => await Promise.all([chainDb.close(), userDb.close(), ...Object.values(chainDbs).map(db => db.close())]); +export const closeConnections = async () => await Promise.all([chainDb.close(), userDb.close()]); diff --git a/apps/api/src/utils/env.ts b/apps/api/src/utils/env.ts index 4e5cccafd..64d212d0f 100644 --- a/apps/api/src/utils/env.ts +++ b/apps/api/src/utils/env.ts @@ -5,10 +5,7 @@ export const env = z CORS_WEBSITE_URLS: z.string().optional(), NODE_ENV: z.string().optional(), HEALTHCHECKS_ENABLED: z.string().optional(), - AKASH_DATABASE_CS: z.string().optional(), - AKASH_TESTNET_DATABASE_CS: z.string().optional(), - AKASH_SANDBOX_DATABASE_CS: z.string().optional(), - USER_DATABASE_CS: z.string().optional(), + CHAIN_INDEXER_POSTGRES_DB_URI: z.string(), NETWORK: z.string().default("mainnet"), REST_API_NODE_URL: z.string().optional(), SERVER_ORIGIN: z.string().optional().default("http://localhost:3080"), diff --git a/packages/database/chainDefinitions.ts b/packages/database/chainDefinitions.ts index 7de18e66e..3879b1dbf 100644 --- a/packages/database/chainDefinitions.ts +++ b/packages/database/chainDefinitions.ts @@ -149,263 +149,6 @@ export const chainDefinitions: { [key: string]: ChainDef } = { ProviderSnapshotNodeGPU, ProviderSnapshotStorage ] - }, - passage: { - code: "passage", - rpcNodes: [ - "https://rpc-passage.ecostake.com", - "https://rpc-passage-ia.cosmosia.notional.ventures", - "https://services.staketab.com/passage-rpc", - "https://passage-rpc.panthea.eu", - "https://passage-rpc.polkachu.com", - "https://rpc.passage.vitwit.com" - ], - cosmosDirectoryId: "passage", - connectionString: process.env.PassageDatabaseCS, - genesisFileUrl: "https://raw.githubusercontent.com/envadiv/mainnet/main/passage-1/genesis.json", - coinGeckoId: null, - customIndexers: [], - bech32Prefix: "pasg", - denom: "pasg", - udenom: "upasg" - }, - juno: { - code: "juno", - rpcNodes: [ - "https://rpc-juno.ecostake.com", - "https://rpc.juno.pupmos.network", - "https://rpc.juno.interbloc.org", - "https://rpc-juno.itastakers.com", - "https://juno-rpc.polkachu.com", - "https://juno-rpc.lavenderfive.com:443", - "https://rpc.juno.chaintools.tech", - "https://rpc-juno-ia.cosmosia.notional.ventures", - "https://rpc-juno.whispernode.com", - "https://juno-rpc.reece.sh" - ], - cosmosDirectoryId: "juno", - connectionString: process.env.JunoDatabaseCS, - genesisFileUrl: "https://raw.githubusercontent.com/CosmosContracts/mainnet/main/juno-1/genesis.json", - coinGeckoId: "juno-network", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/juno.svg", - logoUrlPNG: "https://console.akash.network/images/chains/juno.png", - customIndexers: [], - bech32Prefix: "juno", - denom: "juno", - udenom: "ujuno", - startHeight: 9_426_289 - }, - cosmos: { - code: "cosmos", - rpcNodes: [ - "https://rpc-cosmoshub.ecostake.com", - "https://rpc-cosmoshub.goldenratiostaking.net", - "https://cosmoshub-rpc.lavenderfive.com:443", - "https://rpc.cosmos.dragonstake.io", - "https://cosmos-rpc.icycro.org", - "https://cosmos-rpc.quickapi.com:443", - "https://cosmoshub.rpc.stakin.com", - "https://rpc-cosmoshub-ia.cosmosia.notional.ventures", - "https://rpc.cosmoshub.pupmos.network", - "https://cosmos-rpc.polkachu.com", - "https://rpc.cosmoshub.strange.love", - "https://cosmoshub.rpc.interchain.ivaldilabs.xyz", - "https://rpc.cosmos.silknodes.io", - "https://rpc.cosmos.network:443", - "https://rpc-cosmoshub.architectnodes.com", - "https://rpc-cosmoshub.blockapsis.com", - "https://rpc-cosmoshub.whispernode.com" - ], - cosmosDirectoryId: "cosmoshub", - connectionString: process.env.CosmosDatabaseCS, - genesisFileUrl: "https://raw.githubusercontent.com/cosmos/mainnet/master/genesis/genesis.cosmoshub-4.json.gz", - coinGeckoId: "cosmos", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/cosmoshub/images/atom.svg", - logoUrlPNG: "https://console.akash.network/images/chains/atom.png", - customIndexers: [], - bech32Prefix: "cosmos", - denom: "atom", - udenom: "uatom", - startHeight: 16_416_294 - }, - osmosis: { - code: "osmosis", - rpcNodes: [ - "https://rpc-osmosis-ia.cosmosia.notional.ventures", - "https://osmosis.rpc.stakin-nodes.com", - "https://rpc-osmosis.ecostake.com", - "https://rpc.osmosis.zone", - "https://osmosis-rpc.polkachu.com", - "https://osmosis-rpc.quickapi.com:443", - "https://osmosis-rpc.ibs.team", - "https://osmosis-rpc.lavenderfive.com:443", - "https://rpc-osmosis.blockapsis.com", - "https://rpc.osmosis.silknodes.io", - "https://osmosis.rpc.chandrastation.com:443" - ], - cosmosDirectoryId: "osmosis", - connectionString: process.env.OsmosisDatabaseCS, - genesisFileUrl: "https://github.com/osmosis-labs/networks/blob/main/osmosis-1/genesis.json", - coinGeckoId: "osmosis", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/osmo.svg", - logoUrlPNG: "https://console.akash.network/images/chains/osmo.png", - customIndexers: [], - bech32Prefix: "osmo", - denom: "osmo", - udenom: "uosmo", - startHeight: 10_817_394 - }, - stargaze: { - code: "stargaze", - rpcNodes: [ - "https://rpc.stargaze-apis.com", - "https://stargaze-rpc.polkachu.com", - "https://rpc-stargaze.pupmos.network", - "https://rpc-stargaze-ia.cosmosia.notional.ventures", - "https://rpc-stargaze.d-stake.xyz", - "https://rpc.stargaze.silentvalidator.com", - "https://stargaze-rpc.ibs.team" - ], - cosmosDirectoryId: "stargaze", - connectionString: process.env.StargazeDatabaseCS, - genesisFileUrl: "https://raw.githubusercontent.com/public-awesome/mainnet/main/stargaze-1/genesis.tar.gz", - coinGeckoId: "stargaze", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/stars.png", - logoUrlPNG: "https://console.akash.network/images/chains/stars.png", - customIndexers: [], - bech32Prefix: "stars", - denom: "stars", - udenom: "ustars", - startHeight: 9_401_277 - }, - secret: { - code: "secret", - rpcNodes: [ - "https://rpc.secret.forbole.com/", - "https://scrt-rpc.agoranodes.com", - "https://secretnetwork-rpc.stakely.io", - "https://rpc-secret.whispernode.com" - ], - cosmosDirectoryId: "secretnetwork", - connectionString: process.env.SecretDatabaseCS, - genesisFileUrl: "https://raw.githubusercontent.com/enigmampc/SecretNetwork/master/secret-testnet-genesis.json", - coinGeckoId: "secret", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/scrt.svg", - logoUrlPNG: "https://console.akash.network/images/chains/scrt.png", - customIndexers: [], - bech32Prefix: "secret", - denom: "scrt", - udenom: "uscrt", - startHeight: 10_024_705 - }, - evmos: { - code: "evmos", - rpcNodes: [ - "https://rpc.evmos.tcnetwork.io", - "https://tendermint.bd.evmos.org:26657", - "https://rpc.evmos.bh.rocks", - "https://rpc-evmos.ecostake.com", - "https://rpc.evmos.interbloc.org", - "https://rpc.evmos.nodestake.top", - "https://rpc-evmos.goldenratiostaking.net", - "https://rpc-evmos-ia.cosmosia.notional.ventures:443", - "https://rpc.evmos.silentvalidator.com/", - "https://evmos.rpc.stakin-nodes.com", - "https://rpc-evmos.architectnodes.com", - "https://rpc.evmos.chaintools.tech/", - "https://evmos-rpc.lavenderfive.com:443", - "https://rpc.evmos.silknodes.io/" - ], - cosmosDirectoryId: "evmos", - connectionString: process.env.EvmosDatabaseCS, - genesisFileUrl: "https://archive.evmos.org/mainnet/genesis.json", - coinGeckoId: "evmos", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/evmos/images/evmos.svg", - logoUrlPNG: "https://console.akash.network/images/chains/evmos.png", - customIndexers: [], - bech32Prefix: "evmos", - denom: "evmos", - udenom: "uevmos", - startHeight: 14_993_969 - }, - huahua: { - code: "huahua", - rpcNodes: [ - "https://rpc-chihuahua-ia.cosmosia.notional.ventures/", - "https://rpc-chihuahua.ecostake.com", - "https://rpc.chihuahua.wtf/", - "https://rpc.huahua.bh.rocks", - "https://chihuahua-rpc.polkachu.com", - "https://chihuahua-rpc.kleomedes.network", - "https://rpc-chihuahua.pupmos.network/" - ], - cosmosDirectoryId: "chihuahua", - connectionString: process.env.HuahuaDatabaseCS, - genesisFileUrl: "https://raw.githubusercontent.com/ChihuahuaChain/chihuahua/main/mainnet/genesis.json", - coinGeckoId: "chihuahua-chain", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/huahua.svg", - logoUrlPNG: "https://console.akash.network/images/chains/huahua.png", - customIndexers: [], - bech32Prefix: "chihuahua", - denom: "HUAHUA", - udenom: "uhuahua", - startHeight: 8_612_168 - }, - stride: { - code: "stride", - rpcNodes: [ - "https://stride.nodejumper.io:443", - "http://rpc-stride.nodeist.net", - "https://stride.rpc.kjnodes.com", - "https://rpc.stride.bh.rocks", - "https://stride-rpc.lavenderfive.com/", - "https://rpc.stride.silentvalidator.com/", - "https://stride-rpc.polkachu.com/", - "https://rpc-stride.pupmos.network", - "https://rpc-stride.architectnodes.com", - "https://stride.rpc.chandrastation.com", - "https://stride.rpc.interchain.ivaldilabs.xyz" - ], - cosmosDirectoryId: "stride", - connectionString: process.env.StrideDatabaseCS, - genesisFileUrl: "https://raw.githubusercontent.com/Stride-Labs/testnet/main/mainnet/genesis.json", - coinGeckoId: "stride", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/strd.svg", - logoUrlPNG: "https://console.akash.network/images/chains/strd.png", - customIndexers: [], - bech32Prefix: "stride", - denom: "STRD", - udenom: "ustrd", - startHeight: 4_823_860 - }, - kujira: { - code: "kujira", - rpcNodes: [ - "https://rpc-kujira.ecostake.com", - "https://rpc-kujira.nodeist.net", - "https://rpc-kujira.starsquid.io", - "https://rpc-kujira-ia.cosmosia.notional.ventures/", - "https://rpc.kujira.chaintools.tech/", - "https://kujira-rpc.ibs.team/", - "https://kujira.rpc.kjnodes.com", - "https://kuji-rpc.kleomedes.network", - "https://kujira-rpc.polkachu.com", - "https://kujira-rpc.wildsage.io", - // "https://rpc.kaiyo.kujira.setten.io", - "https://kujira-rpc.lavenderfive.com:443", - "https://rpc-kujira.whispernode.com" - ], - cosmosDirectoryId: "kujira", - connectionString: process.env.KujiraDatabaseCS, - genesisFileUrl: "https://raw.githubusercontent.com/Team-Kujira/networks/master/mainnet/kaiyo-1.json", - coinGeckoId: "kujira", - logoUrlSVG: "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/kuji.png", - logoUrlPNG: "https://console.akash.network/images/chains/kuji.png", - customIndexers: [], - bech32Prefix: "kujira", - denom: "KUJI", - udenom: "ukuji", - startHeight: 12_975_265 } };