From 20ebd93e176f4089bdfe8bdef5a3dd0d449467ed Mon Sep 17 00:00:00 2001 From: Yaroslav Grishajev Date: Thu, 5 Sep 2024 14:07:44 +0200 Subject: [PATCH] feat(env): implement unified file loading in console-web refs #313 --- .dockerignore | 1 - .gitignore | 1 - apps/deploy-web/.gitignore | 2 + apps/deploy-web/README.md | 48 ++-- apps/deploy-web/env.config.js | 26 --- apps/deploy-web/env/.env | 2 + apps/deploy-web/env/.env.production | 17 ++ apps/deploy-web/env/.env.sample | 22 ++ apps/deploy-web/env/.env.staging | 16 ++ apps/deploy-web/next.config.js | 19 +- apps/deploy-web/package.json | 5 +- .../authorizations/AllowanceModal.tsx | 8 +- .../components/authorizations/GrantModal.tsx | 6 +- .../deployments/DeploymentDepositModal.tsx | 4 +- .../deployments/DeploymentDetail.tsx | 4 +- .../deployments/DeploymentLeaseShell.tsx | 4 +- .../components/deployments/DeploymentLogs.tsx | 4 +- .../get-started/GetStartedStepper.tsx | 12 +- .../deploy-web/src/components/graph/Graph.tsx | 8 +- .../src/components/home/HomeContainer.tsx | 1 - .../src/components/home/YourAccount.tsx | 25 ++- .../layout/CustomGoogleAnalytics.tsx | 4 +- .../src/components/layout/Layout.tsx | 4 +- apps/deploy-web/src/components/layout/Nav.tsx | 4 +- .../src/components/layout/Sidebar.tsx | 8 +- .../src/components/layout/WalletStatus.tsx | 4 +- .../components/new-deployment/BidGroup.tsx | 4 +- .../components/new-deployment/CreateLease.tsx | 4 +- .../new-deployment/ManifestEdit.tsx | 14 +- .../new-deployment/NewDeploymentContainer.tsx | 12 +- .../src/components/new-deployment/Stepper.tsx | 4 +- .../new-deployment/TemplateList.tsx | 10 +- .../providers/ActiveLeasesGraph.tsx | 4 +- .../src/components/sdl/PlacementFormModal.tsx | 6 +- .../src/components/sdl/RentGpusForm.tsx | 10 +- .../components/sdl/SimpleSdlBuilderForm.tsx | 4 +- .../sdl/SimpleServiceFormControl.tsx | 4 +- .../settings/SelectNetworkModal.tsx | 6 +- .../components/shared/DynamicMonacoEditor.tsx | 20 +- .../src/components/shared/TimeRange.tsx | 14 +- .../components/templates/TemplateDetail.tsx | 4 +- .../src/components/templates/UserTemplate.tsx | 4 +- .../src/components/user/UserProviders.tsx | 4 +- apps/deploy-web/src/config/auth.config.ts | 2 + .../src/config/browser-env.config.ts | 18 ++ apps/deploy-web/src/config/denom.config.ts | 18 ++ .../src/config/env-config.schema.ts | 38 ++++ apps/deploy-web/src/config/env.config.ts | 2 - apps/deploy-web/src/config/graph.config.ts | 5 + apps/deploy-web/src/config/network.config.ts | 5 + .../src/config/server-env.config.ts | 5 + apps/deploy-web/src/config/tx.config.ts | 1 + apps/deploy-web/src/config/ui.config.ts | 1 + .../BackgroundTaskProvider.tsx | 6 +- .../CertificateProviderContext.tsx | 4 +- .../ChainParamProvider/ChainParamProvider.tsx | 4 +- .../PricingProvider/PricingProvider.tsx | 4 +- .../SettingsProviderContext.tsx | 7 +- .../context/WalletProvider/WalletProvider.tsx | 7 +- apps/deploy-web/src/hooks/useDenom.ts | 6 +- apps/deploy-web/src/hooks/useManagedWallet.ts | 8 +- .../src/hooks/useManagedWalletDenom.ts | 4 +- .../src/hooks/useStoredAnonymousUser.ts | 6 +- apps/deploy-web/src/hooks/useWalletBalance.ts | 9 +- apps/deploy-web/src/instrumentation.ts | 13 ++ apps/deploy-web/src/middleware.ts | 6 +- .../src/pages/api/auth/[...auth0].ts | 4 +- .../src/pages/api/proxy/[...path].ts | 4 +- .../src/pages/profile/[username]/index.tsx | 4 +- .../src/pages/providers/[owner]/index.tsx | 4 +- .../src/pages/template/[id]/index.tsx | 4 +- .../pages/templates/[templateId]/index.tsx | 4 +- .../src/queries/useBalancesQuery.ts | 12 +- apps/deploy-web/src/queries/useLeaseQuery.ts | 4 +- .../src/queries/useProvidersQuery.ts | 6 +- .../src/services/api-url/api-url.service.ts | 19 ++ .../api-url/browser-api-url.service.ts | 4 + .../api-url/server-api-url.service.ts | 4 + .../src/services/auth/auth.service.ts | 2 +- .../src/services/http/http.service.ts | 4 +- .../managed-wallet-http.service.ts | 8 +- .../src/services/network/network.service.ts | 43 ++++ .../src/services/user/user-http.service.ts | 2 +- apps/deploy-web/src/store/networkStore.ts | 15 +- apps/deploy-web/src/types/route-steps.type.ts | 5 + .../src/utils/TransactionMessageData.ts | 22 +- apps/deploy-web/src/utils/apiUtils.ts | 67 +++--- apps/deploy-web/src/utils/auth0.ts | 10 - apps/deploy-web/src/utils/constants.ts | 208 ------------------ .../src/utils/deploymentData/index.ts | 8 +- .../src/utils/deploymentData/v1beta2.ts | 4 +- .../src/utils/deploymentData/v1beta3.ts | 4 +- apps/deploy-web/src/utils/deploymentUtils.ts | 4 +- apps/deploy-web/src/utils/init.ts | 4 +- apps/deploy-web/src/utils/priceUtils.ts | 11 +- apps/deploy-web/src/utils/proto/index.ts | 8 +- apps/deploy-web/src/utils/urlUtils.ts | 9 +- apps/deploy-web/src/utils/walletUtils.ts | 12 +- docker/Dockerfile.nextjs | 5 + package-lock.json | 144 +++++++++--- packages/env-loader/package.json | 20 ++ packages/env-loader/src/index.js | 31 +++ script/deploy-web.sh | 24 ++ 103 files changed, 762 insertions(+), 551 deletions(-) delete mode 100644 apps/deploy-web/env.config.js create mode 100644 apps/deploy-web/env/.env create mode 100644 apps/deploy-web/env/.env.production create mode 100644 apps/deploy-web/env/.env.sample create mode 100644 apps/deploy-web/env/.env.staging create mode 100644 apps/deploy-web/src/config/auth.config.ts create mode 100644 apps/deploy-web/src/config/browser-env.config.ts create mode 100644 apps/deploy-web/src/config/denom.config.ts create mode 100644 apps/deploy-web/src/config/env-config.schema.ts delete mode 100644 apps/deploy-web/src/config/env.config.ts create mode 100644 apps/deploy-web/src/config/graph.config.ts create mode 100644 apps/deploy-web/src/config/network.config.ts create mode 100644 apps/deploy-web/src/config/server-env.config.ts create mode 100644 apps/deploy-web/src/config/tx.config.ts create mode 100644 apps/deploy-web/src/config/ui.config.ts create mode 100644 apps/deploy-web/src/instrumentation.ts create mode 100644 apps/deploy-web/src/services/api-url/api-url.service.ts create mode 100644 apps/deploy-web/src/services/api-url/browser-api-url.service.ts create mode 100644 apps/deploy-web/src/services/api-url/server-api-url.service.ts create mode 100644 apps/deploy-web/src/services/network/network.service.ts create mode 100644 apps/deploy-web/src/types/route-steps.type.ts delete mode 100644 apps/deploy-web/src/utils/auth0.ts delete mode 100644 apps/deploy-web/src/utils/constants.ts create mode 100644 packages/env-loader/package.json create mode 100644 packages/env-loader/src/index.js create mode 100755 script/deploy-web.sh diff --git a/.dockerignore b/.dockerignore index a9e9df47c..9c820219e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,7 +8,6 @@ **/.env.*.local **/.env.*.test -apps/deploy-web/.env* apps/indexer/.env* apps/landing/.env* apps/provider-console/.env* diff --git a/.gitignore b/.gitignore index 63c8b4825..9f89be47b 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,6 @@ build.ps1 .yarn-integrity # dotenv environment variable files -apps/deploy-web/.env apps/indexer/.env apps/provider-console/.env apps/provider-proxy/.env diff --git a/apps/deploy-web/.gitignore b/apps/deploy-web/.gitignore index b95fb0169..55caf2b0c 100644 --- a/apps/deploy-web/.gitignore +++ b/apps/deploy-web/.gitignore @@ -44,3 +44,5 @@ sentry.properties /playwright-report/ /blob-report/ /playwright/.cache/ + +env-config.schema.js diff --git a/apps/deploy-web/README.md b/apps/deploy-web/README.md index ed0ab2943..a44b16280 100644 --- a/apps/deploy-web/README.md +++ b/apps/deploy-web/README.md @@ -14,21 +14,33 @@ The website should be accessible: [http://localhost:3000/](http://localhost:3000 ## Environment Variables -When running the api locally the following environment variables can be set in a `.env.local` file. - -It is possible to run the website locally without any environment variables, but the login feature will be unavailable. - -|Name|Value|Note| -|-|-|- -|NEXT_PUBLIC_GA_MEASUREMENT_ID|ex: `G-87H3KK3D`|Google Analytics ID -|NEXT_PUBLIC_SENTRY_DSN|ex: `"https://1234...789@z645.ingest.sentry.io/1234"`|[Sentry DSN](https://docs.sentry.io/product/sentry-basics/dsn-explainer/) used when initializing Sentry in [sentry.client.config.js](./sentry.client.config.js) and [sentry.server.config.js](./sentry.server.config.js) -|AUTH0_SECRET|| -|AUTH0_BASE_URL|| -|AUTH0_ISSUER_BASE_URL|| -|AUTH0_CLIENT_ID|| -|AUTH0_CLIENT_SECRET|| -|AUTH0_AUDIENCE|| -|AUTH0_SCOPE|| -|AUTH0_M2M_DOMAIN|| -|AUTH0_M2M_CLIENT_ID|| -|AUTH0_M2M_CLIENT_SECRET|| \ No newline at end of file +### Overview +Environment variables in this Next.js app follow the standard Next.js behavior, as documented in the [Next.js environment variables documentation](https://nextjs.org/docs/basic-features/environment-variables). This means that files like `.env.local` or `.env.production` will be automatically loaded based on the environment in which the app is running. + +However, we have extended this functionality to support more granular environment-specific configurations. Environment variables are stored in the `./env` directory, where multiple `.env` files exist for different deployment environments (stages): + +- `.env` - Loaded for any environment +- `.env.production` - Loaded for the production stage +- `.env.staging` - Loaded for the staging stage + +### How Environment Variables Are Loaded +We use **dotenvx** to manage and load environment variables. This allows us to take advantage of its features, such as **variable interpolation** (i.e., using other environment variables within variable values). + +### Validation with Zod +Environment variables are validated using **Zod** schemas, ensuring that all required variables are present and have valid values. The validation logic can be found in the file `src/config/env-config.schema.ts`. + +We use two separate Zod schemas: +- **Static Build-Time Schema**: Validates variables at build time. If any variables are missing or invalid during the build process, the build will fail. +- **Dynamic Server Runtime Schema**: Validates variables at server startup. If any variables are missing or invalid at this stage, the server will fail to start. + +This validation ensures that both build and runtime configurations are secure and complete before the app runs. + +### App Configuration +App configurations, including environment variables, are located in the `src/config` directory. In our setup: +- **Environment configs** are handled separately from **hardcoded configs**. +- Hardcoded configs are organized by domain to maintain a clear structure and separation of concerns. + +### Sample Environment Variables +All environment variables required for the app, along with their expected structure and types, can be found in the `env/.env.sample` file. This sample file serves as a template for setting up your environment variables and ensures that all necessary variables are accounted for in each environment. + +By organizing environment variables and configuration this way, we ensure a consistent, safe, and scalable approach to managing different deployment environments. \ No newline at end of file diff --git a/apps/deploy-web/env.config.js b/apps/deploy-web/env.config.js deleted file mode 100644 index 4ece40b20..000000000 --- a/apps/deploy-web/env.config.js +++ /dev/null @@ -1,26 +0,0 @@ -const { z } = require("zod"); - -const networkId = z.enum(["mainnet", "sandbox", "testnet"]); - -const envSchema = z.object({ - NEXT_PUBLIC_MASTER_WALLET_ADDRESS: z.string().optional(), - NEXT_PUBLIC_BILLING_ENABLED: z - .enum(["true", "false"]) - .transform(val => val === "true") - .optional() - .default("false"), - NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID: networkId.optional().default("mainnet"), - NEXT_PUBLIC_DEFAULT_NETWORK_ID: networkId.optional().default("mainnet"), - DEFAULT_NETWORK_ID: networkId.optional().default("mainnet"), - NEXT_PUBLIC_MANAGED_WALLET_DENOM: z.enum(["uakt", "usdc"]).optional().default("usdc") -}); - -module.exports.envSchema = envSchema; -module.exports.envConfig = envSchema.parse({ - NEXT_PUBLIC_MASTER_WALLET_ADDRESS: process.env.NEXT_PUBLIC_MASTER_WALLET_ADDRESS, - NEXT_PUBLIC_BILLING_ENABLED: process.env.NEXT_PUBLIC_BILLING_ENABLED, - NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID: process.env.NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID, - NEXT_PUBLIC_DEFAULT_NETWORK_ID: process.env.NEXT_PUBLIC_DEFAULT_NETWORK_ID, - DEFAULT_NETWORK_ID: process.env.DEFAULT_NETWORK_ID, - NEXT_PUBLIC_MANAGED_WALLET_DENOM: process.env.NEXT_PUBLIC_MANAGED_WALLET_DENOM -}); diff --git a/apps/deploy-web/env/.env b/apps/deploy-web/env/.env new file mode 100644 index 000000000..1e1b78ccd --- /dev/null +++ b/apps/deploy-web/env/.env @@ -0,0 +1,2 @@ +AUTH0_AUDIENCE=https://api.cloudmos.io +AUTH0_SCOPE=openid profile email offline_access \ No newline at end of file diff --git a/apps/deploy-web/env/.env.production b/apps/deploy-web/env/.env.production new file mode 100644 index 000000000..e3d12e4f8 --- /dev/null +++ b/apps/deploy-web/env/.env.production @@ -0,0 +1,17 @@ +AUTH0_BASE_URL=https://console.akash.network +AUTH0_ISSUER_BASE_URL=https://auth.cloudmos.io + +NEXT_PUBLIC_BILLING_ENABLED=false +NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID=mainnet +NEXT_PUBLIC_MANAGED_WALLET_DENOM=usdc +# TODO: replace with a fresh master wallet before release +NEXT_PUBLIC_MASTER_WALLET_ADDRESS=akash1ss0d2yw38r6e7ew8ndye9h7kg62sem36zak4d5 + +NEXT_PUBLIC_STATS_APP_URL=https://stats.akash.network +NEXT_PUBLIC_PROVIDER_PROXY_URL=https://providerproxy.cloudmos.io +NEXT_PUBLIC_PROVIDER_PROXY_URL_WS=wss://providerproxy.cloudmos.io +NEXT_PUBLIC_NODE_ENV=$NODE_ENV +NEXT_PUBLIC_BASE_API_MAINNET_URL=https://api.cloudmos.io +NEXT_PUBLIC_BASE_API_SANDBOX_URL=https://api-sandbox.cloudmos.io +NEXT_PUBLIC_BASE_API_TESTNET_URL=https://api-testnet.cloudmos.io +NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_BASE_API_MAINNET_URL diff --git a/apps/deploy-web/env/.env.sample b/apps/deploy-web/env/.env.sample new file mode 100644 index 000000000..8fc721297 --- /dev/null +++ b/apps/deploy-web/env/.env.sample @@ -0,0 +1,22 @@ +DEPLOYMENT_ENV + +AUTH0_BASE_URL= +AUTH0_ISSUER_BASE_URL= +AUTH0_SECRET +AUTH0_CLIENT_ID +AUTH0_CLIENT_SECRET + +NEXT_PUBLIC_BILLING_ENABLED= +NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID= +NEXT_PUBLIC_MANAGED_WALLET_DENOM= +NEXT_PUBLIC_MASTER_WALLET_ADDRESS= +NEXT_PUBLIC_STATS_APP_URL= +NEXT_PUBLIC_PROVIDER_PROXY_URL= +NEXT_PUBLIC_PROVIDER_PROXY_URL_WS= +NEXT_PUBLIC_NODE_ENV= +NEXT_PUBLIC_BASE_API_MAINNET_URL= +NEXT_PUBLIC_BASE_API_SANDBOX_URL= +NEXT_PUBLIC_BASE_API_TESTNET_URL= +NEXT_PUBLIC_API_BASE_URL= +NEXT_PUBLIC_SENTRY_DSN= +NEXT_PUBLIC_SENTRY_SERVER_NAME diff --git a/apps/deploy-web/env/.env.staging b/apps/deploy-web/env/.env.staging new file mode 100644 index 000000000..08bdd5c3a --- /dev/null +++ b/apps/deploy-web/env/.env.staging @@ -0,0 +1,16 @@ +AUTH0_BASE_URL=https://console-beta.akash.network +AUTH0_ISSUER_BASE_URL=https://dev-5aprb0lr.us.auth0.com + +NEXT_PUBLIC_BILLING_ENABLED=true +NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID=mainnet +NEXT_PUBLIC_MANAGED_WALLET_DENOM=usdc +NEXT_PUBLIC_MASTER_WALLET_ADDRESS=akash1ss0d2yw38r6e7ew8ndye9h7kg62sem36zak4d5 + +NEXT_PUBLIC_STATS_APP_URL=https://stats.akash.network +NEXT_PUBLIC_PROVIDER_PROXY_URL=https://providerproxy.cloudmos.io +NEXT_PUBLIC_PROVIDER_PROXY_URL_WS=wss://providerproxy.cloudmos.io +NEXT_PUBLIC_NODE_ENV=$NODE_ENV +NEXT_PUBLIC_BASE_API_MAINNET_URL=https://api-mainnet-staging.cloudmos.io +NEXT_PUBLIC_BASE_API_SANDBOX_URL=https://api-sandbox-staging.cloudmos.io +NEXT_PUBLIC_BASE_API_TESTNET_URL=$NEXT_PUBLIC_BASE_API_MAINNET_URL +NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_BASE_API_MAINNET_URL \ No newline at end of file diff --git a/apps/deploy-web/next.config.js b/apps/deploy-web/next.config.js index 2cd3b5d10..4895b3aa2 100644 --- a/apps/deploy-web/next.config.js +++ b/apps/deploy-web/next.config.js @@ -1,4 +1,4 @@ -require("./env.config"); +require("@akashnetwork/env-loader"); const withBundleAnalyzer = require("@next/bundle-analyzer")({ enabled: process.env.ANALYZE === "true" }); @@ -10,6 +10,16 @@ const withPWA = require("next-pwa")({ }); const { withSentryConfig } = require("@sentry/nextjs"); +try { + const { browserEnvSchema } = require("./env-config.schema"); + + browserEnvSchema.parse(process.env); +} catch (error) { + if (error.message.includes("Cannot find module")) { + console.warn("No env-config.schema.js found, skipping env validation"); + } +} + /** * @type {import('next').NextConfig} */ @@ -30,10 +40,9 @@ const moduleExports = { ignoreDuringBuilds: true }, transpilePackages: ["geist", "@akashnetwork/ui"], - // experimental: { - // // outputStandalone: true, - // externalDir: true // to make the import from shared parent folder work https://github.com/vercel/next.js/issues/9474#issuecomment-810212174 - // }, + experimental: { + instrumentationHook: true + }, publicRuntimeConfig: { version }, diff --git a/apps/deploy-web/package.json b/apps/deploy-web/package.json index 7cafbaf5f..97b5ebdba 100644 --- a/apps/deploy-web/package.json +++ b/apps/deploy-web/package.json @@ -6,8 +6,8 @@ "license": "Apache-2.0", "author": "Akash Network", "scripts": { - "build": "next build", - "build-analyze": "set ANALYZE=true&& next build", + "build": "npm run build-env-schemas && next build", + "build-env-schemas": "tsc src/config/env-config.schema.ts --outDir . --skipLibCheck", "dev": "next", "format": "prettier --write ./*.{ts,js,json} **/*.{ts,tsx,js,json}", "lint": "eslint .", @@ -17,6 +17,7 @@ "dependencies": { "@akashnetwork/akash-api": "^1.3.0", "@akashnetwork/akashjs": "^0.10.0", + "@akashnetwork/env-loader": "*", "@akashnetwork/http-sdk": "*", "@akashnetwork/ui": "*", "@auth0/nextjs-auth0": "^3.5.0", diff --git a/apps/deploy-web/src/components/authorizations/AllowanceModal.tsx b/apps/deploy-web/src/components/authorizations/AllowanceModal.tsx index 2de36afd0..1dce8fb3c 100644 --- a/apps/deploy-web/src/components/authorizations/AllowanceModal.tsx +++ b/apps/deploy-web/src/components/authorizations/AllowanceModal.tsx @@ -10,11 +10,11 @@ import { event } from "nextjs-google-analytics"; import { z } from "zod"; import { LinkTo } from "@src/components/shared/LinkTo"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { useWallet } from "@src/context/WalletProvider"; import { useDenomData } from "@src/hooks/useWalletBalance"; import { AllowanceType } from "@src/types/grant"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { uAktDenom } from "@src/utils/constants"; import { aktToUakt, coinToDenom } from "@src/utils/priceUtils"; import { TransactionMessageData } from "@src/utils/TransactionMessageData"; @@ -46,7 +46,7 @@ export const AllowanceModal: React.FunctionComponent = ({ editingAllowanc }); const { handleSubmit, control, watch, clearErrors, setValue } = form; const { amount, granteeAddress, expiration } = watch(); - const denomData = useDenomData(uAktDenom); + const denomData = useDenomData(UAKT_DENOM); const onDepositClick = event => { event.preventDefault(); @@ -64,7 +64,7 @@ export const AllowanceModal: React.FunctionComponent = ({ editingAllowanc if (editingAllowance) { messages.push(TransactionMessageData.getRevokeAllowanceMsg(address, granteeAddress)); } - messages.push(TransactionMessageData.getGrantBasicAllowanceMsg(address, granteeAddress, spendLimit, uAktDenom, expirationDate)); + messages.push(TransactionMessageData.getGrantBasicAllowanceMsg(address, granteeAddress, spendLimit, UAKT_DENOM, expirationDate)); const response = await signAndBroadcastTx(messages); if (response) { @@ -144,7 +144,7 @@ export const AllowanceModal: React.FunctionComponent = ({ editingAllowanc min={0} step={0.000001} max={denomData?.inputMax} - startIcon={{denomData?.label}} + startIcon={{denomData?.label}} /> ); }} diff --git a/apps/deploy-web/src/components/authorizations/GrantModal.tsx b/apps/deploy-web/src/components/authorizations/GrantModal.tsx index a7c847049..b2c134c6c 100644 --- a/apps/deploy-web/src/components/authorizations/GrantModal.tsx +++ b/apps/deploy-web/src/components/authorizations/GrantModal.tsx @@ -23,12 +23,12 @@ import { event } from "nextjs-google-analytics"; import { z } from "zod"; import { LinkTo } from "@src/components/shared/LinkTo"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { useWallet } from "@src/context/WalletProvider"; import { getUsdcDenom, useUsdcDenom } from "@src/hooks/useDenom"; import { useDenomData } from "@src/hooks/useWalletBalance"; import { GrantType } from "@src/types/grant"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { uAktDenom } from "@src/utils/constants"; import { denomToUdenom } from "@src/utils/mathHelpers"; import { aktToUakt, coinToDenom } from "@src/utils/priceUtils"; import { TransactionMessageData } from "@src/utils/TransactionMessageData"; @@ -69,7 +69,7 @@ export const GrantModal: React.FunctionComponent = ({ editingGrant, addre const { handleSubmit, control, watch, clearErrors, setValue } = form; const { amount, granteeAddress, expiration, token } = watch(); const selectedToken = supportedTokens.find(x => x.id === token); - const denom = token === "akt" ? uAktDenom : usdcDenom; + const denom = token === "akt" ? UAKT_DENOM : usdcDenom; const denomData = useDenomData(denom); const onDepositClick = event => { @@ -82,7 +82,7 @@ export const GrantModal: React.FunctionComponent = ({ editingGrant, addre clearErrors(); const spendLimit = token === "akt" ? aktToUakt(amount) : denomToUdenom(amount); const usdcDenom = getUsdcDenom(); - const denom = token === "akt" ? uAktDenom : usdcDenom; + const denom = token === "akt" ? UAKT_DENOM : usdcDenom; const expirationDate = new Date(expiration); const message = TransactionMessageData.getGrantMsg(address, granteeAddress, spendLimit, expirationDate, denom); diff --git a/apps/deploy-web/src/components/deployments/DeploymentDepositModal.tsx b/apps/deploy-web/src/components/deployments/DeploymentDepositModal.tsx index 5013366c6..2cbabf9c3 100644 --- a/apps/deploy-web/src/components/deployments/DeploymentDepositModal.tsx +++ b/apps/deploy-web/src/components/deployments/DeploymentDepositModal.tsx @@ -25,13 +25,13 @@ import { event } from "nextjs-google-analytics"; import { useSnackbar } from "notistack"; import { z } from "zod"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { useSettings } from "@src/context/SettingsProvider"; import { useWallet } from "@src/context/WalletProvider"; import { useUsdcDenom } from "@src/hooks/useDenom"; import { useDenomData } from "@src/hooks/useWalletBalance"; import { useGranteeGrants } from "@src/queries/useGrantsQuery"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { uAktDenom } from "@src/utils/constants"; import { denomToUdenom, udenomToDenom } from "@src/utils/mathHelpers"; import { coinToUDenom, uaktToAKT } from "@src/utils/priceUtils"; import { LinkTo } from "../shared/LinkTo"; @@ -185,7 +185,7 @@ export const DeploymentDepositModal: React.FunctionComponent = ({ handleC category: "deployments", label: "Use depositor to deposit in deployment" }); - } else if (denom === uAktDenom && deposit > uaktBalance) { + } else if (denom === UAKT_DENOM && deposit > uaktBalance) { setError(`You can't deposit more than you currently have in your balance. Current balance is: ${uaktToAKT(uaktBalance)} AKT.`); return; } else if (denom === usdcIbcDenom && deposit > usdcBalance) { diff --git a/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx b/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx index aea0f148a..9191df96a 100644 --- a/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx +++ b/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx @@ -14,8 +14,8 @@ import { useWallet } from "@src/context/WalletProvider"; import { useDeploymentDetail } from "@src/queries/useDeploymentQuery"; import { useDeploymentLeaseList } from "@src/queries/useLeaseQuery"; import { useProviderList } from "@src/queries/useProvidersQuery"; +import { RouteStep } from "@src/types/route-steps.type"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { RouteStepKeys } from "@src/utils/constants"; import { getDeploymentLocalData } from "@src/utils/deploymentLocalDataUtils"; import { cn } from "@src/utils/styleUtils"; import { UrlService } from "@src/utils/urlUtils"; @@ -63,7 +63,7 @@ export function DeploymentDetail({ dseq }: React.PropsWithChildren<{ dseq: strin if (_leases) { // Redirect to select bids if has no lease if (deployment?.state === "active" && _leases.length === 0) { - router.replace(UrlService.newDeployment({ dseq, step: RouteStepKeys.createLeases })); + router.replace(UrlService.newDeployment({ dseq, step: RouteStep.createLeases })); } // Set the array of refs for lease rows diff --git a/apps/deploy-web/src/components/deployments/DeploymentLeaseShell.tsx b/apps/deploy-web/src/components/deployments/DeploymentLeaseShell.tsx index 8b2f746c4..d78e77baf 100644 --- a/apps/deploy-web/src/components/deployments/DeploymentLeaseShell.tsx +++ b/apps/deploy-web/src/components/deployments/DeploymentLeaseShell.tsx @@ -5,6 +5,7 @@ import { OpenInWindow, OpenNewWindow } from "iconoir-react"; import Link from "next/link"; import ViewPanel from "@src/components/shared/ViewPanel"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useCertificate } from "@src/context/CertificateProvider"; import { useCustomWebSocket } from "@src/hooks/useCustomWebSocket"; import { XTerm } from "@src/lib/XTerm"; @@ -13,7 +14,6 @@ import { useLeaseStatus } from "@src/queries/useLeaseQuery"; import { useProviderList } from "@src/queries/useProvidersQuery"; import { LeaseDto } from "@src/types/deployment"; import { LeaseShellCode } from "@src/types/shell"; -import { PROVIDER_PROXY_URL_WS } from "@src/utils/constants"; import { cn } from "@src/utils/styleUtils"; import { UrlService } from "@src/utils/urlUtils"; import { LeaseSelect } from "./LeaseSelect"; @@ -47,7 +47,7 @@ export const DeploymentLeaseShell: React.FunctionComponent = ({ leases }) }); const currentUrl = useRef(null); const terminalRef = useRef(null); - const { sendJsonMessage } = useCustomWebSocket(PROVIDER_PROXY_URL_WS, { + const { sendJsonMessage } = useCustomWebSocket(browserEnvConfig.NEXT_PUBLIC_PROVIDER_PROXY_URL_WS, { onOpen: () => { console.log("opened"); }, diff --git a/apps/deploy-web/src/components/deployments/DeploymentLogs.tsx b/apps/deploy-web/src/components/deployments/DeploymentLogs.tsx index 032f11966..7794f2c0b 100644 --- a/apps/deploy-web/src/components/deployments/DeploymentLogs.tsx +++ b/apps/deploy-web/src/components/deployments/DeploymentLogs.tsx @@ -14,6 +14,7 @@ import { LinearLoadingSkeleton } from "@src/components/shared/LinearLoadingSkele import { MemoMonaco } from "@src/components/shared/MemoMonaco"; import { SelectCheckbox } from "@src/components/shared/SelectCheckbox"; import ViewPanel from "@src/components/shared/ViewPanel"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useBackgroundTask } from "@src/context/BackgroundTaskProvider"; import { useCertificate } from "@src/context/CertificateProvider"; import { useThrottledCallback } from "@src/hooks/useThrottle"; @@ -21,7 +22,6 @@ import { useLeaseStatus } from "@src/queries/useLeaseQuery"; import { useProviderList } from "@src/queries/useProvidersQuery"; import { LeaseDto } from "@src/types/deployment"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { PROVIDER_PROXY_URL_WS } from "@src/utils/constants"; import { cn } from "@src/utils/styleUtils"; import { LeaseSelect } from "./LeaseSelect"; @@ -57,7 +57,7 @@ export const DeploymentLogs: React.FunctionComponent = ({ leases, selecte } = useLeaseStatus(providerInfo?.hostUri || "", selectedLease as LeaseDto, { enabled: false }); - const { sendJsonMessage } = useWebSocket(PROVIDER_PROXY_URL_WS, { + const { sendJsonMessage } = useWebSocket(browserEnvConfig.NEXT_PUBLIC_PROVIDER_PROXY_URL_WS, { onOpen: () => {}, onMessage: onLogReceived, onError: error => console.error("error", error), diff --git a/apps/deploy-web/src/components/get-started/GetStartedStepper.tsx b/apps/deploy-web/src/components/get-started/GetStartedStepper.tsx index 8023acbbc..dc20bd59b 100644 --- a/apps/deploy-web/src/components/get-started/GetStartedStepper.tsx +++ b/apps/deploy-web/src/components/get-started/GetStartedStepper.tsx @@ -12,10 +12,10 @@ import Link from "next/link"; import { LoginRequiredLink } from "@src/components/user/LoginRequiredLink"; import { ConnectManagedWalletButton } from "@src/components/wallet/ConnectManagedWalletButton"; -import { envConfig } from "@src/config/env.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useChainParam } from "@src/context/ChainParamProvider"; import { useWallet } from "@src/context/WalletProvider"; -import { RouteStepKeys } from "@src/utils/constants"; +import { RouteStep } from "@src/types/route-steps.type"; import { udenomToDenom } from "@src/utils/mathHelpers"; import { uaktToAKT } from "@src/utils/priceUtils"; import { cn } from "@src/utils/styleUtils"; @@ -91,11 +91,11 @@ export const GetStartedStepper: React.FunctionComponent = () => { onClick={() => (activeStep > 0 ? onStepClick(0) : null)} classes={{ label: cn("text-xl tracking-tight", { ["cursor-pointer hover:text-primary"]: activeStep > 0, ["!font-bold"]: activeStep === 0 }) }} > - {envConfig.NEXT_PUBLIC_BILLING_ENABLED ? "Trial / Billing" : "Billing"} + {browserEnvConfig.NEXT_PUBLIC_BILLING_ENABLED ? "Trial / Billing" : "Billing"} - {envConfig.NEXT_PUBLIC_BILLING_ENABLED && !isWalletConnected && ( + {browserEnvConfig.NEXT_PUBLIC_BILLING_ENABLED && !isWalletConnected && (

