From e22e0cc8c9d8a22bd8ebfa27741b6e4f411a5cec Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Thu, 25 Jun 2026 08:02:01 +0100 Subject: [PATCH 1/9] chore(config): move non-secret config out of env into code --- src/config/index.ts | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/config/index.ts b/src/config/index.ts index 87d0e46..dac1706 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,20 +1,11 @@ const config = { - iqAddress: - process.env.NEXT_PUBLIC_IQ_ADDRESS || - "0x0552D756a3E92Aa874EF60F61b7a29030373e869", - hiiqAddress: - process.env.NEXT_PUBLIC_HIIQ_ADDRESS || - "0xC03bCACC5377b7cc6634537650A7a1D14711c1A3", + iqAddress: "0x579cea1889991f68acc35ff5c3dd0621ff29b0c9", + hiiqAddress: "0x1bf5457ecaa14ff63cc89efd560e251e814e16ba", + sophiaAgentAddress: "0x4dBcC239b265295500D2Fe2d0900629BDcBBD0fB", + iqGatewayUrl: "https://gateway.braindao.org", alchemyApiKey: String(process.env.NEXT_PUBLIC_ALCHEMY_API_KEY), - alchemyChain: process.env.NEXT_PUBLIC_ALCHEMY_CHAIN || "goerli", - chainId: process.env.NEXT_PUBLIC_CHAIN_ID || "5", - walletConnectProjectId: - process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID || - "e6567b95-7acb-4954-8673-76d34981e18f", - posthogApiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY || "", - iqGatewayUrl: process.env.NEXT_PUBLIC_IQ_GATEWAY_URL || "", iqGatewayKey: process.env.NEXT_PUBLIC_IQ_GATEWAY_KEY || "", - sophiaAgentAddress: process.env.NEXT_PUBLIC_SOPHIA_AGENT_ADDRESS || "", + posthogApiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY || "", }; export default config; From 857a9e3080f7f190b3b8f03fc47a6b926db04908 Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Mon, 29 Jun 2026 15:35:35 +0100 Subject: [PATCH 2/9] build(deps): add @t3-oss/env-nextjs for env validation --- package.json | 1 + pnpm-lock.yaml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/package.json b/package.json index 688536d..efae474 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@radix-ui/react-slot": "^1.2.3", "@react-three/drei": "^9.86.3", "@react-three/fiber": "^8.14.4", + "@t3-oss/env-nextjs": "^0.13.11", "axios": "^1.5.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d7f5ae5..2257900 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: '@react-three/fiber': specifier: ^8.14.4 version: 8.18.0(@types/react@19.1.12)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(three@0.157.0) + '@t3-oss/env-nextjs': + specifier: ^0.13.11 + version: 0.13.11(typescript@5.9.2)(zod@4.1.5) axios: specifier: ^1.5.1 version: 1.11.0 @@ -1057,6 +1060,40 @@ packages: '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@t3-oss/env-core@0.13.11': + resolution: {integrity: sha512-sM7GYY+KL7H/Hl0BE0inWfk3nRHZOLhmVn7sHGxaZt9FAR6KqREXAE+6TqKfiavfXmpRxO/OZ2QgKRd+oiBYRQ==} + peerDependencies: + arktype: ^2.1.0 + typescript: '>=5.0.0' + valibot: ^1.0.0-beta.7 || ^1.0.0 + zod: ^3.24.0 || ^4.0.0 + peerDependenciesMeta: + arktype: + optional: true + typescript: + optional: true + valibot: + optional: true + zod: + optional: true + + '@t3-oss/env-nextjs@0.13.11': + resolution: {integrity: sha512-NC+3j7YWgpzdFu1t5y/8wqibTK0lm5RS4bjXA1n8uwik3wIR4iZM4Fa+U2BaMa5k3Qk8RZiYhoAIX0WogmGkzg==} + peerDependencies: + arktype: ^2.1.0 + typescript: '>=5.0.0' + valibot: ^1.0.0-beta.7 || ^1.0.0 + zod: ^3.24.0 || ^4.0.0 + peerDependenciesMeta: + arktype: + optional: true + typescript: + optional: true + valibot: + optional: true + zod: + optional: true + '@tybys/wasm-util@0.10.0': resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==} @@ -4183,6 +4220,18 @@ snapshots: dependencies: tslib: 2.8.1 + '@t3-oss/env-core@0.13.11(typescript@5.9.2)(zod@4.1.5)': + optionalDependencies: + typescript: 5.9.2 + zod: 4.1.5 + + '@t3-oss/env-nextjs@0.13.11(typescript@5.9.2)(zod@4.1.5)': + dependencies: + '@t3-oss/env-core': 0.13.11(typescript@5.9.2)(zod@4.1.5) + optionalDependencies: + typescript: 5.9.2 + zod: 4.1.5 + '@tybys/wasm-util@0.10.0': dependencies: tslib: 2.8.1 From 5685471faffa55d7e76c616368575aecd61c1b94 Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Mon, 29 Jun 2026 15:35:52 +0100 Subject: [PATCH 3/9] feat(env): add zod-validated env module with safe defaults Introduce src/env.ts using @t3-oss/env-nextjs to centralize and validate environment access. Non-secret config (IQ/HiIQ/Sophia addresses, IQ gateway URL, public PostHog key) carries in-code defaults that are byte-identical to the deployed Vercel values, so while the Vercel vars stay set they override with the same value (no behavior change) and can later be removed. The PostHog key branches on NEXT_PUBLIC_IS_PROD since it differs between production and preview/development. Genuine secrets (alchemy key, gateway key) have no default and are required from the environment, so a missing value now fails fast at boot instead of silently becoming "undefined". --- src/env.ts | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/env.ts diff --git a/src/env.ts b/src/env.ts new file mode 100644 index 0000000..184cc82 --- /dev/null +++ b/src/env.ts @@ -0,0 +1,71 @@ +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod"; + +/** + * Production is the only environment that diverges for env-varying values; + * preview and development share the non-prod values. Set NEXT_PUBLIC_IS_PROD + * to "true" in the production deployment so the prod-side defaults apply once + * the corresponding Vercel vars are removed. + */ +const isProd = process.env.NEXT_PUBLIC_IS_PROD === "true"; + +export const env = createEnv({ + /** + * Client-side env vars. Everything this app reads is `NEXT_PUBLIC_`-prefixed + * (it ships to the browser), so there are no server-only vars. + * + * Non-secret values carry in-code `.default()`s that are byte-identical to + * the deployed Vercel values. While the Vercel vars stay set they override + * these with the same value (no behavior change); once removed, the defaults + * take over. Genuine secrets have no default and must come from the env. + */ + client: { + // Constant across all environments: + NEXT_PUBLIC_IQ_ADDRESS: z + .string() + .min(1) + .default("0x579cea1889991f68acc35ff5c3dd0621ff29b0c9"), + NEXT_PUBLIC_HIIQ_ADDRESS: z + .string() + .min(1) + .default("0x1bf5457ecaa14ff63cc89efd560e251e814e16ba"), + NEXT_PUBLIC_SOPHIA_AGENT_ADDRESS: z + .string() + .min(1) + .default("0x4dBcC239b265295500D2Fe2d0900629BDcBBD0fB"), + NEXT_PUBLIC_IQ_GATEWAY_URL: z + .string() + .url() + .default("https://gateway.braindao.org"), + + // Public PostHog project key โ€” differs prod vs preview/dev, so the + // default branches on isProd. + NEXT_PUBLIC_POSTHOG_KEY: z + .string() + .min(1) + .default( + isProd + ? "phc_4MsVVKQqCaAJUKqSLTIbPpEEl4fWW8h8FKV8mj7Wjsf" + : "phc_cRzhhwKmv122zsoEzDViTsRWaFNxPP9GeZJ5p4eWniZ", + ), + + // Secrets โ€” required from the environment, no default: + NEXT_PUBLIC_ALCHEMY_API_KEY: z.string().min(1), + NEXT_PUBLIC_IQ_GATEWAY_KEY: z.string().min(1), + }, + /** + * Next.js inlines `NEXT_PUBLIC_` vars at build time, so each must be listed + * here as a literal `process.env.X` reference. + */ + experimental__runtimeEnv: { + NEXT_PUBLIC_IQ_ADDRESS: process.env.NEXT_PUBLIC_IQ_ADDRESS, + NEXT_PUBLIC_HIIQ_ADDRESS: process.env.NEXT_PUBLIC_HIIQ_ADDRESS, + NEXT_PUBLIC_SOPHIA_AGENT_ADDRESS: + process.env.NEXT_PUBLIC_SOPHIA_AGENT_ADDRESS, + NEXT_PUBLIC_IQ_GATEWAY_URL: process.env.NEXT_PUBLIC_IQ_GATEWAY_URL, + NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY, + NEXT_PUBLIC_ALCHEMY_API_KEY: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY, + NEXT_PUBLIC_IQ_GATEWAY_KEY: process.env.NEXT_PUBLIC_IQ_GATEWAY_KEY, + }, + emptyStringAsUndefined: true, +}); From 57ed3b63eda49039db9fbcb0554fc873c686c778 Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Mon, 29 Jun 2026 15:36:36 +0100 Subject: [PATCH 4/9] refactor(config): migrate consumers to @/env and remove config.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Point every consumer at the new validated @/env module and delete the unvalidated src/config/index.ts. The config object's dead fields (chainId, alchemyChain, walletConnectProjectId โ€” declared but never read) are dropped in the process. theme.ts is left unchanged: it keeps reading NEXT_PUBLIC_THEME directly so the seasonal theme stays a runtime toggle. --- src/app/[locale]/_actions.ts | 8 ++-- src/components/layouts/CgPosthogProvider.tsx | 12 +++--- src/config/index.ts | 11 ----- src/modules/alchemyFetch.ts | 4 +- src/modules/fetchCoinMarketData.ts | 6 +-- src/modules/getLockOverview.ts | 42 ++++++++++---------- src/modules/getTVL.ts | 40 +++++++++---------- 7 files changed, 56 insertions(+), 67 deletions(-) delete mode 100644 src/config/index.ts diff --git a/src/app/[locale]/_actions.ts b/src/app/[locale]/_actions.ts index 9a288ee..adff9a1 100644 --- a/src/app/[locale]/_actions.ts +++ b/src/app/[locale]/_actions.ts @@ -1,4 +1,4 @@ -import config from "@/config"; +import { env } from "@/env"; import { formatNumber } from "@/modules/helpers/numFormatter"; import axios, { AxiosError } from "axios"; import { @@ -8,7 +8,7 @@ import { } from "./_schema"; const CACHE_DURATION_SECONDS_12_HR_IN_SECONDS = 12 * 60 * 60; -const SOPHIA_STATS_API_URL = `https://app.iqai.com/api/agents/stats?address=${config.sophiaAgentAddress}`; +const SOPHIA_STATS_API_URL = `https://app.iqai.com/api/agents/stats?address=${env.NEXT_PUBLIC_SOPHIA_AGENT_ADDRESS}`; export async function getIqStats() { try { @@ -85,9 +85,9 @@ export async function getSophiaStats() { async function fetchMarketCapData(): Promise { try { - const response = await axios.get(`${config.iqGatewayUrl}`, { + const response = await axios.get(`${env.NEXT_PUBLIC_IQ_GATEWAY_URL}`, { headers: { - "x-api-key": config.iqGatewayKey, + "x-api-key": env.NEXT_PUBLIC_IQ_GATEWAY_KEY, }, params: { url: "https://pro-api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=everipedia", diff --git a/src/components/layouts/CgPosthogProvider.tsx b/src/components/layouts/CgPosthogProvider.tsx index c62a4d4..94ad198 100644 --- a/src/components/layouts/CgPosthogProvider.tsx +++ b/src/components/layouts/CgPosthogProvider.tsx @@ -1,16 +1,16 @@ "use client"; -import config from "@/config"; +import { env } from "@/env"; import posthog from "posthog-js"; import { PostHogProvider } from "posthog-js/react"; if (typeof window !== "undefined") { - posthog.init(config.posthogApiKey, { - api_host: "/ingest", - ui_host: "https://us.posthog.com", - }); + posthog.init(env.NEXT_PUBLIC_POSTHOG_KEY, { + api_host: "/ingest", + ui_host: "https://us.posthog.com", + }); } export const CSPostHogProvider = ({ children }: React.PropsWithChildren) => { - return {children}; + return {children}; }; diff --git a/src/config/index.ts b/src/config/index.ts deleted file mode 100644 index dac1706..0000000 --- a/src/config/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -const config = { - iqAddress: "0x579cea1889991f68acc35ff5c3dd0621ff29b0c9", - hiiqAddress: "0x1bf5457ecaa14ff63cc89efd560e251e814e16ba", - sophiaAgentAddress: "0x4dBcC239b265295500D2Fe2d0900629BDcBBD0fB", - iqGatewayUrl: "https://gateway.braindao.org", - alchemyApiKey: String(process.env.NEXT_PUBLIC_ALCHEMY_API_KEY), - iqGatewayKey: process.env.NEXT_PUBLIC_IQ_GATEWAY_KEY || "", - posthogApiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY || "", -}; - -export default config; diff --git a/src/modules/alchemyFetch.ts b/src/modules/alchemyFetch.ts index ccae9f4..d9e5455 100644 --- a/src/modules/alchemyFetch.ts +++ b/src/modules/alchemyFetch.ts @@ -1,4 +1,4 @@ -import config from "@/config"; +import { env } from "@/env"; export const HEX_BASE = 16; export const WEI_TO_ETHER_DIVISOR = 10e17; @@ -13,7 +13,7 @@ type RPCParams = [EthCallParams, string] | unknown[]; export const alchemyFetch = async (method: string, params: RPCParams) => { const response = await fetch( - `https://eth-mainnet.alchemyapi.io/v2/${config.alchemyApiKey}`, + `https://eth-mainnet.alchemyapi.io/v2/${env.NEXT_PUBLIC_ALCHEMY_API_KEY}`, { method: "POST", headers: { diff --git a/src/modules/fetchCoinMarketData.ts b/src/modules/fetchCoinMarketData.ts index c7cac10..30651c5 100644 --- a/src/modules/fetchCoinMarketData.ts +++ b/src/modules/fetchCoinMarketData.ts @@ -1,4 +1,4 @@ -import config from "@/config"; +import { env } from "@/env"; const CACHE_TIME = 60 * 60 * 24; export const formatNumber = new Intl.NumberFormat("en", { @@ -6,7 +6,7 @@ export const formatNumber = new Intl.NumberFormat("en", { }).format; export const fetchCoinMarketData = async () => { - const proxyUrl = new URL(config.iqGatewayUrl); + const proxyUrl = new URL(env.NEXT_PUBLIC_IQ_GATEWAY_URL); const targetUrl = "https://pro-api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=everipedia"; @@ -16,7 +16,7 @@ export const fetchCoinMarketData = async () => { try { const response = await fetch(proxyUrl.href, { headers: { - "x-api-key": config.iqGatewayKey, + "x-api-key": env.NEXT_PUBLIC_IQ_GATEWAY_KEY, }, }); diff --git a/src/modules/getLockOverview.ts b/src/modules/getLockOverview.ts index a9fc29c..6b426f5 100644 --- a/src/modules/getLockOverview.ts +++ b/src/modules/getLockOverview.ts @@ -1,30 +1,30 @@ -import config from "@/config"; +import { env } from "@/env"; import { HEX_BASE, WEI_TO_ETHER_DIVISOR, alchemyFetch } from "./alchemyFetch"; const getTotalHiiqSupply = async () => { - try { - const data = await alchemyFetch("eth_call", [ - { - to: config.hiiqAddress, - data: "0x18160ddd", - }, - "latest", - ]); + try { + const data = await alchemyFetch("eth_call", [ + { + to: env.NEXT_PUBLIC_HIIQ_ADDRESS, + data: "0x18160ddd", + }, + "latest", + ]); - const totalHiiq = Number.parseInt(data, HEX_BASE) / WEI_TO_ETHER_DIVISOR; - return totalHiiq; - } catch (error) { - console.error("๐Ÿšจ Error getting total hiIQ supply", error); - throw new Error("๐Ÿšจ Error getting total hiIQ supply"); - } + const totalHiiq = Number.parseInt(data, HEX_BASE) / WEI_TO_ETHER_DIVISOR; + return totalHiiq; + } catch (error) { + console.error("๐Ÿšจ Error getting total hiIQ supply", error); + throw new Error("๐Ÿšจ Error getting total hiIQ supply"); + } }; export const getLockOverview = async () => { - const totalHiiqSupply = await getTotalHiiqSupply(); + const totalHiiqSupply = await getTotalHiiqSupply(); - return { - totalSupplyError: totalHiiqSupply === 0, - isFetchingTotalSupply: false, - totalHiiqSupply, - }; + return { + totalSupplyError: totalHiiqSupply === 0, + isFetchingTotalSupply: false, + totalHiiqSupply, + }; }; diff --git a/src/modules/getTVL.ts b/src/modules/getTVL.ts index 19083e9..2b7a503 100644 --- a/src/modules/getTVL.ts +++ b/src/modules/getTVL.ts @@ -1,25 +1,25 @@ -import config from "@/config"; +import { env } from "@/env"; import { HEX_BASE, WEI_TO_ETHER_DIVISOR, alchemyFetch } from "./alchemyFetch"; export const getTvl = async () => { - try { - const data = await alchemyFetch("eth_call", [ - { - from: "0x0000000000000000000000000000000000000000", - to: config.iqAddress, - data: `0x70a08231000000000000000000000000${config.hiiqAddress.replace( - "0x", - "" - )}`, - }, - "latest", - ]); + try { + const data = await alchemyFetch("eth_call", [ + { + from: "0x0000000000000000000000000000000000000000", + to: env.NEXT_PUBLIC_IQ_ADDRESS, + data: `0x70a08231000000000000000000000000${env.NEXT_PUBLIC_HIIQ_ADDRESS.replace( + "0x", + "", + )}`, + }, + "latest", + ]); - let tvl = Number.parseInt(data, HEX_BASE); - tvl = tvl / WEI_TO_ETHER_DIVISOR; - return Math.floor(tvl); - } catch (error) { - console.error("๐Ÿšจ Error getting TVL", error); - throw new Error("๐Ÿšจ Error getting TVL"); - } + let tvl = Number.parseInt(data, HEX_BASE); + tvl = tvl / WEI_TO_ETHER_DIVISOR; + return Math.floor(tvl); + } catch (error) { + console.error("๐Ÿšจ Error getting TVL", error); + throw new Error("๐Ÿšจ Error getting TVL"); + } }; From ee45ac18908e72f1458da93f19a9b50779f2b915 Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Mon, 29 Jun 2026 15:45:56 +0100 Subject: [PATCH 5/9] chore(env): update secrets in env configuration --- src/env.ts | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/env.ts b/src/env.ts index 184cc82..e9b6f67 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,26 +1,10 @@ import { createEnv } from "@t3-oss/env-nextjs"; import { z } from "zod"; -/** - * Production is the only environment that diverges for env-varying values; - * preview and development share the non-prod values. Set NEXT_PUBLIC_IS_PROD - * to "true" in the production deployment so the prod-side defaults apply once - * the corresponding Vercel vars are removed. - */ const isProd = process.env.NEXT_PUBLIC_IS_PROD === "true"; export const env = createEnv({ - /** - * Client-side env vars. Everything this app reads is `NEXT_PUBLIC_`-prefixed - * (it ships to the browser), so there are no server-only vars. - * - * Non-secret values carry in-code `.default()`s that are byte-identical to - * the deployed Vercel values. While the Vercel vars stay set they override - * these with the same value (no behavior change); once removed, the defaults - * take over. Genuine secrets have no default and must come from the env. - */ client: { - // Constant across all environments: NEXT_PUBLIC_IQ_ADDRESS: z .string() .min(1) @@ -37,9 +21,6 @@ export const env = createEnv({ .string() .url() .default("https://gateway.braindao.org"), - - // Public PostHog project key โ€” differs prod vs preview/dev, so the - // default branches on isProd. NEXT_PUBLIC_POSTHOG_KEY: z .string() .min(1) @@ -48,15 +29,9 @@ export const env = createEnv({ ? "phc_4MsVVKQqCaAJUKqSLTIbPpEEl4fWW8h8FKV8mj7Wjsf" : "phc_cRzhhwKmv122zsoEzDViTsRWaFNxPP9GeZJ5p4eWniZ", ), - - // Secrets โ€” required from the environment, no default: NEXT_PUBLIC_ALCHEMY_API_KEY: z.string().min(1), NEXT_PUBLIC_IQ_GATEWAY_KEY: z.string().min(1), }, - /** - * Next.js inlines `NEXT_PUBLIC_` vars at build time, so each must be listed - * here as a literal `process.env.X` reference. - */ experimental__runtimeEnv: { NEXT_PUBLIC_IQ_ADDRESS: process.env.NEXT_PUBLIC_IQ_ADDRESS, NEXT_PUBLIC_HIIQ_ADDRESS: process.env.NEXT_PUBLIC_HIIQ_ADDRESS, From f24622906e5fffa63cdc6e1871d19d88eeced58e Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Mon, 29 Jun 2026 16:17:46 +0100 Subject: [PATCH 6/9] fix(alchemyFetch): update API key reference to use NEXT_PUBLIC_ALCHEMY_API_KEY --- src/modules/alchemyFetch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/alchemyFetch.ts b/src/modules/alchemyFetch.ts index 9f4c1ed..d9e5455 100644 --- a/src/modules/alchemyFetch.ts +++ b/src/modules/alchemyFetch.ts @@ -13,7 +13,7 @@ type RPCParams = [EthCallParams, string] | unknown[]; export const alchemyFetch = async (method: string, params: RPCParams) => { const response = await fetch( - `https://eth-mainnet.alchemyapi.io/v2/${env.alchemyApiKey}`, + `https://eth-mainnet.alchemyapi.io/v2/${env.NEXT_PUBLIC_ALCHEMY_API_KEY}`, { method: "POST", headers: { From c43268206cefbf7e0dc89a778d420a60c4fce156 Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Tue, 30 Jun 2026 07:08:20 +0100 Subject: [PATCH 7/9] fix(env): update production environment check to use NEXT_PUBLIC_VERCEL_ENV --- src/env.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/env.ts b/src/env.ts index e9b6f67..9f6e772 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,7 +1,7 @@ import { createEnv } from "@t3-oss/env-nextjs"; import { z } from "zod"; -const isProd = process.env.NEXT_PUBLIC_IS_PROD === "true"; +const isProd = process.env.NEXT_PUBLIC_VERCEL_ENV === "production"; export const env = createEnv({ client: { From 66d2a7fbfb8da28c13d404a5dfa162f98191c7d5 Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Tue, 30 Jun 2026 10:19:52 +0100 Subject: [PATCH 8/9] fix(alchemyFetch): update Alchemy API endpoint to use the correct URL --- src/modules/alchemyFetch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/alchemyFetch.ts b/src/modules/alchemyFetch.ts index d9e5455..7596f2f 100644 --- a/src/modules/alchemyFetch.ts +++ b/src/modules/alchemyFetch.ts @@ -13,7 +13,7 @@ type RPCParams = [EthCallParams, string] | unknown[]; export const alchemyFetch = async (method: string, params: RPCParams) => { const response = await fetch( - `https://eth-mainnet.alchemyapi.io/v2/${env.NEXT_PUBLIC_ALCHEMY_API_KEY}`, + `https://eth-mainnet.g.alchemy.com/v2/${env.NEXT_PUBLIC_ALCHEMY_API_KEY}`, { method: "POST", headers: { From 8757e476c94d635d367a454d32a75df6fb7388f1 Mon Sep 17 00:00:00 2001 From: Olutoke Adedamola Date: Tue, 30 Jun 2026 11:00:24 +0100 Subject: [PATCH 9/9] chore(footer): update business contact text for clarity and improve email link presentation --- messages/en.json | 2 +- messages/kr.json | 2 +- messages/zh.json | 2 +- src/components/layouts/Footer.tsx | 18 +++++++----------- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/messages/en.json b/messages/en.json index daed622..ab34e69 100644 --- a/messages/en.json +++ b/messages/en.json @@ -182,7 +182,7 @@ }, "business": { "title": "For business Inquiries", - "contact": "Contact us", + "contact": "Contact us via email", "email": "tara@iq.wiki" }, "social": { diff --git a/messages/kr.json b/messages/kr.json index 704d521..c31685e 100644 --- a/messages/kr.json +++ b/messages/kr.json @@ -182,7 +182,7 @@ }, "business": { "title": "์‚ฌ์—… ๋ฌธ์˜", - "contact": "๋ฌธ์˜ํ•˜๊ธฐ", + "contact": "์ด๋ฉ”์ผ๋กœ ๋ฌธ์˜ํ•˜๊ธฐ", "email": "tara@iq.wiki" }, "social": { diff --git a/messages/zh.json b/messages/zh.json index d32baaf..40fba44 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -182,7 +182,7 @@ }, "business": { "title": "ๅ•†ๅŠกๅ’จ่ฏข", - "contact": "่”็ณปๆˆ‘ไปฌ", + "contact": "้€š่ฟ‡็”ตๅญ้‚ฎไปถ่”็ณปๆˆ‘ไปฌ", "email": "tara@iq.wiki" }, "social": { diff --git a/src/components/layouts/Footer.tsx b/src/components/layouts/Footer.tsx index aed9106..05cb458 100644 --- a/src/components/layouts/Footer.tsx +++ b/src/components/layouts/Footer.tsx @@ -45,17 +45,13 @@ const Footer = async () => {

{t("business.title")}

-
-

- {t("business.contact")} -

- - {t("business.email")} - -
+ + {t("business.contact")} +