You can pay using either USD (fiat) or with crypto ($AKT or $USDC). To pay with USD click "Start Trial". To pay with crypto, click "Connect Wallet" @@ -158,7 +158,7 @@ export const GetStartedStepper: React.FunctionComponent = () => { Billing is not set up - {envConfig.NEXT_PUBLIC_BILLING_ENABLED && } + {browserEnvConfig.NEXT_PUBLIC_BILLING_ENABLED && } )} @@ -242,7 +242,7 @@ export const GetStartedStepper: React.FunctionComponent = () => {

Deploy! diff --git a/apps/deploy-web/src/components/graph/Graph.tsx b/apps/deploy-web/src/components/graph/Graph.tsx index 5e4cd9f6c..7db8c347b 100644 --- a/apps/deploy-web/src/components/graph/Graph.tsx +++ b/apps/deploy-web/src/components/graph/Graph.tsx @@ -5,9 +5,9 @@ import useMediaQuery from "@mui/material/useMediaQuery"; import { ResponsiveLineCanvas } from "@nivo/line"; import { useTheme } from "next-themes"; +import { SELECTED_RANGE_VALUES } from "@src/config/graph.config"; import { GraphResponse, ISnapshotMetadata, ProviderSnapshots, Snapshots, SnapshotValue } from "@src/types"; import { customColors } from "@src/utils/colors"; -import { selectedRangeValues } from "@src/utils/constants"; import { nFormatter, roundDecimal } from "@src/utils/mathHelpers"; interface IGraphProps { @@ -135,19 +135,19 @@ const getTheme = (theme: string | undefined) => { const getGraphMetadataPerRange = (range: number): { size: number; border: number; xModulo: number } => { switch (range) { - case selectedRangeValues["7D"]: + case SELECTED_RANGE_VALUES["7D"]: return { size: 10, border: 3, xModulo: 1 }; - case selectedRangeValues["1M"]: + case SELECTED_RANGE_VALUES["1M"]: return { size: 6, border: 2, xModulo: 3 }; - case selectedRangeValues["ALL"]: + case SELECTED_RANGE_VALUES["ALL"]: return { size: 0, border: 1, diff --git a/apps/deploy-web/src/components/home/HomeContainer.tsx b/apps/deploy-web/src/components/home/HomeContainer.tsx index 4329ebb01..e3e2436fa 100644 --- a/apps/deploy-web/src/components/home/HomeContainer.tsx +++ b/apps/deploy-web/src/components/home/HomeContainer.tsx @@ -5,7 +5,6 @@ import { Spinner } from "@akashnetwork/ui/components"; import dynamic from "next/dynamic"; import { Footer } from "@src/components/layout/Footer"; -import { envConfig } from "@src/config/env.config"; import { useLocalNotes } from "@src/context/LocalNoteProvider"; import { useSettings } from "@src/context/SettingsProvider"; import { useWallet } from "@src/context/WalletProvider"; diff --git a/apps/deploy-web/src/components/home/YourAccount.tsx b/apps/deploy-web/src/components/home/YourAccount.tsx index 81f1cff8d..95d4abacd 100644 --- a/apps/deploy-web/src/components/home/YourAccount.tsx +++ b/apps/deploy-web/src/components/home/YourAccount.tsx @@ -9,7 +9,8 @@ import Link from "next/link"; import { useTheme } from "next-themes"; import { LoginRequiredLink } from "@src/components/user/LoginRequiredLink"; -import { envConfig } from "@src/config/env.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { usePricing } from "@src/context/PricingProvider"; import { useWallet } from "@src/context/WalletProvider"; import { useUsdcDenom } from "@src/hooks/useDenom"; @@ -19,7 +20,6 @@ import { Balances } from "@src/types"; import { DeploymentDto, LeaseDto } from "@src/types/deployment"; import { ApiProviderList } from "@src/types/provider"; import { customColors } from "@src/utils/colors"; -import { uAktDenom } from "@src/utils/constants"; import { roundDecimal, udenomToDenom } from "@src/utils/mathHelpers"; import { getAvgCostPerMonth, uaktToAKT } from "@src/utils/priceUtils"; import { cn } from "@src/utils/styleUtils"; @@ -61,7 +61,7 @@ export const YourAccount: React.FunctionComponent = ({ balances, isLoadin const [costPerMonth, setCostPerMonth] = useState(null); const [userProviders, setUserProviders] = useState<{ owner: string; name: string }[] | null>(null); const escrowUAktSum = activeDeployments - .filter(x => x.escrowAccount.balance.denom === uAktDenom) + .filter(x => x.escrowAccount.balance.denom === UAKT_DENOM) .map(x => x.escrowBalance) .reduce((a, b) => a + b, 0); const escrowUsdcSum = activeDeployments @@ -92,15 +92,16 @@ export const YourAccount: React.FunctionComponent = ({ balances, isLoadin { id: "balance_akt", label: "Balance", - denom: uAktDenom, + denom: UAKT_DENOM, denomLabel: "AKT", - value: isManagedWallet && envConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "uakt" ? balances.balance + managedWalletCreditAmount : balances.balance, + value: + isManagedWallet && browserEnvConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "uakt" ? balances.balance + managedWalletCreditAmount : balances.balance, color: colors.balance_akt }, { id: "deployment_akt", label: "Deployment", - denom: uAktDenom, + denom: UAKT_DENOM, denomLabel: "AKT", value: escrowUAktSum, color: colors.deployment_akt @@ -115,7 +116,9 @@ export const YourAccount: React.FunctionComponent = ({ balances, isLoadin denom: usdcIbcDenom, denomLabel: "USDC", value: - isManagedWallet && envConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "usdc" ? balances.balanceUsdc + managedWalletCreditAmount : balances.balanceUsdc, + isManagedWallet && browserEnvConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "usdc" + ? balances.balanceUsdc + managedWalletCreditAmount + : balances.balanceUsdc, color: colors.balance_usdc }, { @@ -128,8 +131,8 @@ export const YourAccount: React.FunctionComponent = ({ balances, isLoadin } ]; }; - const aktData = balances && (!isManagedWallet || envConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "uakt") ? getAktData(balances, escrowUAktSum) : []; - const usdcData = balances && (!isManagedWallet || envConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "usdc") ? getUsdcData(balances, escrowUsdcSum) : []; + const aktData = balances && (!isManagedWallet || browserEnvConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "uakt") ? getAktData(balances, escrowUAktSum) : []; + const usdcData = balances && (!isManagedWallet || browserEnvConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "usdc") ? getUsdcData(balances, escrowUsdcSum) : []; const filteredAktData = aktData.filter(x => x.value); const filteredUsdcData = usdcData.filter(x => x.value); const allData = [...aktData, ...usdcData]; @@ -140,7 +143,7 @@ export const YourAccount: React.FunctionComponent = ({ balances, isLoadin const totalCostPerBlock = activeLeases .map(x => { switch (x.price.denom) { - case uAktDenom: + case UAKT_DENOM: return udenomToDenom(x.price.amount, 10) * price; case usdcIbcDenom: return udenomToDenom(x.price.amount, 10); @@ -307,7 +310,7 @@ export const YourAccount: React.FunctionComponent = ({ balances, isLoadin
- +
diff --git a/apps/deploy-web/src/components/layout/CustomGoogleAnalytics.tsx b/apps/deploy-web/src/components/layout/CustomGoogleAnalytics.tsx index aeaccebdf..660a98deb 100644 --- a/apps/deploy-web/src/components/layout/CustomGoogleAnalytics.tsx +++ b/apps/deploy-web/src/components/layout/CustomGoogleAnalytics.tsx @@ -2,7 +2,7 @@ import { useReportWebVitals } from "next/web-vitals"; import { event, GoogleAnalytics as GAnalytics } from "nextjs-google-analytics"; -import { isProd } from "@src/utils/constants"; +import { browserEnvConfig } from "@src/config/browser-env.config"; export default function GoogleAnalytics() { useReportWebVitals(({ id, name, label, value }) => { @@ -14,5 +14,5 @@ export default function GoogleAnalytics() { }); }); - return <>{isProd && }; + return <>{browserEnvConfig.NEXT_PUBLIC_NODE_ENV === "production" && }; } diff --git a/apps/deploy-web/src/components/layout/Layout.tsx b/apps/deploy-web/src/components/layout/Layout.tsx index 321315a64..c66b773e3 100644 --- a/apps/deploy-web/src/components/layout/Layout.tsx +++ b/apps/deploy-web/src/components/layout/Layout.tsx @@ -5,9 +5,9 @@ import { IntlProvider } from "react-intl"; import { ErrorFallback, Spinner } from "@akashnetwork/ui/components"; import { useMediaQuery, useTheme as useMuiTheme } from "@mui/material"; +import { ACCOUNT_BAR_HEIGHT } from "@src/config/ui.config"; import { useSettings } from "@src/context/SettingsProvider"; import { useWallet } from "@src/context/WalletProvider"; -import { accountBarHeight } from "@src/utils/constants"; import { cn } from "@src/utils/styleUtils"; import { LinearLoadingSkeleton } from "../shared/LinearLoadingSkeleton"; import { Nav } from "./Nav"; @@ -106,7 +106,7 @@ const LayoutApp: React.FunctionComponent = ({ children, isLoading, isUsin
-
+
-
+
diff --git a/apps/deploy-web/src/components/providers/ActiveLeasesGraph.tsx b/apps/deploy-web/src/components/providers/ActiveLeasesGraph.tsx index 5f48c99bd..d0b2cba5c 100644 --- a/apps/deploy-web/src/components/providers/ActiveLeasesGraph.tsx +++ b/apps/deploy-web/src/components/providers/ActiveLeasesGraph.tsx @@ -7,10 +7,10 @@ import dynamic from "next/dynamic"; import { DiffNumber } from "@src/components/shared/DiffNumber"; import { DiffPercentageChip } from "@src/components/shared/DiffPercentageChip"; import { TimeRange } from "@src/components/shared/TimeRange"; +import { SELECTED_RANGE_VALUES } from "@src/config/graph.config"; import { useProviderActiveLeasesGraph } from "@src/queries/useProvidersQuery"; import { ProviderSnapshots } from "@src/types"; import { ClientProviderDetailWithStatus } from "@src/types/provider"; -import { selectedRangeValues } from "@src/utils/constants"; import { percIncrease } from "@src/utils/mathHelpers"; import { getSnapshotMetadata } from "@src/utils/providerUtils"; import { Title } from "../shared/Title"; @@ -25,7 +25,7 @@ interface IProps { export const ActiveLeasesGraph: React.FunctionComponent = ({ provider }) => { const { data: snapshotData, status } = useProviderActiveLeasesGraph(provider.owner); - const [selectedRange, setSelectedRange] = useState(selectedRangeValues["7D"]); + const [selectedRange, setSelectedRange] = useState(SELECTED_RANGE_VALUES["7D"]); const hasSnapshotData = snapshotData && snapshotData.snapshots.length > 0; const snapshotMetadata = hasSnapshotData && getSnapshotMetadata(); const rangedData = hasSnapshotData && snapshotData.snapshots.slice(Math.max(snapshotData.snapshots.length - selectedRange, 0), snapshotData.snapshots.length); diff --git a/apps/deploy-web/src/components/sdl/PlacementFormModal.tsx b/apps/deploy-web/src/components/sdl/PlacementFormModal.tsx index 8be7097d0..aba57aadd 100644 --- a/apps/deploy-web/src/components/sdl/PlacementFormModal.tsx +++ b/apps/deploy-web/src/components/sdl/PlacementFormModal.tsx @@ -5,9 +5,9 @@ import { FormattedNumber } from "react-intl"; import { CustomTooltip, FormField, FormInput, Popup } from "@akashnetwork/ui/components"; import { InfoCircle } from "iconoir-react"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { useSdlDenoms } from "@src/hooks/useDenom"; import { PlacementType, SdlBuilderFormValuesType, ServiceType } from "@src/types"; -import { uAktDenom } from "@src/utils/constants"; import { udenomToDenom } from "@src/utils/mathHelpers"; import { getAvgCostPerMonth, toReadableDenom, uaktToAKT } from "@src/utils/priceUtils"; import { PriceValue } from "../shared/PriceValue"; @@ -124,9 +124,9 @@ export const PlacementFormModal: React.FunctionComponent = ({ control, se
Akash will only show providers costing less than{" "} - {selectedDenom?.value === uAktDenom ? ( + {selectedDenom?.value === UAKT_DENOM ? ( <> - ~ + ~ ) : ( <> diff --git a/apps/deploy-web/src/components/sdl/RentGpusForm.tsx b/apps/deploy-web/src/components/sdl/RentGpusForm.tsx index e97f04ad3..c423ce759 100644 --- a/apps/deploy-web/src/components/sdl/RentGpusForm.tsx +++ b/apps/deploy-web/src/components/sdl/RentGpusForm.tsx @@ -10,7 +10,7 @@ import { useAtom } from "jotai"; import { useRouter, useSearchParams } from "next/navigation"; import { event } from "nextjs-google-analytics"; -import { envConfig } from "@src/config/env.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useCertificate } from "@src/context/CertificateProvider"; import { useChainParam } from "@src/context/ChainParamProvider"; import { useSettings } from "@src/context/SettingsProvider"; @@ -24,8 +24,8 @@ import sdlStore from "@src/store/sdlStore"; import { ApiTemplate, ProfileGpuModelType, RentGpusFormValuesSchema, RentGpusFormValuesType, ServiceType } from "@src/types"; import { DepositParams } from "@src/types/deployment"; import { ProviderAttributeSchemaDetailValue } from "@src/types/providerAttributes"; +import { RouteStep } from "@src/types/route-steps.type"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { defaultInitialDeposit, RouteStepKeys } from "@src/utils/constants"; import { deploymentData } from "@src/utils/deploymentData"; import { saveDeploymentManifestAndName } from "@src/utils/deploymentLocalDataUtils"; import { validateDeploymentData } from "@src/utils/deploymentUtils"; @@ -79,7 +79,7 @@ export const RentGpusForm: React.FunctionComponent = () => { const { createDeploymentConfirm } = useManagedDeploymentConfirm(); const managedDenom = useManagedWalletDenom(); const { data: depositParams } = useDepositParams(); - const defaultDeposit = depositParams || defaultInitialDeposit; + const defaultDeposit = depositParams || browserEnvConfig.NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT; useWhen(isManaged && sdlDenom === "uakt", () => { setSdlDenom(managedDenom); @@ -212,7 +212,7 @@ export const RentGpusForm: React.FunctionComponent = () => { return; } - await handleCreateClick(defaultDeposit, envConfig.NEXT_PUBLIC_MASTER_WALLET_ADDRESS); + await handleCreateClick(defaultDeposit, browserEnvConfig.NEXT_PUBLIC_MASTER_WALLET_ADDRESS); } else { setIsCheckingPrerequisites(true); } @@ -272,7 +272,7 @@ export const RentGpusForm: React.FunctionComponent = () => { // Save the manifest saveDeploymentManifestAndName(dd.deploymentId.dseq, sdl, dd.version, address, currentService.image); - router.push(UrlService.newDeployment({ step: RouteStepKeys.createLeases, dseq: dd.deploymentId.dseq })); + router.push(UrlService.newDeployment({ step: RouteStep.createLeases, dseq: dd.deploymentId.dseq })); event(AnalyticsEvents.CREATE_GPU_DEPLOYMENT, { category: "deployments", diff --git a/apps/deploy-web/src/components/sdl/SimpleSdlBuilderForm.tsx b/apps/deploy-web/src/components/sdl/SimpleSdlBuilderForm.tsx index 2c7567d5d..1de14f056 100644 --- a/apps/deploy-web/src/components/sdl/SimpleSdlBuilderForm.tsx +++ b/apps/deploy-web/src/components/sdl/SimpleSdlBuilderForm.tsx @@ -17,9 +17,9 @@ import useFormPersist from "@src/hooks/useFormPersist"; import { useGpuModels } from "@src/queries/useGpuQuery"; import sdlStore from "@src/store/sdlStore"; import { ITemplate, SdlBuilderFormValuesSchema, SdlBuilderFormValuesType, ServiceType } from "@src/types"; +import { RouteStep } from "@src/types/route-steps.type"; import { memoryUnits, storageUnits } from "@src/utils/akash/units"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { RouteStepKeys } from "@src/utils/constants"; import { defaultService } from "@src/utils/sdl/data"; import { generateSdl } from "@src/utils/sdl/sdlGenerator"; import { importSimpleSdl } from "@src/utils/sdl/sdlImport"; @@ -138,7 +138,7 @@ export const SimpleSDLBuilderForm: React.FunctionComponent = () => { content: sdl }); - router.push(UrlService.newDeployment({ step: RouteStepKeys.editDeployment })); + router.push(UrlService.newDeployment({ step: RouteStep.editDeployment })); event(AnalyticsEvents.DEPLOY_SDL, { category: "sdl_builder", diff --git a/apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx b/apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx index 59dfc3bab..668d54d7c 100644 --- a/apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx +++ b/apps/deploy-web/src/components/sdl/SimpleServiceFormControl.tsx @@ -30,11 +30,11 @@ import Image from "next/legacy/image"; import Link from "next/link"; import { SSHKeyFormControl } from "@src/components/sdl/SSHKeyFromControl"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { useSdlBuilder } from "@src/context/SdlBuilderProvider/SdlBuilderProvider"; import { useWallet } from "@src/context/WalletProvider"; import { SdlBuilderFormValuesType, ServiceType } from "@src/types"; import { GpuVendor } from "@src/types/gpu"; -import { uAktDenom } from "@src/utils/constants"; import { udenomToDenom } from "@src/utils/mathHelpers"; import { getAvgCostPerMonth } from "@src/utils/priceUtils"; import { cn } from "@src/utils/styleUtils"; @@ -460,7 +460,7 @@ export const SimpleServiceFormControl: React.FunctionComponent = ({
~ - +   per month
diff --git a/apps/deploy-web/src/components/settings/SelectNetworkModal.tsx b/apps/deploy-web/src/components/settings/SelectNetworkModal.tsx index 9c7de06b6..7597a4ae6 100644 --- a/apps/deploy-web/src/components/settings/SelectNetworkModal.tsx +++ b/apps/deploy-web/src/components/settings/SelectNetworkModal.tsx @@ -3,8 +3,8 @@ import { useState } from "react"; import { Alert, AlertDescription, AlertTitle, Badge, buttonVariants, Popup, RadioGroup, RadioGroupItem } from "@akashnetwork/ui/components"; import { useAtom } from "jotai/index"; +import { MAINNET_ID } from "@src/config/network.config"; import networkStore, { networks } from "@src/store/networkStore"; -import { mainnetId } from "@src/utils/constants"; import { cn } from "@src/utils/styleUtils"; export const SelectNetworkModal = ({ onClose }) => { @@ -66,7 +66,7 @@ export const SelectNetworkModal = ({ onClose }) => { {" - "} {network.version} - {network.id !== mainnetId && ( + {network.id !== MAINNET_ID && ( Experimental )}
@@ -78,7 +78,7 @@ export const SelectNetworkModal = ({ onClose }) => { - {formSelectedNetworkId !== mainnetId && ( + {formSelectedNetworkId !== MAINNET_ID && ( Warning diff --git a/apps/deploy-web/src/components/shared/DynamicMonacoEditor.tsx b/apps/deploy-web/src/components/shared/DynamicMonacoEditor.tsx index 91a06234a..631baf44a 100644 --- a/apps/deploy-web/src/components/shared/DynamicMonacoEditor.tsx +++ b/apps/deploy-web/src/components/shared/DynamicMonacoEditor.tsx @@ -3,7 +3,23 @@ import { OnChange, OnMount } from "@monaco-editor/react"; import dynamic from "next/dynamic"; import { useTheme } from "next-themes"; -import { monacoOptions } from "@src/utils/constants"; +export const MONACO_OPTIONS = { + selectOnLineNumbers: true, + scrollBeyondLastLine: false, + automaticLayout: true, + scrollbar: { + verticalScrollbarSize: 8 + }, + minimap: { + enabled: false + }, + padding: { + bottom: 50 + }, + hover: { + enabled: false + } +}; const _DynamicMonacoEditor = dynamic(() => import("@monaco-editor/react"), { ssr: false, loading: () =>
Loading...
}); @@ -26,7 +42,7 @@ export const DynamicMonacoEditor: React.FunctionComponent = ({ value, hei theme={resolvedTheme === "dark" ? "vs-dark" : "hc-light"} value={value} onChange={onChange} - options={{ ...monacoOptions, ...options }} + options={{ ...MONACO_OPTIONS, ...options }} onMount={onMount} /> ); diff --git a/apps/deploy-web/src/components/shared/TimeRange.tsx b/apps/deploy-web/src/components/shared/TimeRange.tsx index 439c0f13f..5d07b533e 100644 --- a/apps/deploy-web/src/components/shared/TimeRange.tsx +++ b/apps/deploy-web/src/components/shared/TimeRange.tsx @@ -2,7 +2,7 @@ import { ReactNode } from "react"; import { ToggleGroup, ToggleGroupItem } from "@akashnetwork/ui/components"; -import { selectedRangeValues } from "@src/utils/constants"; +import { SELECTED_RANGE_VALUES } from "@src/config/graph.config"; import { cn } from "@src/utils/styleUtils"; type Props = { @@ -20,24 +20,24 @@ export const TimeRange: React.FunctionComponent = ({ selectedRange, onRan _onRangeChange(selectedRangeValues["7D"])} + className={cn({ ["!bg-primary font-bold !text-white"]: selectedRange === SELECTED_RANGE_VALUES["7D"] })} + onClick={() => _onRangeChange(SELECTED_RANGE_VALUES["7D"])} size="sm" > 7D _onRangeChange(selectedRangeValues["1M"])} + className={cn({ ["!bg-primary font-bold !text-white"]: selectedRange === SELECTED_RANGE_VALUES["1M"] })} + onClick={() => _onRangeChange(SELECTED_RANGE_VALUES["1M"])} size="sm" > 1M _onRangeChange(selectedRangeValues["ALL"])} + className={cn({ ["!bg-primary font-bold !text-white"]: selectedRange === SELECTED_RANGE_VALUES["ALL"] })} + onClick={() => _onRangeChange(SELECTED_RANGE_VALUES["ALL"])} size="sm" > ALL diff --git a/apps/deploy-web/src/components/templates/TemplateDetail.tsx b/apps/deploy-web/src/components/templates/TemplateDetail.tsx index cd3af8fb4..a7d4d6054 100644 --- a/apps/deploy-web/src/components/templates/TemplateDetail.tsx +++ b/apps/deploy-web/src/components/templates/TemplateDetail.tsx @@ -14,7 +14,7 @@ import { useTemplates } from "@src/context/TemplatesProvider"; import { usePreviousRoute } from "@src/hooks/usePreviousRoute"; import { getShortText } from "@src/hooks/useShortText"; import { ApiTemplate } from "@src/types"; -import { RouteStepKeys } from "@src/utils/constants"; +import { RouteStep } from "@src/types/route-steps.type"; import { cn } from "@src/utils/styleUtils"; import { domainName, UrlService } from "@src/utils/urlUtils"; import Layout from "../layout/Layout"; @@ -86,7 +86,7 @@ export const TemplateDetail: React.FunctionComponent = ({ templateId, tem Deploy  diff --git a/apps/deploy-web/src/components/templates/UserTemplate.tsx b/apps/deploy-web/src/components/templates/UserTemplate.tsx index dfe6b7d06..cc865c6d9 100644 --- a/apps/deploy-web/src/components/templates/UserTemplate.tsx +++ b/apps/deploy-web/src/components/templates/UserTemplate.tsx @@ -16,8 +16,8 @@ import { getShortText } from "@src/hooks/useShortText"; import { useDeleteTemplate } from "@src/queries/useTemplateQuery"; import sdlStore from "@src/store/sdlStore"; import { ITemplate } from "@src/types"; +import { RouteStep } from "@src/types/route-steps.type"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { RouteStepKeys } from "@src/utils/constants"; import { roundDecimal } from "@src/utils/mathHelpers"; import { cn } from "@src/utils/styleUtils"; import { bytesToShrink } from "@src/utils/unitUtils"; @@ -135,7 +135,7 @@ export const UserTemplate: React.FunctionComponent = ({ id, template }) = content: template.sdl }); - router.push(UrlService.newDeployment({ step: RouteStepKeys.editDeployment })); + router.push(UrlService.newDeployment({ step: RouteStep.editDeployment })); }} > Deploy diff --git a/apps/deploy-web/src/components/user/UserProviders.tsx b/apps/deploy-web/src/components/user/UserProviders.tsx index 597d1fc6e..68d9e7b59 100644 --- a/apps/deploy-web/src/components/user/UserProviders.tsx +++ b/apps/deploy-web/src/components/user/UserProviders.tsx @@ -1,13 +1,13 @@ import { UserProvider } from "@auth0/nextjs-auth0/client"; import { UserInitLoader } from "@src/components/user/UserInitLoader"; -import { envConfig } from "@src/config/env.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { AnonymousUserProvider } from "@src/context/AnonymousUserProvider/AnonymousUserProvider"; import { authHttpService } from "@src/services/user/user-http.service"; import { FCWithChildren } from "@src/types/component"; export const UserProviders: FCWithChildren = ({ children }) => - envConfig.NEXT_PUBLIC_BILLING_ENABLED ? ( + browserEnvConfig.NEXT_PUBLIC_BILLING_ENABLED ? ( {children} diff --git a/apps/deploy-web/src/config/auth.config.ts b/apps/deploy-web/src/config/auth.config.ts new file mode 100644 index 000000000..f8b7cad35 --- /dev/null +++ b/apps/deploy-web/src/config/auth.config.ts @@ -0,0 +1,2 @@ +export const ANONYMOUS_USER_KEY = "anonymous-user"; +export const ANONYMOUS_USER_TOKEN_KEY = "anonymous-user-auth"; diff --git a/apps/deploy-web/src/config/browser-env.config.ts b/apps/deploy-web/src/config/browser-env.config.ts new file mode 100644 index 000000000..08a06cfc5 --- /dev/null +++ b/apps/deploy-web/src/config/browser-env.config.ts @@ -0,0 +1,18 @@ +import { castToValidatedDuringBuild } from "./env-config.schema"; + +export const browserEnvConfig = castToValidatedDuringBuild({ + NEXT_PUBLIC_API_BASE_URL: process.env.NEXT_PUBLIC_API_BASE_URL, + NEXT_PUBLIC_STATS_APP_URL: process.env.NEXT_PUBLIC_STATS_APP_URL, + NEXT_PUBLIC_PROVIDER_PROXY_URL: process.env.NEXT_PUBLIC_PROVIDER_PROXY_URL, + NEXT_PUBLIC_PROVIDER_PROXY_URL_WS: process.env.NEXT_PUBLIC_PROVIDER_PROXY_URL_WS, + NEXT_PUBLIC_DEFAULT_NETWORK_ID: process.env.NEXT_PUBLIC_DEFAULT_NETWORK_ID, + NEXT_PUBLIC_MASTER_WALLET_ADDRESS: process.env.NEXT_PUBLIC_MASTER_WALLET_ADDRESS, + NEXT_PUBLIC_BILLING_ENABLED: process.env.NEXT_PUBLIC_BILLING_ENABLED, + NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID: process.env.NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID, + NEXT_PUBLIC_MANAGED_WALLET_DENOM: process.env.NEXT_PUBLIC_MANAGED_WALLET_DENOM, + NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT: process.env.NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT, + NEXT_PUBLIC_NODE_ENV: process.env.NEXT_PUBLIC_NODE_ENV, + NEXT_PUBLIC_BASE_API_MAINNET_URL: process.env.NEXT_PUBLIC_BASE_API_MAINNET_URL, + NEXT_PUBLIC_BASE_API_TESTNET_URL: process.env.NEXT_PUBLIC_BASE_API_TESTNET_URL, + NEXT_PUBLIC_BASE_API_SANDBOX_URL: process.env.NEXT_PUBLIC_BASE_API_SANDBOX_URL +}); diff --git a/apps/deploy-web/src/config/denom.config.ts b/apps/deploy-web/src/config/denom.config.ts new file mode 100644 index 000000000..6df1052ce --- /dev/null +++ b/apps/deploy-web/src/config/denom.config.ts @@ -0,0 +1,18 @@ +import type { MainnetNetworkId, SandboxNetworkId } from "@akashnetwork/akashjs/build/types/network"; + +import { MAINNET_ID, SANDBOX_ID } from "@src/config/network.config"; + +export const UAKT_DENOM = "uakt"; +export const USDC_IBC_DENOMS: Record = { + [MAINNET_ID]: "ibc/170C677610AC31DF0904FFE09CD3B5C657492170E7E52372E48756B71E56F2F1", + [SANDBOX_ID]: "ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84" +}; + +const READABLE_AKT_DENOM = "uAKT"; +const READABLE_USDC_DENOM = "uUSDC"; + +export const READABLE_DENOMS = { + [UAKT_DENOM]: READABLE_AKT_DENOM, + [USDC_IBC_DENOMS[MAINNET_ID]]: READABLE_USDC_DENOM, + [USDC_IBC_DENOMS[SANDBOX_ID]]: READABLE_USDC_DENOM +}; diff --git a/apps/deploy-web/src/config/env-config.schema.ts b/apps/deploy-web/src/config/env-config.schema.ts new file mode 100644 index 000000000..5987ab42e --- /dev/null +++ b/apps/deploy-web/src/config/env-config.schema.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; + +const networkId = z.enum(["mainnet", "sandbox", "testnet"]); +const coercedBoolean = () => z.enum(["true", "false"]).transform(val => val === "true"); + +export const browserEnvSchema = z.object({ + NEXT_PUBLIC_MASTER_WALLET_ADDRESS: z.string(), + NEXT_PUBLIC_BILLING_ENABLED: coercedBoolean().optional().default("false"), + NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID: networkId.optional().default("mainnet"), + NEXT_PUBLIC_DEFAULT_NETWORK_ID: networkId.optional().default("mainnet"), + NEXT_PUBLIC_MANAGED_WALLET_DENOM: z.enum(["uakt", "usdc"]).optional().default("usdc"), + NEXT_PUBLIC_API_BASE_URL: z.string().url(), + NEXT_PUBLIC_STATS_APP_URL: z.string().url(), + NEXT_PUBLIC_PROVIDER_PROXY_URL: z.string().url(), + NEXT_PUBLIC_PROVIDER_PROXY_URL_WS: z.string().url(), + NEXT_PUBLIC_NODE_ENV: z.enum(["development", "production", "test"]).optional().default("development"), + NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT: z.number({ coerce: true }).optional().default(500000), + NEXT_PUBLIC_BASE_API_MAINNET_URL: z.string().url(), + NEXT_PUBLIC_BASE_API_TESTNET_URL: z.string().url(), + NEXT_PUBLIC_BASE_API_SANDBOX_URL: z.string().url() +}); + +export const serverEnvSchema = browserEnvSchema.extend({ + MAINTENANCE_MODE: coercedBoolean().optional().default("false"), + AUTH0_SECRET: z.string(), + AUTH0_BASE_URL: z.string().url(), + AUTH0_ISSUER_BASE_URL: z.string().url(), + AUTH0_CLIENT_ID: z.string(), + AUTH0_CLIENT_SECRET: z.string(), + AUTH0_AUDIENCE: z.string(), + AUTH0_SCOPE: z.string() +}); + +export type BrowserEnvConfig = z.infer; +export type ServerEnvConfig = z.infer; + +export const castToValidatedDuringBuild = (config: Record) => config as unknown as BrowserEnvConfig; +export const castToValidatedOnStartup = (config: Record) => config as unknown as ServerEnvConfig; diff --git a/apps/deploy-web/src/config/env.config.ts b/apps/deploy-web/src/config/env.config.ts deleted file mode 100644 index 8fd00f172..000000000 --- a/apps/deploy-web/src/config/env.config.ts +++ /dev/null @@ -1,2 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-var-requires -export const { envConfig } = require("../../env.config"); diff --git a/apps/deploy-web/src/config/graph.config.ts b/apps/deploy-web/src/config/graph.config.ts new file mode 100644 index 000000000..de6acce2e --- /dev/null +++ b/apps/deploy-web/src/config/graph.config.ts @@ -0,0 +1,5 @@ +export const SELECTED_RANGE_VALUES: Record = { + "7D": 7, + "1M": 30, + ALL: Number.MAX_SAFE_INTEGER +}; diff --git a/apps/deploy-web/src/config/network.config.ts b/apps/deploy-web/src/config/network.config.ts new file mode 100644 index 000000000..516a3c8e4 --- /dev/null +++ b/apps/deploy-web/src/config/network.config.ts @@ -0,0 +1,5 @@ +import type { MainnetNetworkId, SandboxNetworkId, TestnetNetworkId } from "@akashnetwork/akashjs/build/types/network"; + +export const MAINNET_ID: MainnetNetworkId = "mainnet"; +export const SANDBOX_ID: SandboxNetworkId = "sandbox"; +export const TESTNET_ID: TestnetNetworkId = "testnet"; diff --git a/apps/deploy-web/src/config/server-env.config.ts b/apps/deploy-web/src/config/server-env.config.ts new file mode 100644 index 000000000..84dc73c28 --- /dev/null +++ b/apps/deploy-web/src/config/server-env.config.ts @@ -0,0 +1,5 @@ +import "@akashnetwork/env-loader"; + +import { castToValidatedOnStartup } from "./env-config.schema"; + +export const serverEnvConfig = castToValidatedOnStartup(process.env); diff --git a/apps/deploy-web/src/config/tx.config.ts b/apps/deploy-web/src/config/tx.config.ts new file mode 100644 index 000000000..de646ed5d --- /dev/null +++ b/apps/deploy-web/src/config/tx.config.ts @@ -0,0 +1 @@ +export const TX_FEE_BUFFER = 10000; diff --git a/apps/deploy-web/src/config/ui.config.ts b/apps/deploy-web/src/config/ui.config.ts new file mode 100644 index 000000000..0d24e154b --- /dev/null +++ b/apps/deploy-web/src/config/ui.config.ts @@ -0,0 +1 @@ +export const ACCOUNT_BAR_HEIGHT = 57; diff --git a/apps/deploy-web/src/context/BackgroundTaskProvider/BackgroundTaskProvider.tsx b/apps/deploy-web/src/context/BackgroundTaskProvider/BackgroundTaskProvider.tsx index 2eeab2c33..99324e117 100644 --- a/apps/deploy-web/src/context/BackgroundTaskProvider/BackgroundTaskProvider.tsx +++ b/apps/deploy-web/src/context/BackgroundTaskProvider/BackgroundTaskProvider.tsx @@ -4,7 +4,7 @@ import { Button, Snackbar } from "@akashnetwork/ui/components"; import FileSaver from "file-saver"; import { useSnackbar } from "notistack"; -import { PROVIDER_PROXY_URL_WS } from "@src/utils/constants"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useCertificate } from "../CertificateProvider"; const getPrintCommand = os => { @@ -34,7 +34,7 @@ export const BackgroundTaskProvider = ({ children }) => { const downloadLogs = async (hostUri: string, dseq: string, gseq: number, oseq: number, isLogs: boolean) => { return new Promise((resolve, reject) => { - const ws = new WebSocket(PROVIDER_PROXY_URL_WS); + const ws = new WebSocket(browserEnvConfig.NEXT_PUBLIC_PROVIDER_PROXY_URL_WS); let isCancelled = false; let isFinished = false; @@ -123,7 +123,7 @@ export const BackgroundTaskProvider = ({ children }) => { }; const downloadFileFromShell = async (hostUri: string, dseq: string, gseq: number, oseq: number, service: string, filePath: string) => { - const ws = new WebSocket(PROVIDER_PROXY_URL_WS); + const ws = new WebSocket(browserEnvConfig.NEXT_PUBLIC_PROVIDER_PROXY_URL_WS); let isCancelled = false; let isFinished = false; diff --git a/apps/deploy-web/src/context/CertificateProvider/CertificateProviderContext.tsx b/apps/deploy-web/src/context/CertificateProvider/CertificateProviderContext.tsx index b103b4e2e..537bdf268 100644 --- a/apps/deploy-web/src/context/CertificateProvider/CertificateProviderContext.tsx +++ b/apps/deploy-web/src/context/CertificateProvider/CertificateProviderContext.tsx @@ -6,9 +6,9 @@ import axios from "axios"; import { event } from "nextjs-google-analytics"; import { useSnackbar } from "notistack"; +import { networkService } from "@src/services/network/network.service"; import { RestApiCertificatesResponseType } from "@src/types/certificate"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { networkVersion } from "@src/utils/constants"; import { TransactionMessageData } from "@src/utils/TransactionMessageData"; import { getStorageWallets, updateWallet } from "@src/utils/walletUtils"; import { useSettings } from "../SettingsProvider"; @@ -80,7 +80,7 @@ export const CertificateProvider = ({ children }) => { try { const response = await axios.get( - `${apiEndpoint}/akash/cert/${networkVersion}/certificates/list?filter.state=valid&filter.owner=${address}` + `${apiEndpoint}/akash/cert/${networkService.networkVersion}/certificates/list?filter.state=valid&filter.owner=${address}` ); const certs = (response.data.certificates || []).map(cert => { const parsed = atob(cert.certificate.cert); diff --git a/apps/deploy-web/src/context/ChainParamProvider/ChainParamProvider.tsx b/apps/deploy-web/src/context/ChainParamProvider/ChainParamProvider.tsx index 4eda40942..4a353e769 100644 --- a/apps/deploy-web/src/context/ChainParamProvider/ChainParamProvider.tsx +++ b/apps/deploy-web/src/context/ChainParamProvider/ChainParamProvider.tsx @@ -2,9 +2,9 @@ import React from "react"; import { useEffect } from "react"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { useUsdcDenom } from "@src/hooks/useDenom"; import { useDepositParams } from "@src/queries/useSettings"; -import { uAktDenom } from "@src/utils/constants"; import { udenomToDenom } from "@src/utils/mathHelpers"; import { uaktToAKT } from "@src/utils/priceUtils"; import { useSettings } from "../SettingsProvider"; @@ -24,7 +24,7 @@ export const ChainParamProvider = ({ children }) => { const { isSettingsInit } = useSettings(); const { data: depositParams, refetch: getDepositParams } = useDepositParams({ enabled: false }); const usdcDenom = useUsdcDenom(); - const aktMinDeposit = depositParams ? uaktToAKT(parseFloat(depositParams.find(x => x.denom === uAktDenom)?.amount || "") || 0) : 0; + const aktMinDeposit = depositParams ? uaktToAKT(parseFloat(depositParams.find(x => x.denom === UAKT_DENOM)?.amount || "") || 0) : 0; const usdcMinDeposit = depositParams ? udenomToDenom(parseFloat(depositParams.find(x => x.denom === usdcDenom)?.amount || "") || 0) : 0; const minDeposit = { akt: aktMinDeposit, usdc: usdcMinDeposit }; diff --git a/apps/deploy-web/src/context/PricingProvider/PricingProvider.tsx b/apps/deploy-web/src/context/PricingProvider/PricingProvider.tsx index 17deea308..7205a4c0a 100644 --- a/apps/deploy-web/src/context/PricingProvider/PricingProvider.tsx +++ b/apps/deploy-web/src/context/PricingProvider/PricingProvider.tsx @@ -1,9 +1,9 @@ "use client"; import React from "react"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { useUsdcDenom } from "@src/hooks/useDenom"; import { useMarketData } from "@src/queries"; -import { uAktDenom } from "@src/utils/constants"; import { roundDecimal } from "@src/utils/mathHelpers"; type ContextType = { @@ -33,7 +33,7 @@ export const PricingProvider = ({ children }) => { const getPriceForDenom = (denom: string) => { switch (denom) { - case uAktDenom: + case UAKT_DENOM: return marketData?.price || 0; case usdcIbcDenom: return 1; // TODO Get price from API diff --git a/apps/deploy-web/src/context/SettingsProvider/SettingsProviderContext.tsx b/apps/deploy-web/src/context/SettingsProvider/SettingsProviderContext.tsx index 12557ee8d..e950dea3a 100644 --- a/apps/deploy-web/src/context/SettingsProvider/SettingsProviderContext.tsx +++ b/apps/deploy-web/src/context/SettingsProvider/SettingsProviderContext.tsx @@ -1,14 +1,15 @@ "use client"; import React, { FC, ReactNode, useCallback, useEffect, useState } from "react"; +import type { NetworkId } from "@akashnetwork/akashjs/build/types/network"; import axios from "axios"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useLocalStorage } from "@src/hooks/useLocalStorage"; import { usePreviousRoute } from "@src/hooks/usePreviousRoute"; import { queryClient } from "@src/queries"; import { initiateNetworkData, networks } from "@src/store/networkStore"; import { NodeStatus } from "@src/types/node"; import { mainnetNodes } from "@src/utils/apiUtils"; -import { defaultNetworkId } from "@src/utils/constants"; import { initAppTypes } from "@src/utils/init"; import { migrateLocalStorage } from "@src/utils/localStorage"; @@ -58,7 +59,7 @@ export const SettingsProvider: FC<{ children: ReactNode }> = ({ children }) => { const [isSettingsInit, setIsSettingsInit] = useState(false); const [isRefreshingNodeStatus, setIsRefreshingNodeStatus] = useState(false); const { getLocalStorageItem, setLocalStorageItem } = useLocalStorage(); - const [selectedNetworkId, setSelectedNetworkId] = useState(defaultNetworkId); + const [selectedNetworkId, setSelectedNetworkId] = useState(browserEnvConfig.NEXT_PUBLIC_DEFAULT_NETWORK_ID); const { isCustomNode, customNode, nodes, apiEndpoint, rpcEndpoint } = settings; usePreviousRoute(); @@ -77,7 +78,7 @@ export const SettingsProvider: FC<{ children: ReactNode }> = ({ children }) => { // Init app types based on the selected network id initAppTypes(); - const _selectedNetworkId = localStorage.getItem("selectedNetworkId") || defaultNetworkId; + const _selectedNetworkId = (localStorage.getItem("selectedNetworkId") as NetworkId | null) || browserEnvConfig.NEXT_PUBLIC_DEFAULT_NETWORK_ID; setSelectedNetworkId(_selectedNetworkId); diff --git a/apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx b/apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx index ccc0ba783..0aa371932 100644 --- a/apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx +++ b/apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx @@ -13,6 +13,8 @@ import { event } from "nextjs-google-analytics"; import { SnackbarKey, useSnackbar } from "notistack"; import { LoadingState, TransactionModal } from "@src/components/layout/TransactionModal"; +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { useAllowance } from "@src/hooks/useAllowance"; import { useUsdcDenom } from "@src/hooks/useDenom"; import { useManagedWallet } from "@src/hooks/useManagedWallet"; @@ -21,7 +23,6 @@ import { useWhen } from "@src/hooks/useWhen"; import { txHttpService } from "@src/services/http/http.service"; import networkStore from "@src/store/networkStore"; import { AnalyticsEvents } from "@src/utils/analytics"; -import { STATS_APP_URL, uAktDenom } from "@src/utils/constants"; import { customRegistry } from "@src/utils/customRegistry"; import { UrlService } from "@src/utils/urlUtils"; import { getSelectedStorageWallet, getStorageWallets, updateStorageManagedWallet, updateStorageWallets } from "@src/utils/walletUtils"; @@ -358,7 +359,7 @@ export const WalletProvider = ({ children }) => { if (client) { const balances = await client.getAllBalances(_address as string); - const uaktBalance = balances.find(b => b.denom === uAktDenom); + const uaktBalance = balances.find(b => b.denom === UAKT_DENOM); const usdcBalance = balances.find(b => b.denom === usdcIbcDenom); const walletBalances = { @@ -412,7 +413,7 @@ export function useWallet() { const TransactionSnackbarContent = ({ snackMessage, transactionHash }) => { const selectedNetwork = networkStore.useSelectedNetwork(); - const txUrl = transactionHash && `${STATS_APP_URL}/transactions/${transactionHash}?network=${selectedNetwork.id}`; + const txUrl = transactionHash && `${browserEnvConfig.NEXT_PUBLIC_STATS_APP_URL}/transactions/${transactionHash}?network=${selectedNetwork.id}`; return ( <> diff --git a/apps/deploy-web/src/hooks/useDenom.ts b/apps/deploy-web/src/hooks/useDenom.ts index 87d9e2f18..ff20c1353 100644 --- a/apps/deploy-web/src/hooks/useDenom.ts +++ b/apps/deploy-web/src/hooks/useDenom.ts @@ -1,14 +1,14 @@ +import { USDC_IBC_DENOMS } from "@src/config/denom.config"; import networkStore from "@src/store/networkStore"; -import { usdcIbcDenoms } from "@src/utils/constants"; export const useUsdcDenom = () => { const selectedNetwork = networkStore.useSelectedNetwork(); - return usdcIbcDenoms[selectedNetwork.id]; + return USDC_IBC_DENOMS[selectedNetwork.id]; }; export const getUsdcDenom = () => { const selectedNetwork = networkStore.getSelectedNetwork(); - return usdcIbcDenoms[selectedNetwork.id]; + return USDC_IBC_DENOMS[selectedNetwork.id]; }; export const useSdlDenoms = () => { diff --git a/apps/deploy-web/src/hooks/useManagedWallet.ts b/apps/deploy-web/src/hooks/useManagedWallet.ts index cbee4f997..ea53bba9d 100644 --- a/apps/deploy-web/src/hooks/useManagedWallet.ts +++ b/apps/deploy-web/src/hooks/useManagedWallet.ts @@ -1,7 +1,7 @@ import { useEffect, useMemo } from "react"; import { useAtom } from "jotai/index"; -import { envConfig } from "@src/config/env.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useUser } from "@src/hooks/useUser"; import { useWhen } from "@src/hooks/useWhen"; import { useCreateManagedWalletMutation, useManagedWalletQuery } from "@src/queries/useManagedWalletQuery"; @@ -14,14 +14,14 @@ import { updateStorageManagedWallet } from "@src/utils/walletUtils"; -const isBillingEnabled = envConfig.NEXT_PUBLIC_BILLING_ENABLED; -const { NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID } = envConfig; +const { NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID, NEXT_PUBLIC_BILLING_ENABLED } = browserEnvConfig; +const isBillingEnabled = NEXT_PUBLIC_BILLING_ENABLED; const storedManagedWallet = getStorageManagedWallet(); export const useManagedWallet = () => { const user = useUser(); - const { data: queried, isFetched, isLoading: isFetching, refetch } = useManagedWalletQuery(isBillingEnabled && user?.id); + const { data: queried, isFetched, isLoading: isFetching, refetch } = useManagedWalletQuery(isBillingEnabled ? user?.id : undefined); const { mutate: create, data: created, isLoading: isCreating, isSuccess: isCreated } = useCreateManagedWalletMutation(); const wallet = useMemo(() => queried || storedManagedWallet || created, [queried, created]); const isLoading = isFetching || isCreating; diff --git a/apps/deploy-web/src/hooks/useManagedWalletDenom.ts b/apps/deploy-web/src/hooks/useManagedWalletDenom.ts index 5ebc07cbc..d6435a48a 100644 --- a/apps/deploy-web/src/hooks/useManagedWalletDenom.ts +++ b/apps/deploy-web/src/hooks/useManagedWalletDenom.ts @@ -1,4 +1,4 @@ -import { envConfig } from "@src/config/env.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useWallet } from "@src/context/WalletProvider"; import { useUsdcDenom } from "@src/hooks/useDenom"; @@ -6,5 +6,5 @@ export const useManagedWalletDenom = () => { const wallet = useWallet(); const usdcDenom = useUsdcDenom(); - return wallet.isManaged && envConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "usdc" ? usdcDenom : "uakt"; + return wallet.isManaged && browserEnvConfig.NEXT_PUBLIC_MANAGED_WALLET_DENOM === "usdc" ? usdcDenom : "uakt"; }; diff --git a/apps/deploy-web/src/hooks/useStoredAnonymousUser.ts b/apps/deploy-web/src/hooks/useStoredAnonymousUser.ts index cfd97336c..5f9fa3a98 100644 --- a/apps/deploy-web/src/hooks/useStoredAnonymousUser.ts +++ b/apps/deploy-web/src/hooks/useStoredAnonymousUser.ts @@ -1,10 +1,10 @@ import { useMemo } from "react"; -import { envConfig } from "@src/config/env.config"; +import { ANONYMOUS_USER_KEY, ANONYMOUS_USER_TOKEN_KEY } from "@src/config/auth.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { useCustomUser } from "@src/hooks/useCustomUser"; import { useWhen } from "@src/hooks/useWhen"; import { useAnonymousUserQuery, UserOutput } from "@src/queries/useAnonymousUserQuery"; -import { ANONYMOUS_USER_KEY, ANONYMOUS_USER_TOKEN_KEY } from "@src/utils/constants"; type UseApiUserResult = { user?: UserOutput; @@ -17,7 +17,7 @@ const storedAnonymousUser: UserOutput | undefined = storedAnonymousUserStr ? JSO export const useStoredAnonymousUser = (): UseApiUserResult => { const { user: registeredUser, isLoading: isLoadingRegisteredUser } = useCustomUser(); const { user, isLoading, token } = useAnonymousUserQuery(storedAnonymousUser?.id, { - enabled: envConfig.NEXT_PUBLIC_BILLING_ENABLED && !registeredUser && !isLoadingRegisteredUser + enabled: browserEnvConfig.NEXT_PUBLIC_BILLING_ENABLED && !registeredUser && !isLoadingRegisteredUser }); useWhen(user, () => localStorage.setItem("anonymous-user", JSON.stringify(user))); diff --git a/apps/deploy-web/src/hooks/useWalletBalance.ts b/apps/deploy-web/src/hooks/useWalletBalance.ts index 2429f5ca6..a7ba46a7a 100644 --- a/apps/deploy-web/src/hooks/useWalletBalance.ts +++ b/apps/deploy-web/src/hooks/useWalletBalance.ts @@ -1,9 +1,10 @@ import { useEffect, useState } from "react"; +import { UAKT_DENOM } from "@src/config/denom.config"; +import { TX_FEE_BUFFER } from "@src/config/tx.config"; import { useChainParam } from "@src/context/ChainParamProvider"; import { usePricing } from "@src/context/PricingProvider"; import { useWallet } from "@src/context/WalletProvider"; -import { txFeeBuffer, uAktDenom } from "@src/utils/constants"; import { udenomToDenom } from "@src/utils/mathHelpers"; import { uaktToAKT } from "@src/utils/priceUtils"; import { useUsdcDenom } from "./useDenom"; @@ -44,12 +45,12 @@ export const useDenomData = (denom: string) => { if (isLoaded && walletBalances && minDeposit?.akt && minDeposit?.usdc && price) { let depositData: DenomData | null = null; switch (denom) { - case uAktDenom: + case UAKT_DENOM: depositData = { min: minDeposit.akt, label: "AKT", balance: uaktToAKT(walletBalances.uakt, 6), - inputMax: uaktToAKT(Math.max(walletBalances.uakt - txFeeBuffer, 0), 6) + inputMax: uaktToAKT(Math.max(walletBalances.uakt - TX_FEE_BUFFER, 0), 6) }; break; case usdcIbcDenom: @@ -57,7 +58,7 @@ export const useDenomData = (denom: string) => { min: minDeposit.usdc, label: "USDC", balance: udenomToDenom(walletBalances.usdc, 6), - inputMax: udenomToDenom(Math.max(walletBalances.usdc - txFeeBuffer, 0), 6) + inputMax: udenomToDenom(Math.max(walletBalances.usdc - TX_FEE_BUFFER, 0), 6) }; break; default: diff --git a/apps/deploy-web/src/instrumentation.ts b/apps/deploy-web/src/instrumentation.ts new file mode 100644 index 000000000..adfd92e62 --- /dev/null +++ b/apps/deploy-web/src/instrumentation.ts @@ -0,0 +1,13 @@ +export async function register() { + if (process.env.NEXT_RUNTIME === "nodejs") { + try { + await import("@akashnetwork/env-loader"); + const { serverEnvSchema } = await import("./config/env-config.schema"); + + serverEnvSchema.parse(process.env); + } catch (error) { + console.error("Failed to validate server environment variables", error); + process.exit(1); + } + } +} diff --git a/apps/deploy-web/src/middleware.ts b/apps/deploy-web/src/middleware.ts index 682982778..f398d90ad 100644 --- a/apps/deploy-web/src/middleware.ts +++ b/apps/deploy-web/src/middleware.ts @@ -1,16 +1,16 @@ import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; -import { isMaintenanceMode } from "./utils/constants"; +const { MAINTENANCE_MODE } = process.env; export function middleware(request: NextRequest) { const maintenancePage = "/maintenance"; - if (isMaintenanceMode && !request.nextUrl.pathname.startsWith(maintenancePage)) { + if (MAINTENANCE_MODE && !request.nextUrl.pathname.startsWith(maintenancePage)) { const fromPath = request.nextUrl.pathname + request.nextUrl.search; console.log("Redirecting to maintenance page from " + fromPath); return NextResponse.redirect(new URL(`${maintenancePage}?return=${encodeURIComponent(fromPath)}`, request.url), 307); // 307 - temporary redirect - } else if (!isMaintenanceMode && request.nextUrl.pathname.startsWith(maintenancePage)) { + } else if (!MAINTENANCE_MODE && request.nextUrl.pathname.startsWith(maintenancePage)) { const returnPath = getReturnPath(request); console.log("Redirecting from maintenance page to " + returnPath); diff --git a/apps/deploy-web/src/pages/api/auth/[...auth0].ts b/apps/deploy-web/src/pages/api/auth/[...auth0].ts index 32ecd6f02..c5a78639b 100644 --- a/apps/deploy-web/src/pages/api/auth/[...auth0].ts +++ b/apps/deploy-web/src/pages/api/auth/[...auth0].ts @@ -3,7 +3,7 @@ import { handleAuth, handleLogin, handleProfile } from "@auth0/nextjs-auth0"; import axios, { AxiosHeaders } from "axios"; import type { NextApiRequest, NextApiResponse } from "next"; -import { BASE_API_MAINNET_URL } from "@src/utils/constants"; +import { serverEnvConfig } from "@src/config/server-env.config"; export default handleAuth({ async login(req: NextApiRequest, res: NextApiResponse) { @@ -33,7 +33,7 @@ export default handleAuth({ } const userSettings = await axios.post( - `${BASE_API_MAINNET_URL}/user/tokenInfo`, + `${serverEnvConfig.NEXT_PUBLIC_BASE_API_MAINNET_URL}/user/tokenInfo`, { wantedUsername: session.user.nickname, email: session.user.email, diff --git a/apps/deploy-web/src/pages/api/proxy/[...path].ts b/apps/deploy-web/src/pages/api/proxy/[...path].ts index f80192a33..dfe9235c2 100644 --- a/apps/deploy-web/src/pages/api/proxy/[...path].ts +++ b/apps/deploy-web/src/pages/api/proxy/[...path].ts @@ -1,7 +1,7 @@ import { getSession } from "@auth0/nextjs-auth0"; import httpProxy from "http-proxy"; -import { BASE_API_MAINNET_URL } from "@src/utils/constants"; +import { serverEnvConfig } from "@src/config/server-env.config"; export default async (req, res) => { // removes the api prefix from url @@ -19,7 +19,7 @@ export default async (req, res) => { const proxy = httpProxy.createProxyServer({ changeOrigin: true, - target: BASE_API_MAINNET_URL, + target: serverEnvConfig.NEXT_PUBLIC_BASE_API_MAINNET_URL, secure: false, autoRewrite: false }); diff --git a/apps/deploy-web/src/pages/profile/[username]/index.tsx b/apps/deploy-web/src/pages/profile/[username]/index.tsx index 1ff7cb45a..96fc5ae5b 100644 --- a/apps/deploy-web/src/pages/profile/[username]/index.tsx +++ b/apps/deploy-web/src/pages/profile/[username]/index.tsx @@ -1,8 +1,8 @@ import axios from "axios"; import { UserProfile } from "@src/components/user/UserProfile"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { IUserSetting } from "@src/types/user"; -import { BASE_API_MAINNET_URL } from "@src/utils/constants"; type Props = { username: string; @@ -37,6 +37,6 @@ export async function getServerSideProps({ params }) { } async function fetchUser(username: string) { - const response = await axios.get(`${BASE_API_MAINNET_URL}/user/byUsername/${username}`); + const response = await axios.get(`${browserEnvConfig.NEXT_PUBLIC_BASE_API_MAINNET_URL}/user/byUsername/${username}`); return response.data; } diff --git a/apps/deploy-web/src/pages/providers/[owner]/index.tsx b/apps/deploy-web/src/pages/providers/[owner]/index.tsx index e7428d140..bb04a496b 100644 --- a/apps/deploy-web/src/pages/providers/[owner]/index.tsx +++ b/apps/deploy-web/src/pages/providers/[owner]/index.tsx @@ -1,8 +1,8 @@ import axios from "axios"; import { ProviderDetail } from "@src/components/providers/ProviderDetail"; +import { serverApiUrlService } from "@src/services/api-url/server-api-url.service"; import { ApiProviderDetail } from "@src/types/provider"; -import { getNetworkBaseApiUrl } from "@src/utils/constants"; type Props = { owner: string; @@ -16,7 +16,7 @@ const ProviderDetailPage: React.FunctionComponent = ({ owner, _provider } export default ProviderDetailPage; export async function getServerSideProps({ params, query }) { - const apiUrl = getNetworkBaseApiUrl(query.network as string); + const apiUrl = serverApiUrlService.getBaseApiUrlFor(query.network as string); const response = await axios.get(`${apiUrl}/v1/providers/${params?.owner}`); return { diff --git a/apps/deploy-web/src/pages/template/[id]/index.tsx b/apps/deploy-web/src/pages/template/[id]/index.tsx index ace724f28..cbb2df68c 100644 --- a/apps/deploy-web/src/pages/template/[id]/index.tsx +++ b/apps/deploy-web/src/pages/template/[id]/index.tsx @@ -2,8 +2,8 @@ import { getSession } from "@auth0/nextjs-auth0"; import axios from "axios"; import { UserTemplate } from "@src/components/templates/UserTemplate"; +import { serverEnvConfig } from "@src/config/server-env.config"; import { ITemplate } from "@src/types"; -import { BASE_API_MAINNET_URL } from "@src/utils/constants"; type Props = { id: string; @@ -29,7 +29,7 @@ export const getServerSideProps = async function getServerSideProps({ params, re }; } - const response = await axios.get(`${BASE_API_MAINNET_URL}/user/template/${params?.id}`, config); + const response = await axios.get(`${serverEnvConfig.NEXT_PUBLIC_BASE_API_MAINNET_URL}/user/template/${params?.id}`, config); return { props: { diff --git a/apps/deploy-web/src/pages/templates/[templateId]/index.tsx b/apps/deploy-web/src/pages/templates/[templateId]/index.tsx index 1dc6eddf2..0c4a11ac9 100644 --- a/apps/deploy-web/src/pages/templates/[templateId]/index.tsx +++ b/apps/deploy-web/src/pages/templates/[templateId]/index.tsx @@ -1,8 +1,8 @@ import axios from "axios"; import { TemplateDetail } from "@src/components/templates/TemplateDetail"; +import { serverEnvConfig } from "@src/config/server-env.config"; import { ApiTemplate } from "@src/types"; -import { BASE_API_MAINNET_URL } from "@src/utils/constants"; type Props = { templateId: string; @@ -16,7 +16,7 @@ const TemplateDetailPage: React.FunctionComponent = ({ templateId, templa export default TemplateDetailPage; export async function getServerSideProps({ params }) { - const response = await axios.get(`${BASE_API_MAINNET_URL}/templates`); + const response = await axios.get(`${serverEnvConfig.NEXT_PUBLIC_BASE_API_MAINNET_URL}/templates`); const categories = response.data.filter(x => (x.templates || []).length > 0); categories.forEach(c => { c.templates.forEach(t => (t.category = c.title)); diff --git a/apps/deploy-web/src/queries/useBalancesQuery.ts b/apps/deploy-web/src/queries/useBalancesQuery.ts index f5e09752a..d2a289df3 100644 --- a/apps/deploy-web/src/queries/useBalancesQuery.ts +++ b/apps/deploy-web/src/queries/useBalancesQuery.ts @@ -1,6 +1,7 @@ import { useQuery } from "react-query"; import axios from "axios"; +import { UAKT_DENOM } from "@src/config/denom.config"; import { getUsdcDenom } from "@src/hooks/useDenom"; import { Balances } from "@src/types"; import { @@ -11,7 +12,6 @@ import { RestApiUnbondingsResponseType } from "@src/types/balances"; import { ApiUrlService } from "@src/utils/apiUtils"; -import { uAktDenom } from "@src/utils/constants"; import { useSettings } from "../context/SettingsProvider"; import { QueryKeys } from "./queryKeys"; @@ -34,14 +34,16 @@ async function getBalances(apiEndpoint: string, address: string): Promise b.denom === uAktDenom) ? parseFloat(balanceData.balances.find(b => b.denom === uAktDenom)?.amount || "0") : 0; + const balance = balanceData.balances.some(b => b.denom === UAKT_DENOM) + ? parseFloat(balanceData.balances.find(b => b.denom === UAKT_DENOM)?.amount || "0") + : 0; const balanceUsdc = balanceData.balances.some(b => b.denom === usdcIbcDenom) ? parseFloat(balanceData.balances.find(b => b.denom === usdcIbcDenom)?.amount || "0") : 0; // Rewards const rewardsData = rewardsResponse.data; - const rewards = rewardsData.total.some(b => b.denom === uAktDenom) ? parseFloat(rewardsData.total.find(b => b.denom === uAktDenom)?.amount || "0") : 0; + const rewards = rewardsData.total.some(b => b.denom === UAKT_DENOM) ? parseFloat(rewardsData.total.find(b => b.denom === UAKT_DENOM)?.amount || "0") : 0; // Redelegations const redelegationsData = redelegationsResponse.data; @@ -64,9 +66,9 @@ async function getBalances(apiEndpoint: string, address: string): Promise(ApiUrlService.delegations(apiEndpoint, address)); const delegationsData = delegationsResponse.data; - delegations = delegationsData.delegation_responses.some(b => b.balance.denom === uAktDenom) + delegations = delegationsData.delegation_responses.some(b => b.balance.denom === UAKT_DENOM) ? delegationsData.delegation_responses - .filter(x => x.balance.denom === uAktDenom) + .filter(x => x.balance.denom === UAKT_DENOM) .map(x => parseFloat(x.balance.amount)) .reduce((a, b) => a + b, 0) : 0; diff --git a/apps/deploy-web/src/queries/useLeaseQuery.ts b/apps/deploy-web/src/queries/useLeaseQuery.ts index 16a656cc0..049605f4e 100644 --- a/apps/deploy-web/src/queries/useLeaseQuery.ts +++ b/apps/deploy-web/src/queries/useLeaseQuery.ts @@ -1,10 +1,10 @@ import { useQuery } from "react-query"; import axios from "axios"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { LocalCert } from "@src/context/CertificateProvider/CertificateProviderContext"; import { LeaseDto } from "@src/types/deployment"; import { ApiUrlService, loadWithPagination } from "@src/utils/apiUtils"; -import { PROVIDER_PROXY_URL } from "@src/utils/constants"; import { leaseToDto } from "@src/utils/deploymentDetailUtils"; import { useCertificate } from "../context/CertificateProvider"; import { useSettings } from "../context/SettingsProvider"; @@ -50,7 +50,7 @@ async function getLeaseStatus(providerUri: string, lease: LeaseDto, localCert: L if (!providerUri) return null; const leaseStatusPath = `${providerUri}/lease/${lease.dseq}/${lease.gseq}/${lease.oseq}/status`; - const response = await axios.post(PROVIDER_PROXY_URL, { + const response = await axios.post(browserEnvConfig.NEXT_PUBLIC_PROVIDER_PROXY_URL, { method: "GET", url: leaseStatusPath, certPem: localCert?.certPem, diff --git a/apps/deploy-web/src/queries/useProvidersQuery.ts b/apps/deploy-web/src/queries/useProvidersQuery.ts index 84317b130..5fd03e886 100644 --- a/apps/deploy-web/src/queries/useProvidersQuery.ts +++ b/apps/deploy-web/src/queries/useProvidersQuery.ts @@ -1,10 +1,10 @@ import { useQuery } from "react-query"; import axios from "axios"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { ApiProviderDetail, ApiProviderList, ApiProviderRegion, Auditor } from "@src/types/provider"; import { ProviderAttributesSchema } from "@src/types/providerAttributes"; import { ApiUrlService } from "@src/utils/apiUtils"; -import { PROVIDER_PROXY_URL } from "@src/utils/constants"; import { getNetworkCapacityDto, providerStatusToDto } from "@src/utils/providerUtils"; import { QueryKeys } from "./queryKeys"; @@ -24,8 +24,8 @@ async function getProviderStatus(providerUri: string) { if (!providerUri) return null; try { - const statusResponse = await axios.post(PROVIDER_PROXY_URL, { url: `${providerUri}/status`, method: "GET" }); - const versionResponse = await axios.post(PROVIDER_PROXY_URL, { url: `${providerUri}/version`, method: "GET" }); + const statusResponse = await axios.post(browserEnvConfig.NEXT_PUBLIC_PROVIDER_PROXY_URL, { url: `${providerUri}/status`, method: "GET" }); + const versionResponse = await axios.post(browserEnvConfig.NEXT_PUBLIC_PROVIDER_PROXY_URL, { url: `${providerUri}/version`, method: "GET" }); return providerStatusToDto(statusResponse.data, versionResponse?.data || {}); } catch (error) { console.log(error); diff --git a/apps/deploy-web/src/services/api-url/api-url.service.ts b/apps/deploy-web/src/services/api-url/api-url.service.ts new file mode 100644 index 000000000..67ac94003 --- /dev/null +++ b/apps/deploy-web/src/services/api-url/api-url.service.ts @@ -0,0 +1,19 @@ +import type { ServerEnvConfig } from "@src/config/env-config.schema"; +import { SANDBOX_ID, TESTNET_ID } from "@src/config/network.config"; + +export class ApiUrlService { + constructor( + private readonly config: Pick + ) {} + + getBaseApiUrlFor(network: string) { + switch (network) { + case TESTNET_ID: + return this.config.NEXT_PUBLIC_BASE_API_TESTNET_URL; + case SANDBOX_ID: + return this.config.NEXT_PUBLIC_BASE_API_SANDBOX_URL; + default: + return this.config.NEXT_PUBLIC_BASE_API_MAINNET_URL; + } + } +} diff --git a/apps/deploy-web/src/services/api-url/browser-api-url.service.ts b/apps/deploy-web/src/services/api-url/browser-api-url.service.ts new file mode 100644 index 000000000..ac36366ef --- /dev/null +++ b/apps/deploy-web/src/services/api-url/browser-api-url.service.ts @@ -0,0 +1,4 @@ +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { ApiUrlService } from "@src/services/api-url/api-url.service"; + +export const browserApiUrlService = new ApiUrlService(browserEnvConfig); diff --git a/apps/deploy-web/src/services/api-url/server-api-url.service.ts b/apps/deploy-web/src/services/api-url/server-api-url.service.ts new file mode 100644 index 000000000..4c55ddcee --- /dev/null +++ b/apps/deploy-web/src/services/api-url/server-api-url.service.ts @@ -0,0 +1,4 @@ +import { serverEnvConfig } from "@src/config/server-env.config"; +import { ApiUrlService } from "@src/services/api-url/api-url.service"; + +export const serverApiUrlService = new ApiUrlService(serverEnvConfig); diff --git a/apps/deploy-web/src/services/auth/auth.service.ts b/apps/deploy-web/src/services/auth/auth.service.ts index 6f4b4b8cd..56a493963 100644 --- a/apps/deploy-web/src/services/auth/auth.service.ts +++ b/apps/deploy-web/src/services/auth/auth.service.ts @@ -1,6 +1,6 @@ import { InternalAxiosRequestConfig } from "axios"; -import { ANONYMOUS_USER_TOKEN_KEY } from "@src/utils/constants"; +import { ANONYMOUS_USER_TOKEN_KEY } from "@src/config/auth.config"; export class AuthService { constructor() { diff --git a/apps/deploy-web/src/services/http/http.service.ts b/apps/deploy-web/src/services/http/http.service.ts index 4b45946f3..829babb16 100644 --- a/apps/deploy-web/src/services/http/http.service.ts +++ b/apps/deploy-web/src/services/http/http.service.ts @@ -1,10 +1,10 @@ import { TxHttpService, UserHttpService } from "@akashnetwork/http-sdk"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { authService } from "@src/services/auth/auth.service"; -import { BASE_API_URL } from "@src/utils/constants"; import { customRegistry } from "@src/utils/customRegistry"; -const apiConfig = { baseURL: BASE_API_URL }; +const apiConfig = { baseURL: browserEnvConfig.NEXT_PUBLIC_API_BASE_URL }; export const userHttpService = new UserHttpService(apiConfig); export const txHttpService = new TxHttpService(customRegistry, apiConfig); diff --git a/apps/deploy-web/src/services/managed-wallet-http/managed-wallet-http.service.ts b/apps/deploy-web/src/services/managed-wallet-http/managed-wallet-http.service.ts index ab4a1e5d1..31c6952f9 100644 --- a/apps/deploy-web/src/services/managed-wallet-http/managed-wallet-http.service.ts +++ b/apps/deploy-web/src/services/managed-wallet-http/managed-wallet-http.service.ts @@ -2,9 +2,9 @@ import { ApiWalletOutput, ManagedWalletHttpService as ManagedWalletHttpServiceOr import { AxiosRequestConfig } from "axios"; import { debounce } from "lodash"; -import { envConfig } from "@src/config/env.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { browserApiUrlService } from "@src/services/api-url/browser-api-url.service"; import { authService } from "@src/services/auth/auth.service"; -import { getNetworkBaseApiUrl } from "@src/utils/constants"; class ManagedWalletHttpService extends ManagedWalletHttpServiceOriginal { private checkoutSessionId: string | null = null; @@ -61,5 +61,7 @@ class ManagedWalletHttpService extends ManagedWalletHttpServiceOriginal { } } -export const managedWalletHttpService = new ManagedWalletHttpService({ baseURL: getNetworkBaseApiUrl(envConfig.NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID) }); +export const managedWalletHttpService = new ManagedWalletHttpService({ + baseURL: browserApiUrlService.getBaseApiUrlFor(browserEnvConfig.NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID) +}); managedWalletHttpService.interceptors.request.use(authService.withAnonymousUserHeader); diff --git a/apps/deploy-web/src/services/network/network.service.ts b/apps/deploy-web/src/services/network/network.service.ts new file mode 100644 index 000000000..af72431df --- /dev/null +++ b/apps/deploy-web/src/services/network/network.service.ts @@ -0,0 +1,43 @@ +import { NetworkId } from "@akashnetwork/akashjs/build/types/network"; + +import { MAINNET_ID, SANDBOX_ID, TESTNET_ID } from "@src/config/network.config"; + +type API_VERSION = "v1beta2" | "v1beta3" | "v1beta4"; + +export class NetworkService { + selectedNetworkId: NetworkId; + + networkVersion: API_VERSION; + + networkVersionMarket: API_VERSION; + + setNetworkVersion() { + const selectedNetworkId = localStorage.getItem("selectedNetworkId"); + + switch (selectedNetworkId) { + case MAINNET_ID: + this.networkVersion = "v1beta3"; + this.networkVersionMarket = "v1beta4"; + this.selectedNetworkId = MAINNET_ID; + break; + case TESTNET_ID: + this.networkVersion = "v1beta3"; + this.networkVersionMarket = "v1beta3"; + this.selectedNetworkId = TESTNET_ID; + break; + case SANDBOX_ID: + this.networkVersion = "v1beta3"; + this.networkVersionMarket = "v1beta4"; + this.selectedNetworkId = SANDBOX_ID; + break; + + default: + this.networkVersion = "v1beta3"; + this.networkVersionMarket = "v1beta4"; + this.selectedNetworkId = MAINNET_ID; + break; + } + } +} + +export const networkService = new NetworkService(); diff --git a/apps/deploy-web/src/services/user/user-http.service.ts b/apps/deploy-web/src/services/user/user-http.service.ts index fbfada62c..6f338047d 100644 --- a/apps/deploy-web/src/services/user/user-http.service.ts +++ b/apps/deploy-web/src/services/user/user-http.service.ts @@ -2,7 +2,7 @@ import { HttpService } from "@akashnetwork/http-sdk"; import type { UserProfile } from "@auth0/nextjs-auth0/client"; import { InternalAxiosRequestConfig } from "axios"; -import { ANONYMOUS_USER_TOKEN_KEY } from "@src/utils/constants"; +import { ANONYMOUS_USER_TOKEN_KEY } from "@src/config/auth.config"; export class UserHttpService extends HttpService { constructor() { diff --git a/apps/deploy-web/src/store/networkStore.ts b/apps/deploy-web/src/store/networkStore.ts index 31721a145..082aaa10d 100644 --- a/apps/deploy-web/src/store/networkStore.ts +++ b/apps/deploy-web/src/store/networkStore.ts @@ -3,14 +3,15 @@ import { atom } from "jotai"; import { useAtom } from "jotai/index"; import { atomWithStorage } from "jotai/utils"; +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { MAINNET_ID, SANDBOX_ID, TESTNET_ID } from "@src/config/network.config"; import { store } from "@src/store/global-store"; import { Network } from "@src/types/network"; import { ApiUrlService, mainnetNodes, sandboxNodes, testnetNodes } from "@src/utils/apiUtils"; -import { defaultNetworkId, mainnetId, sandboxId, testnetId } from "@src/utils/constants"; export let networks: Network[] = [ { - id: mainnetId, + id: MAINNET_ID, title: "Mainnet", description: "Akash Network mainnet network.", nodesUrl: mainnetNodes, @@ -22,7 +23,7 @@ export let networks: Network[] = [ version: null // Set asynchronously }, { - id: testnetId, + id: TESTNET_ID, title: "GPU Testnet", description: "Testnet of the new GPU features.", nodesUrl: testnetNodes, @@ -34,7 +35,7 @@ export let networks: Network[] = [ version: null // Set asynchronously }, { - id: sandboxId, + id: SANDBOX_ID, title: "Sandbox", description: "Sandbox of the mainnet version.", nodesUrl: sandboxNodes, @@ -71,7 +72,7 @@ export const initiateNetworkData = async () => { const selectedNetworkId = atomWithStorage( "selectedNetworkId", - defaultNetworkId, + browserEnvConfig.NEXT_PUBLIC_DEFAULT_NETWORK_ID, // TODO: remove this once we have all clients using this store instead of the localstorage // Issue: https://github.com/akash-network/console/issues/297 typeof window !== "undefined" @@ -84,8 +85,8 @@ const selectedNetworkId = atomWithStorage( const stored = localStorage.getItem(key) as Network["id"] | null; if (!stored) { - localStorage.setItem(key, defaultNetworkId); - return defaultNetworkId; + localStorage.setItem(key, browserEnvConfig.NEXT_PUBLIC_DEFAULT_NETWORK_ID); + return browserEnvConfig.NEXT_PUBLIC_DEFAULT_NETWORK_ID; } return stored; diff --git a/apps/deploy-web/src/types/route-steps.type.ts b/apps/deploy-web/src/types/route-steps.type.ts new file mode 100644 index 000000000..bbdac77c0 --- /dev/null +++ b/apps/deploy-web/src/types/route-steps.type.ts @@ -0,0 +1,5 @@ +export enum RouteStep { + chooseTemplate = "choose-template", + editDeployment = "edit-deployment", + createLeases = "create-leases" +} diff --git a/apps/deploy-web/src/utils/TransactionMessageData.ts b/apps/deploy-web/src/utils/TransactionMessageData.ts index 26378958d..1b8faed98 100644 --- a/apps/deploy-web/src/utils/TransactionMessageData.ts +++ b/apps/deploy-web/src/utils/TransactionMessageData.ts @@ -1,21 +1,21 @@ import Long from "long"; +import { networkService } from "@src/services/network/network.service"; import { BidDto } from "@src/types/deployment"; import { BasicAllowance, MsgGrantAllowance, MsgRevoke, MsgRevokeAllowance } from "./proto/grant"; -import { networkVersion, networkVersionMarket } from "./constants"; import { protoTypes } from "./proto"; export function setMessageTypes() { - TransactionMessageData.Types.MSG_CLOSE_DEPLOYMENT = `/akash.deployment.${networkVersion}.MsgCloseDeployment`; - TransactionMessageData.Types.MSG_CREATE_DEPLOYMENT = `/akash.deployment.${networkVersion}.MsgCreateDeployment`; - TransactionMessageData.Types.MSG_DEPOSIT_DEPLOYMENT = `/akash.deployment.${networkVersion}.MsgDepositDeployment`; - TransactionMessageData.Types.MSG_DEPOSIT_DEPLOYMENT_AUTHZ = `/akash.deployment.${networkVersion}.DepositDeploymentAuthorization`; - TransactionMessageData.Types.MSG_UPDATE_DEPLOYMENT = `/akash.deployment.${networkVersion}.MsgUpdateDeployment`; - TransactionMessageData.Types.MSG_CREATE_LEASE = `/akash.market.${networkVersionMarket}.MsgCreateLease`; - TransactionMessageData.Types.MSG_REVOKE_CERTIFICATE = `/akash.cert.${networkVersion}.MsgRevokeCertificate`; - TransactionMessageData.Types.MSG_CREATE_CERTIFICATE = `/akash.cert.${networkVersion}.MsgCreateCertificate`; - - TransactionMessageData.Types.MSG_UPDATE_PROVIDER = `/akash.provider.${networkVersion}.MsgUpdateProvider`; + TransactionMessageData.Types.MSG_CLOSE_DEPLOYMENT = `/akash.deployment.${networkService.networkVersion}.MsgCloseDeployment`; + TransactionMessageData.Types.MSG_CREATE_DEPLOYMENT = `/akash.deployment.${networkService.networkVersion}.MsgCreateDeployment`; + TransactionMessageData.Types.MSG_DEPOSIT_DEPLOYMENT = `/akash.deployment.${networkService.networkVersion}.MsgDepositDeployment`; + TransactionMessageData.Types.MSG_DEPOSIT_DEPLOYMENT_AUTHZ = `/akash.deployment.${networkService.networkVersion}.DepositDeploymentAuthorization`; + TransactionMessageData.Types.MSG_UPDATE_DEPLOYMENT = `/akash.deployment.${networkService.networkVersion}.MsgUpdateDeployment`; + TransactionMessageData.Types.MSG_CREATE_LEASE = `/akash.market.${networkService.networkVersionMarket}.MsgCreateLease`; + TransactionMessageData.Types.MSG_REVOKE_CERTIFICATE = `/akash.cert.${networkService.networkVersion}.MsgRevokeCertificate`; + TransactionMessageData.Types.MSG_CREATE_CERTIFICATE = `/akash.cert.${networkService.networkVersion}.MsgCreateCertificate`; + + TransactionMessageData.Types.MSG_UPDATE_PROVIDER = `/akash.provider.${networkService.networkVersion}.MsgUpdateProvider`; } export class TransactionMessageData { diff --git a/apps/deploy-web/src/utils/apiUtils.ts b/apps/deploy-web/src/utils/apiUtils.ts index c174604d8..ea9670f1f 100644 --- a/apps/deploy-web/src/utils/apiUtils.ts +++ b/apps/deploy-web/src/utils/apiUtils.ts @@ -1,6 +1,7 @@ import axios from "axios"; -import { BASE_API_URL, networkVersion, networkVersionMarket } from "./constants"; +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { networkService } from "@src/services/network/network.service"; import { appendSearchParams } from "./urlUtils"; export class ApiUrlService { @@ -8,31 +9,31 @@ export class ApiUrlService { return `${apiEndpoint}/cosmos/params/v1beta1/params?subspace=deployment&key=MinDeposits`; } static deploymentList(apiEndpoint: string, address: string) { - return `${apiEndpoint}/akash/deployment/${networkVersion}/deployments/list?filters.owner=${address}`; + return `${apiEndpoint}/akash/deployment/${networkService.networkVersion}/deployments/list?filters.owner=${address}`; } static deploymentDetail(apiEndpoint: string, address: string, dseq: string) { - return `${apiEndpoint}/akash/deployment/${networkVersion}/deployments/info?id.owner=${address}&id.dseq=${dseq}`; + return `${apiEndpoint}/akash/deployment/${networkService.networkVersion}/deployments/info?id.owner=${address}&id.dseq=${dseq}`; } static bidList(apiEndpoint: string, address: string, dseq: string) { - return `${apiEndpoint}/akash/market/${networkVersionMarket}/bids/list?filters.owner=${address}&filters.dseq=${dseq}`; + return `${apiEndpoint}/akash/market/${networkService.networkVersionMarket}/bids/list?filters.owner=${address}&filters.dseq=${dseq}`; } static bidInfo(apiEndpoint: string, address: string, dseq: string, gseq: number, oseq: number, provider: string) { - return `${apiEndpoint}/akash/market/${networkVersionMarket}/bids/info?id.owner=${address}&id.dseq=${dseq}&id.gseq=${gseq}&id.oseq=${oseq}&id.provider=${provider}`; + return `${apiEndpoint}/akash/market/${networkService.networkVersionMarket}/bids/info?id.owner=${address}&id.dseq=${dseq}&id.gseq=${gseq}&id.oseq=${oseq}&id.provider=${provider}`; } static leaseList(apiEndpoint: string, address: string, dseq: string) { - return `${apiEndpoint}/akash/market/${networkVersionMarket}/leases/list?filters.owner=${address}${dseq ? "&filters.dseq=" + dseq : ""}`; + return `${apiEndpoint}/akash/market/${networkService.networkVersionMarket}/leases/list?filters.owner=${address}${dseq ? "&filters.dseq=" + dseq : ""}`; } static providers(apiEndpoint: string) { - return `${apiEndpoint}/akash/provider/${networkVersion}/providers`; + return `${apiEndpoint}/akash/provider/${networkService.networkVersion}/providers`; } static providerList() { - return `${BASE_API_URL}/v1/providers`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/providers`; } static providerDetail(owner: string) { - return `${BASE_API_URL}/v1/providers/${owner}`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/providers/${owner}`; } static providerRegions() { - return `${BASE_API_URL}/v1/provider-regions`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/provider-regions`; } static block(apiEndpoint: string, id: string) { return `${apiEndpoint}/blocks/${id}`; @@ -65,74 +66,74 @@ export class ApiUrlService { return `${apiEndpoint}/cosmos/feegrant/v1beta1/allowances/${address}`; } static dashboardData() { - return `${BASE_API_URL}/v1/dashboard-data`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/dashboard-data`; } static marketData() { - return `${BASE_API_URL}/v1/market-data`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/market-data`; } static proposals() { - return `${BASE_API_URL}/v1/proposals`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/proposals`; } static apiProviders() { - return `${BASE_API_URL}/v1/providers`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/providers`; } static templates() { - return `${BASE_API_URL}/v1/templates`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/templates`; } static validators() { - return `${BASE_API_URL}/v1/validators`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/validators`; } static transactions(limit: number) { - return `${BASE_API_URL}/v1/transactions${appendSearchParams({ limit })}`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/transactions${appendSearchParams({ limit })}`; } static addressTransactions(address: string, skip: number, limit: number) { - return `${BASE_API_URL}/v1/addresses/${address}/transactions/${skip}/${limit}`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/addresses/${address}/transactions/${skip}/${limit}`; } static addressDeployments(address: string, skip: number, limit: number, reverseSorting: boolean, filters: { [key: string]: string }) { - return `${BASE_API_URL}/v1/addresses/${address}/deployments/${skip}/${limit}${appendSearchParams({ reverseSorting, ...filters })}`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/addresses/${address}/deployments/${skip}/${limit}${appendSearchParams({ reverseSorting, ...filters })}`; } static graphData(snapshot: string) { - return `${BASE_API_URL}/v1/graph-data/${snapshot}`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/graph-data/${snapshot}`; } static providerGraphData(snapshot: string) { - return `${BASE_API_URL}/v1/provider-graph-data/${snapshot}`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/provider-graph-data/${snapshot}`; } static blocks(limit: number) { - return `${BASE_API_URL}/v1/blocks${appendSearchParams({ limit })}`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/blocks${appendSearchParams({ limit })}`; } static providerActiveLeasesGraph(providerAddress: string) { - return `${BASE_API_URL}/v1/provider-active-leases-graph-data/${providerAddress}`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/provider-active-leases-graph-data/${providerAddress}`; } static providerAttributesSchema() { - return `${BASE_API_URL}/v1/provider-attributes-schema`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/provider-attributes-schema`; } static networkCapacity() { - return `${BASE_API_URL}/v1/network-capacity`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/network-capacity`; } static gpuModels() { - return `${BASE_API_URL}/internal/gpu-models`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/internal/gpu-models`; } // Github static auditors() { - return `${BASE_API_URL}/v1/auditors`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/auditors`; } static mainnetNodes() { - return `${BASE_API_URL}/v1/nodes/mainnet`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/nodes/mainnet`; } static testnetNodes() { - return `${BASE_API_URL}/v1/nodes/testnet`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/nodes/testnet`; } static sandboxNodes() { - return `${BASE_API_URL}/v1/nodes/sandbox`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/nodes/sandbox`; } static mainnetVersion() { - return `${BASE_API_URL}/v1/version/mainnet`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/version/mainnet`; } static testnetVersion() { - return `${BASE_API_URL}/v1/version/testnet`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/version/testnet`; } static sandboxVersion() { - return `${BASE_API_URL}/v1/version/sandbox`; + return `${browserEnvConfig.NEXT_PUBLIC_API_BASE_URL}/v1/version/sandbox`; } } diff --git a/apps/deploy-web/src/utils/auth0.ts b/apps/deploy-web/src/utils/auth0.ts deleted file mode 100644 index c5b6dde35..000000000 --- a/apps/deploy-web/src/utils/auth0.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { UserProfile } from "@auth0/nextjs-auth0/client"; - -import { auth0TokenNamespace } from "./constants"; - -export function getUserField(user: UserProfile, field: "username" | "user_metadata"): any { - if (user && user[auth0TokenNamespace + "/" + field]) { - return user[auth0TokenNamespace + "/" + field]; - } - return null; -} diff --git a/apps/deploy-web/src/utils/constants.ts b/apps/deploy-web/src/utils/constants.ts deleted file mode 100644 index 922f10434..000000000 --- a/apps/deploy-web/src/utils/constants.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { envConfig } from "@src/config/env.config"; - -const ENV = { - API_MAINNET_BASE_URL: - typeof window === "undefined" - ? process.env.API_MAINNET_BASE_URL || process.env.NEXT_PUBLIC_API_MAINNET_BASE_URL - : process.env.NEXT_PUBLIC_API_MAINNET_BASE_URL, - API_TESTNET_BASE_URL: - typeof window === "undefined" - ? process.env.API_TESTNET_BASE_URL || process.env.NEXT_PUBLIC_API_TESTNET_BASE_URL - : process.env.NEXT_PUBLIC_API_TESTNET_BASE_URL, - API_SANDBOX_BASE_URL: - typeof window === "undefined" - ? process.env.API_SANDBOX_BASE_URL || process.env.NEXT_PUBLIC_API_SANDBOX_BASE_URL - : process.env.NEXT_PUBLIC_API_SANDBOX_BASE_URL, - API_BASE_URL: typeof window === "undefined" ? process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL : process.env.NEXT_PUBLIC_API_BASE_URL, - STATS_APP_URL: typeof window === "undefined" ? process.env.STATS_APP_URL || process.env.NEXT_PUBLIC_STATS_APP_URL : process.env.NEXT_PUBLIC_STATS_APP_URL, - PROVIDER_PROXY_URL: - typeof window === "undefined" ? process.env.PROVIDER_PROXY_URL || process.env.NEXT_PUBLIC_PROVIDER_PROXY_URL : process.env.NEXT_PUBLIC_PROVIDER_PROXY_URL, - DEFAULT_NETWORK_ID: - typeof window === "undefined" ? envConfig.DEFAULT_NETWORK_ID || envConfig.NEXT_PUBLIC_DEFAULT_NETWORK_ID : envConfig.NEXT_PUBLIC_DEFAULT_NETWORK_ID -}; - -export const mainnetId = "mainnet"; -export const testnetId = "testnet"; -export const sandboxId = "sandbox"; -export const defaultNetworkId = envConfig.DEFAULT_NETWORK_ID || mainnetId; - -export const selectedRangeValues: { [key: string]: number } = { - "7D": 7, - "1M": 30, - ALL: Number.MAX_SAFE_INTEGER -}; - -// UI -export const statusBarHeight = 30; -export const drawerWidth = 240; -export const closedDrawerWidth = 57; -export const accountBarHeight = 57; - -// Deployment creation -export enum RouteStepKeys { - chooseTemplate = "choose-template", - editDeployment = "edit-deployment", - createLeases = "create-leases" -} - -const productionMainnetApiUrl = "https://api.cloudmos.io"; -const productionTestnetApiUrl = "https://api-testnet.cloudmos.io"; -const productionSandboxApiUrl = "https://api-sandbox.cloudmos.io"; -const productionStatsAppUrl = "https://stats.akash.network"; -const productionHostnames = ["deploy.cloudmos.io", "console.akash.network", "staging-console.akash.network", "beta.cloudmos.io", "console-beta.akash.network"]; - -export const isProd = process.env.NODE_ENV === "production"; -export const isMaintenanceMode = process.env.MAINTENANCE_MODE === "true"; -export const BASE_API_MAINNET_URL = getApiMainnetUrl(); -export const BASE_API_TESTNET_URL = getApiTestnetUrl(); -export const BASE_API_SANDBOX_URL = getApiSandboxUrl(); -export const STATS_APP_URL = getStatsAppUrl(); - -export const BASE_API_URL = getApiUrl(); - -export function getNetworkBaseApiUrl(network: string) { - switch (network) { - case testnetId: - return BASE_API_TESTNET_URL; - case sandboxId: - return BASE_API_SANDBOX_URL; - default: - return BASE_API_MAINNET_URL; - } -} - -export const PROVIDER_PROXY_URL = getProviderProxyHttpUrl(); -export const PROVIDER_PROXY_URL_WS = getProviderProxyWsUrl(); - -// TODO: Fix for console -export const auth0TokenNamespace = "https://console.akash.network"; - -export const uAktDenom = "uakt"; -export const usdcIbcDenoms = { - [mainnetId]: "ibc/170C677610AC31DF0904FFE09CD3B5C657492170E7E52372E48756B71E56F2F1", - [sandboxId]: "ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84" -}; -const readableAktDenom = "uAKT"; -const readableUsdcDenom = "uUSDC"; -export const readableDenoms = { - [uAktDenom]: readableAktDenom, - [usdcIbcDenoms[mainnetId]]: readableUsdcDenom, - [usdcIbcDenoms[sandboxId]]: readableUsdcDenom -}; - -function getApiMainnetUrl() { - if (ENV.API_MAINNET_BASE_URL) return ENV.API_MAINNET_BASE_URL; - if (typeof window === "undefined") return "http://localhost:3080"; - if (productionHostnames.includes(window.location?.hostname)) return productionMainnetApiUrl; - return "http://localhost:3080"; -} - -function getApiTestnetUrl() { - if (ENV.API_TESTNET_BASE_URL) return ENV.API_TESTNET_BASE_URL; - if (typeof window === "undefined") return "http://localhost:3080"; - if (productionHostnames.includes(window.location?.hostname)) return productionTestnetApiUrl; - return "http://localhost:3080"; -} - -function getApiSandboxUrl() { - if (ENV.API_SANDBOX_BASE_URL) return ENV.API_SANDBOX_BASE_URL; - if (typeof window === "undefined") return "http://localhost:3080"; - if (productionHostnames.includes(window.location?.hostname)) return productionSandboxApiUrl; - return "http://localhost:3080"; -} - -function getApiUrl() { - if (ENV.API_BASE_URL) return ENV.API_BASE_URL; - if (typeof window === "undefined") return "http://localhost:3080"; - if (productionHostnames.includes(window.location?.hostname)) { - try { - const _selectedNetworkId = localStorage.getItem("selectedNetworkId"); - return getNetworkBaseApiUrl(_selectedNetworkId || mainnetId); - } catch (e) { - console.error(e); - return productionMainnetApiUrl; - } - } - return "http://localhost:3080"; -} - -function getStatsAppUrl() { - if (ENV.STATS_APP_URL) return ENV.STATS_APP_URL; - if (typeof window === "undefined") return "http://localhost:3001"; - if (productionHostnames.includes(window.location?.hostname)) return productionStatsAppUrl; - return "http://localhost:3001"; -} - -function getProviderProxyHttpUrl() { - if (ENV.PROVIDER_PROXY_URL) return ENV.PROVIDER_PROXY_URL; - if (typeof window === "undefined") return "http://localhost:3040"; - if (window.location?.hostname === "deploybeta.cloudmos.io") return "https://deployproxybeta.cloudmos.io"; - if (productionHostnames.includes(window.location?.hostname)) return "https://providerproxy.cloudmos.io"; - return "http://localhost:3040"; -} - -function getProviderProxyWsUrl() { - if (typeof window === "undefined") return "ws://localhost:3040"; - if (window.location?.hostname === "deploybeta.cloudmos.io") return "wss://deployproxybeta.cloudmos.io"; - if (productionHostnames.includes(window.location?.hostname)) return "wss://providerproxy.cloudmos.io"; - return "ws://localhost:3040"; -} - -export let selectedNetworkId = ""; - -// 0.5AKT aka 500000uakt -export const defaultInitialDeposit = 500000; - -export let networkVersion: "v1beta2" | "v1beta3" | "v1beta4"; -export let networkVersionMarket: "v1beta2" | "v1beta3" | "v1beta4"; - -export function setNetworkVersion() { - const _selectedNetworkId = localStorage.getItem("selectedNetworkId"); - - switch (_selectedNetworkId) { - case mainnetId: - networkVersion = "v1beta3"; - networkVersionMarket = "v1beta4"; - selectedNetworkId = mainnetId; - break; - case testnetId: - networkVersion = "v1beta3"; - networkVersionMarket = "v1beta3"; - selectedNetworkId = testnetId; - break; - case sandboxId: - networkVersion = "v1beta3"; - networkVersionMarket = "v1beta4"; - selectedNetworkId = sandboxId; - break; - - default: - networkVersion = "v1beta3"; - networkVersionMarket = "v1beta4"; - selectedNetworkId = mainnetId; - break; - } -} - -export const monacoOptions = { - selectOnLineNumbers: true, - scrollBeyondLastLine: false, - automaticLayout: true, - scrollbar: { - verticalScrollbarSize: 8 - }, - minimap: { - enabled: false - }, - padding: { - bottom: 50 - }, - hover: { - enabled: false - } -}; - -export const txFeeBuffer = 10000; // 10000 uAKT - -export const ANONYMOUS_USER_KEY = "anonymous-user"; -export const ANONYMOUS_USER_TOKEN_KEY = "anonymous-user-auth"; diff --git a/apps/deploy-web/src/utils/deploymentData/index.ts b/apps/deploy-web/src/utils/deploymentData/index.ts index 8e31c8de2..53bfaeb05 100644 --- a/apps/deploy-web/src/utils/deploymentData/index.ts +++ b/apps/deploy-web/src/utils/deploymentData/index.ts @@ -1,14 +1,14 @@ import { NetworkId } from "@akashnetwork/akashjs/build/types/network"; +import { MAINNET_ID, SANDBOX_ID, TESTNET_ID } from "@src/config/network.config"; import networkStore from "@src/store/networkStore"; -import { mainnetId, sandboxId, testnetId } from "../constants"; import * as v1beta3 from "./v1beta3"; export * from "./helpers"; const NETWORK_SDL: Record = { - [mainnetId]: v1beta3, - [testnetId]: v1beta3, - [sandboxId]: v1beta3 + [MAINNET_ID]: v1beta3, + [TESTNET_ID]: v1beta3, + [SANDBOX_ID]: v1beta3 }; export const selectedNetwork = networkStore.getSelectedNetwork(); diff --git a/apps/deploy-web/src/utils/deploymentData/v1beta2.ts b/apps/deploy-web/src/utils/deploymentData/v1beta2.ts index b2dc8f569..2616f3931 100644 --- a/apps/deploy-web/src/utils/deploymentData/v1beta2.ts +++ b/apps/deploy-web/src/utils/deploymentData/v1beta2.ts @@ -3,8 +3,8 @@ import { NetworkId } from "@akashnetwork/akashjs/build/types/network"; import yaml from "js-yaml"; import path from "path"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import networkStore from "@src/store/networkStore"; -import { defaultInitialDeposit } from "../constants"; import { stringToBoolean } from "../stringUtils"; import { CustomValidationError, DeploymentGroups, getCurrentHeight, getSdl, Manifest, ManifestVersion, parseSizeStr } from "./helpers"; @@ -179,7 +179,7 @@ export async function NewDeploymentData( yamlStr: string, dseq: string, fromAddress: string, - deposit = defaultInitialDeposit, + deposit = browserEnvConfig.NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT, depositorAddress = null ) { const { id: networkId } = networkStore.getSelectedNetwork(); diff --git a/apps/deploy-web/src/utils/deploymentData/v1beta3.ts b/apps/deploy-web/src/utils/deploymentData/v1beta3.ts index a844a1898..8e198c7d1 100644 --- a/apps/deploy-web/src/utils/deploymentData/v1beta3.ts +++ b/apps/deploy-web/src/utils/deploymentData/v1beta3.ts @@ -1,6 +1,6 @@ +import { browserEnvConfig } from "@src/config/browser-env.config"; import networkStore from "@src/store/networkStore"; import type { DepositParams } from "@src/types/deployment"; -import { defaultInitialDeposit } from "../constants"; import { CustomValidationError, getCurrentHeight, getSdl, Manifest, ManifestVersion } from "./helpers"; export const endpointNameValidationRegex = /^[a-z]+[-_\da-z]+$/; @@ -29,7 +29,7 @@ export async function NewDeploymentData( yamlStr: string, dseq: string | null, fromAddress: string, - deposit: number | DepositParams[] = defaultInitialDeposit, + deposit: number | DepositParams[] = browserEnvConfig.NEXT_PUBLIC_DEFAULT_INITIAL_DEPOSIT, depositorAddress: string | null = null ) { try { diff --git a/apps/deploy-web/src/utils/deploymentUtils.ts b/apps/deploy-web/src/utils/deploymentUtils.ts index b8f31e6c8..8cde1a96a 100644 --- a/apps/deploy-web/src/utils/deploymentUtils.ts +++ b/apps/deploy-web/src/utils/deploymentUtils.ts @@ -1,8 +1,8 @@ import axios from "axios"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { LocalCert } from "@src/context/CertificateProvider/CertificateProviderContext"; import { ApiProviderList } from "@src/types/provider"; -import { PROVIDER_PROXY_URL } from "./constants"; import { wait } from "./timer"; export const sendManifestToProvider = async (providerInfo: ApiProviderList, manifest: any, dseq: string, localCert: LocalCert) => { @@ -20,7 +20,7 @@ export const sendManifestToProvider = async (providerInfo: ApiProviderList, mani console.log("Try #" + i); try { if (!response) { - response = await axios.post(PROVIDER_PROXY_URL, { + response = await axios.post(browserEnvConfig.NEXT_PUBLIC_PROVIDER_PROXY_URL, { method: "PUT", url: providerInfo.hostUri + "/deployment/" + dseq + "/manifest", certPem: localCert?.certPem, diff --git a/apps/deploy-web/src/utils/init.ts b/apps/deploy-web/src/utils/init.ts index a3e6e0903..cb835abe0 100644 --- a/apps/deploy-web/src/utils/init.ts +++ b/apps/deploy-web/src/utils/init.ts @@ -1,9 +1,9 @@ -import { setNetworkVersion } from "./constants"; +import { networkService } from "@src/services/network/network.service"; import { initProtoTypes } from "./proto"; import { setMessageTypes } from "./TransactionMessageData"; export const initAppTypes = () => { - setNetworkVersion(); + networkService.setNetworkVersion(); initProtoTypes(); setMessageTypes(); }; diff --git a/apps/deploy-web/src/utils/priceUtils.ts b/apps/deploy-web/src/utils/priceUtils.ts index 3df05cd34..031a767f5 100644 --- a/apps/deploy-web/src/utils/priceUtils.ts +++ b/apps/deploy-web/src/utils/priceUtils.ts @@ -1,9 +1,9 @@ import { Coin } from "@cosmjs/stargate"; import add from "date-fns/add"; +import { READABLE_DENOMS, UAKT_DENOM } from "@src/config/denom.config"; import { getUsdcDenom } from "@src/hooks/useDenom"; import { useBlock } from "@src/queries/useBlocksQuery"; -import { readableDenoms, uAktDenom } from "./constants"; import { averageDaysInMonth } from "./dateUtils"; import { denomToUdenom } from "./mathHelpers"; @@ -23,7 +23,7 @@ export function coinToUDenom(coin: Coin) { if (coin.denom === "akt") { value = denomToUdenom(parseFloat(coin.amount)); - } else if (coin.denom === uAktDenom || coin.denom === usdcDenom) { + } else if (coin.denom === UAKT_DENOM || coin.denom === usdcDenom) { value = parseFloat(coin.amount); } else { throw Error("Unrecognized denom: " + coin.denom); @@ -38,7 +38,7 @@ export function coinToDenom(coin: Coin) { if (coin.denom === "akt") { value = parseFloat(coin.amount); - } else if (coin.denom === uAktDenom || coin.denom === usdcDenom) { + } else if (coin.denom === UAKT_DENOM || coin.denom === usdcDenom) { value = uaktToAKT(parseFloat(coin.amount), 6); } else { throw Error("Unrecognized denom: " + coin.denom); @@ -48,8 +48,7 @@ export function coinToDenom(coin: Coin) { } export function getAvgCostPerMonth(pricePerBlock: number) { - const averagePrice = (pricePerBlock * averageDaysInMonth * 24 * 60 * 60) / averageBlockTime; - return averagePrice; + return (pricePerBlock * averageDaysInMonth * 24 * 60 * 60) / averageBlockTime; } export function getTimeLeft(pricePerBlock: number, balance: number) { @@ -79,5 +78,5 @@ export function useRealTimeLeft(pricePerBlock: number, balance: number, settledA } export function toReadableDenom(denom: string) { - return readableDenoms[denom]; + return READABLE_DENOMS[denom]; } diff --git a/apps/deploy-web/src/utils/proto/index.ts b/apps/deploy-web/src/utils/proto/index.ts index 78e217a43..313168aa7 100644 --- a/apps/deploy-web/src/utils/proto/index.ts +++ b/apps/deploy-web/src/utils/proto/index.ts @@ -1,7 +1,7 @@ import * as v1beta3 from "@akashnetwork/akash-api/v1beta3"; import * as v1beta4 from "@akashnetwork/akash-api/v1beta4"; -import { mainnetId, sandboxId, testnetId } from "../constants"; +import { MAINNET_ID, SANDBOX_ID, TESTNET_ID } from "@src/config/network.config"; const commonTypes = { ...v1beta3, ...v1beta4 }; const mainnetTypes = commonTypes; @@ -13,12 +13,12 @@ export function initProtoTypes() { const selectedNetworkId = localStorage.getItem("selectedNetworkId"); switch (selectedNetworkId) { - case mainnetId: - case testnetId: + case MAINNET_ID: + case TESTNET_ID: protoTypes = mainnetTypes; break; - case sandboxId: + case SANDBOX_ID: protoTypes = sandboxTypes; break; diff --git a/apps/deploy-web/src/utils/urlUtils.ts b/apps/deploy-web/src/utils/urlUtils.ts index 282268b40..99053ff15 100644 --- a/apps/deploy-web/src/utils/urlUtils.ts +++ b/apps/deploy-web/src/utils/urlUtils.ts @@ -1,5 +1,6 @@ +import { MAINNET_ID } from "@src/config/network.config"; import { FaqAnchorType } from "@src/pages/faq"; -import { mainnetId, selectedNetworkId } from "./constants"; +import { networkService } from "@src/services/network/network.service"; export type NewDeploymentParams = { step?: string; @@ -10,12 +11,12 @@ export type NewDeploymentParams = { }; function getSelectedNetworkQueryParam() { - if (selectedNetworkId) { - return selectedNetworkId; + if (networkService.selectedNetworkId) { + return networkService.selectedNetworkId; } else if (typeof window !== "undefined") { return new URLSearchParams(window.location.search).get("network"); } else { - return mainnetId; + return MAINNET_ID; } } diff --git a/apps/deploy-web/src/utils/walletUtils.ts b/apps/deploy-web/src/utils/walletUtils.ts index 9e64cd3b7..d9ef03c79 100644 --- a/apps/deploy-web/src/utils/walletUtils.ts +++ b/apps/deploy-web/src/utils/walletUtils.ts @@ -1,7 +1,7 @@ import { isEqual } from "lodash"; -import { envConfig } from "@src/config/env.config"; -import { mainnetId } from "./constants"; +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { MAINNET_ID } from "@src/config/network.config"; interface BaseLocalWallet { address: string; @@ -37,7 +37,7 @@ export function getStorageManagedWallet(networkId?: string): ManagedLocalWallet export function updateStorageManagedWallet( wallet: Pick & { selected?: boolean } ): ManagedLocalWallet { - const networkId = envConfig.NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID; + const networkId = browserEnvConfig.NEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID; const wallets = getStorageWallets(networkId); const prevIndex = wallets.findIndex(({ isManaged }) => isManaged); const prev = wallets[prevIndex]; @@ -86,7 +86,7 @@ export function getStorageWallets(networkId?: string) { return []; } - const selectedNetworkId = networkId || localStorage.getItem("selectedNetworkId") || mainnetId; + const selectedNetworkId = networkId || localStorage.getItem("selectedNetworkId") || MAINNET_ID; const wallets = JSON.parse(localStorage.getItem(`${selectedNetworkId}/wallets`) || "[]") as LocalWallet[]; return wallets || []; @@ -105,12 +105,12 @@ export function updateWallet(address: string, func: (w: LocalWallet) => LocalWal } export function updateStorageWallets(wallets: LocalWallet[], networkId?: string) { - const selectedNetworkId = networkId || localStorage.getItem("selectedNetworkId") || mainnetId; + const selectedNetworkId = networkId || localStorage.getItem("selectedNetworkId") || MAINNET_ID; localStorage.setItem(`${selectedNetworkId}/wallets`, JSON.stringify(wallets)); } export function deleteWalletFromStorage(address: string, deleteDeployments: boolean, networkId?: string) { - const selectedNetworkId = networkId || localStorage.getItem("selectedNetworkId") || mainnetId; + const selectedNetworkId = networkId || localStorage.getItem("selectedNetworkId") || MAINNET_ID; const wallets = getStorageWallets(); const newWallets = wallets.filter(w => w.address !== address).map((w, i) => ({ ...w, selected: i === 0 })); diff --git a/docker/Dockerfile.nextjs b/docker/Dockerfile.nextjs index 7e278f152..fd09ee6a8 100644 --- a/docker/Dockerfile.nextjs +++ b/docker/Dockerfile.nextjs @@ -2,6 +2,10 @@ FROM node:20-alpine AS base ARG WORKSPACE ENV WORKSPACE $WORKSPACE + +ARG DEPLOYMENT_ENV +ENV DEPLOYMENT_ENV $DEPLOYMENT_ENV + ENV NEXT_TELEMETRY_DISABLED 1 WORKDIR /app @@ -37,6 +41,7 @@ ENV APP_USER app RUN addgroup --system --gid $APP_GROUP_ID $APP_GROUP \ && adduser --system --uid $APP_GROUP_ID $APP_USER +COPY --from=builder /app/$WORKSPACE/env ./$WORKSPACE/env COPY --from=builder /app/$WORKSPACE/public ./$WORKSPACE/public COPY --from=builder /app/$WORKSPACE/.next/standalone ./ COPY --from=builder /app/$WORKSPACE/.next/static ./$WORKSPACE/.next/static diff --git a/package-lock.json b/package-lock.json index 8d5de885b..d151f2d22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -270,6 +270,7 @@ "dependencies": { "@akashnetwork/akash-api": "^1.3.0", "@akashnetwork/akashjs": "^0.10.0", + "@akashnetwork/env-loader": "*", "@akashnetwork/http-sdk": "*", "@akashnetwork/ui": "*", "@auth0/nextjs-auth0": "^3.5.0", @@ -972,6 +973,10 @@ "resolved": "packages/dev-config", "link": true }, + "node_modules/@akashnetwork/env-loader": { + "resolved": "packages/env-loader", + "link": true + }, "node_modules/@akashnetwork/http-sdk": { "resolved": "packages/http-sdk", "link": true @@ -4284,20 +4289,19 @@ } }, "node_modules/@dotenvx/dotenvx": { - "version": "1.9.0", - "license": "BSD-3-Clause", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.14.0.tgz", + "integrity": "sha512-ujWncblsqokvW8w6tCW35hjwlD3FHySMdrC5OPMYqfcGR96B/H6xK9xSu5F/SyZ8uk8USoPZynsXxB24IGvfmQ==", "dependencies": { "commander": "^11.1.0", - "diff": "^5.2.0", "dotenv": "^16.4.5", "eciesjs": "^0.4.6", + "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "picomatch": "^4.0.2", - "tinyexec": "^0.2.0", - "which": "^4.0.0", - "xxhashjs": "^0.2.2" + "which": "^4.0.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js", @@ -4314,13 +4318,6 @@ "node": ">=16" } }, - "node_modules/@dotenvx/dotenvx/node_modules/diff": { - "version": "5.2.0", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/@dotenvx/dotenvx/node_modules/dotenv": { "version": "16.4.5", "license": "BSD-2-Clause", @@ -23732,10 +23729,6 @@ "version": "3.1.3", "license": "MIT" }, - "node_modules/cuint": { - "version": "0.2.2", - "license": "MIT" - }, "node_modules/d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", @@ -42198,10 +42191,6 @@ "version": "4.12.0", "license": "MIT" }, - "node_modules/tinyexec": { - "version": "0.2.0", - "license": "MIT" - }, "node_modules/tmp": { "version": "0.0.33", "dev": true, @@ -44913,13 +44902,6 @@ "xterm": "^5.0.0" } }, - "node_modules/xxhashjs": { - "version": "0.2.2", - "license": "MIT", - "dependencies": { - "cuint": "^0.2.2" - } - }, "node_modules/y18n": { "version": "5.0.8", "license": "ISC", @@ -45073,6 +45055,112 @@ "prettier-plugin-tailwindcss": "^0.6.1" } }, + "packages/env-loader": { + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@dotenvx/dotenvx": "^1.12.1", + "pino": "^9.3.2" + }, + "bin": { + "detect-env-files": "src/detect-files-stdout.js" + } + }, + "packages/env-loader/node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, + "packages/env-loader/node_modules/pino": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.4.0.tgz", + "integrity": "sha512-nbkQb5+9YPhQRz/BeQmrWpEknAaqjpAqRK8NwJpmrX/JHu7JuZC5G1CeAwJDJfGes4h+YihC6in3Q2nGb+Y09w==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "packages/env-loader/node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "packages/env-loader/node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, + "packages/env-loader/node_modules/process-warning": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.0.tgz", + "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==" + }, + "packages/env-loader/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "packages/env-loader/node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "packages/env-loader/node_modules/sonic-boom": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.1.0.tgz", + "integrity": "sha512-NGipjjRicyJJ03rPiZCJYjwlsuP2d1/5QUviozRXC7S3WdVWNK5e3Ojieb9CCyfhq2UC+3+SRd9nG3I2lPRvUw==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "packages/env-loader/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "packages/env-loader/node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "dependencies": { + "real-require": "^0.2.0" + } + }, "packages/http-sdk": { "name": "@akashnetwork/http-sdk", "version": "1.0.0", diff --git a/packages/env-loader/package.json b/packages/env-loader/package.json new file mode 100644 index 000000000..bd8b76788 --- /dev/null +++ b/packages/env-loader/package.json @@ -0,0 +1,20 @@ +{ + "name": "@akashnetwork/env-loader", + "version": "1.0.0", + "description": "Package used to load environment variables", + "keywords": [], + "license": "Apache-2.0", + "author": "", + "main": "src/index.js", + "scripts": { + "format": "prettier --write ./*.{ts,json} **/*.{ts,json}", + "lint": "eslint ." + }, + "dependencies": { + "@dotenvx/dotenvx": "^1.12.1", + "pino": "^9.3.2" + }, + "bin": { + "detect-env-files": "src/detect-files-stdout.js" + } +} diff --git a/packages/env-loader/src/index.js b/packages/env-loader/src/index.js new file mode 100644 index 000000000..a523be468 --- /dev/null +++ b/packages/env-loader/src/index.js @@ -0,0 +1,31 @@ +const dotenv = require("@dotenvx/dotenvx"); +const fs = require("fs"); +const pino = require("pino"); + +const logger = pino( + pino.destination({ + sync: true + }) +).child({ context: "ENV" }); + +const files = []; + +const config = path => { + if (fs.existsSync(path)) { + dotenv.config({ path, logLevel: "error" }); + files.push(path); + } +}; +config("env/.env.local"); +config("env/.env"); + +const deploymentEnv = process.env.DEPLOYMENT_ENV; + +if (deploymentEnv && deploymentEnv !== "local") { + config(`env/.env.${deploymentEnv}`); +} + +const network = process.env.NETWORK; +config(`env/.env.${network}`); + +logger.info(`Loaded env files: ${files.join(", ")}`); diff --git a/script/deploy-web.sh b/script/deploy-web.sh new file mode 100755 index 000000000..3c99cb44f --- /dev/null +++ b/script/deploy-web.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +deploy_web() { + local instance_name=$1; + local tag=$2; + local deployment_env=$3; + + docker build \ + -f docker/Dockerfile.nextjs \ + --target production-nginx \ + --build-arg WORKSPACE=apps/deploy-web \ + --build-arg DEPLOYMENT_ENV=$deployment_env \ + --platform linux/amd64 \ + -t gcr.io/cloudmos-explorer/console-deploy-web:$tag .; + + docker push gcr.io/cloudmos-explorer/console-deploy-web:$tag; + + gcloud compute instances update-container $instance_name \ + --container-image=gcr.io/cloudmos-explorer/console-deploy-web:$tag; +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + deploy_web "$@" +fi \ No newline at end of file