Skip to content

Commit

Permalink
feat: new and improved environments handling (#618)
Browse files Browse the repository at this point in the history
* feat: new and improved environments handling

* fix(frontend): only enable template preview mode in non-production deployments

* fix(frontend): only disable service worker in development environment

* chore(shared-state): update main entrypoint in package.json

* chore(sdk): move shared-state lib from dev to prod dependencies

---------

Co-authored-by: luzzifoss <[email protected]>
  • Loading branch information
luzzif and luzzifoss authored Mar 18, 2024
1 parent a02c59e commit c579660
Show file tree
Hide file tree
Showing 43 changed files with 193 additions and 217 deletions.
9 changes: 9 additions & 0 deletions .changeset/light-berries-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@carrot-kpi/shared-state": minor
"@carrot-kpi/host-frontend": minor
"@carrot-kpi/react": minor
"@carrot-kpi/sdk": minor
"@carrot-kpi/ui": minor
---

New environments handling
5 changes: 3 additions & 2 deletions packages/frontend/craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ const { EsbuildPlugin } = require("esbuild-loader");
const { join } = require("node:path");
const shared = require("./shared-dependencies.json");
const { getEnv } = require("./utils/env");
const { Environment } = require("@carrot-kpi/shared-state");

const ALLOWED_ENVIRONMENTS = ["prod", "staging", "dev", "library"];
const ALLOWED_ENVIRONMENTS = Object.values(Environment);

const environment = process.env.ENVIRONMENT;
if (ALLOWED_ENVIRONMENTS.indexOf(environment) < 0) {
if (!Object.values(Environment).includes(environment)) {
console.error(
`Invalid environment "${environment}" specified. Allowed values are: ${ALLOWED_ENVIRONMENTS.join(
", ",
Expand Down
5 changes: 2 additions & 3 deletions packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@
"size-limit": "size-limit",
"prepare-fathom": "prepare-fathom",
"config-react-env": "./scripts/config-react-env.js",
"start:production": "yarn prepare-fathom && ENVIRONMENT=prod craco start",
"start:production": "yarn prepare-fathom && ENVIRONMENT=production craco start",
"start:staging": "yarn prepare-fathom && ENVIRONMENT=staging craco start",
"start:dev": "yarn prepare-fathom && ENVIRONMENT=dev craco start",
"start": "craco start",
"start:dev": "yarn prepare-fathom && ENVIRONMENT=development craco start",
"synpress:run": "env-cmd -f ../../.env.e2e synpress run --browser chrome --configFile synpress.config.js",
"test:e2e": "start-server-and-test 'yarn start:staging' http-get://127.0.0.1:3000 'yarn synpress:run'"
},
Expand Down
3 changes: 2 additions & 1 deletion packages/frontend/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import json from "@rollup/plugin-json";
import replace from "@rollup/plugin-replace";
import esbuild from "rollup-plugin-esbuild";
import { createRequire } from "module";
import { Environment } from "@carrot-kpi/shared-state";

const require = createRequire(import.meta.url);
const { getEnv } = require("./utils/env");
Expand All @@ -25,7 +26,7 @@ export default [
replace({
preventAssignment: true,
values: {
__ENVIRONMENT__: JSON.stringify("library"),
__ENVIRONMENT__: JSON.stringify(Environment.Local),
__INFURA_PROJECT_ID__: getEnv("INFURA_PROJECT_ID", true),
__WALLETCONNECT_PROJECT_ID__: JSON.stringify(""),
__FATHOM_SITE_ID__: JSON.stringify(""),
Expand Down
15 changes: 8 additions & 7 deletions packages/frontend/src/components/authenticate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import { t } from "i18next";
import { useAccount, useSignMessage } from "wagmi";
import { useSetDataManagerJWT } from "../hooks/useSetDataManagerJWT";
import { WalletDisconnected } from "./wallet-disconnected";
import { SERVICE_URLS } from "@carrot-kpi/sdk";

interface AuthenticateProps {
onCancel: () => void;
}

export const Authenticate = ({ onCancel }: AuthenticateProps) => {
const { chain, address } = useAccount();
const { address } = useAccount();
const setDataManagerJWT = useSetDataManagerJWT();

const [loading, setLoading] = useState(false);
Expand All @@ -20,11 +21,11 @@ export const Authenticate = ({ onCancel }: AuthenticateProps) => {

useEffect(() => {
const fetchData = async () => {
if (!chain || !address || !signedLoginMessage) return;
if (!address || !signedLoginMessage) return;
setLoading(true);
try {
const response = await fetch(
`${chain.serviceUrls.dataManager}/token`,
`${SERVICE_URLS[__ENVIRONMENT__].dataManager}/token`,
{
method: "POST",
headers: {
Expand All @@ -50,15 +51,15 @@ export const Authenticate = ({ onCancel }: AuthenticateProps) => {
}
};
fetchData();
}, [chain, address, setDataManagerJWT, signedLoginMessage]);
}, [address, setDataManagerJWT, signedLoginMessage]);

const handleSign = useCallback(() => {
const fetchSignableMessage = async () => {
if (!chain || !address) return;
if (!address) return;
setLoading(true);
try {
const response = await fetch(
`${chain.serviceUrls.dataManager}/login-message/${address}`,
`${SERVICE_URLS[__ENVIRONMENT__].dataManager}/login-message/${address}`,
);
if (!response.ok) throw new Error(await response.text());
const { message } = (await response.json()) as {
Expand All @@ -74,7 +75,7 @@ export const Authenticate = ({ onCancel }: AuthenticateProps) => {
}
};
fetchSignableMessage();
}, [chain, address, signMessage]);
}, [address, signMessage]);

return (
<div className="w-full h-full flex justify-center">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ export function CampaignCreationForm<S extends SerializableObject<S>>() {
}
const resolvedTemplates = await Fetcher.resolveTemplates({
ipfsGatewayURL,
dataCDNURL: chain.serviceUrls.dataCdn,
preferDecentralization,
templates: templates,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { NetworksPopover } from "./networks-popover";
import { Typography } from "@carrot-kpi/ui";
import { useTranslation } from "react-i18next";
import { useClickAway } from "react-use";
import { Environment } from "@carrot-kpi/shared-state";

export interface ChainSelectProps {
compact?: boolean;
Expand Down Expand Up @@ -47,7 +48,7 @@ export const ChainSelect = ({ compact = true }: ChainSelectProps) => {

return (
<div>
{__ENVIRONMENT__ !== "library" && (
{__ENVIRONMENT__ !== Environment.Local && (
<NetworksPopover
open={networksPopoverOpen}
anchor={networksPopoverAnchor}
Expand All @@ -58,7 +59,7 @@ export const ChainSelect = ({ compact = true }: ChainSelectProps) => {
<div
data-testid="network-drop-down-button"
className={`h-11 w-fit flex items-center border border-black dark:border-white px-[10px] rounded-lg ${
__ENVIRONMENT__ === "library" || chains.length === 1
__ENVIRONMENT__ === Environment.Local || chains.length === 1
? ""
: "cursor-pointer"
} gap-3`}
Expand All @@ -80,7 +81,7 @@ export const ChainSelect = ({ compact = true }: ChainSelectProps) => {
{chain?.name || t("connect.wallet.unknown")}
</Typography>
)}
{__ENVIRONMENT__ !== "library" && chains.length > 1 && (
{__ENVIRONMENT__ !== Environment.Local && chains.length > 1 && (
<CaretDown className="w-3 dark:text-white" />
)}
</div>
Expand Down
42 changes: 22 additions & 20 deletions packages/frontend/src/components/connect-wallet/preferences.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "@carrot-kpi/react";
import { useTranslation } from "react-i18next";
import { useAccount } from "wagmi";
import { Environment } from "@carrot-kpi/shared-state";

// TODO: move this in the UI lib with additional functionality (like variants for info, warning and error feedback)
export const Preferences = () => {
Expand Down Expand Up @@ -88,31 +89,32 @@ export const Preferences = () => {
/>
</div>
</div> */}
{!!chain?.serviceUrls.subgraph && __ENVIRONMENT__ !== "dev" && (
<div className="flex flex-col border border-black dark:border-white rounded-lg">
<div className="flex gap-2 items-center justify-between p-4 border-b border-black dark:border-white">
<Typography
data-testid="decentralization-mode-text"
variant="base"
weight="bold"
>
{t("preferences.decentralization")}
{!!chain?.subgraphUrl &&
__ENVIRONMENT__ !== Environment.Development && (
<div className="flex flex-col border border-black dark:border-white rounded-lg">
<div className="flex gap-2 items-center justify-between p-4 border-b border-black dark:border-white">
<Typography
data-testid="decentralization-mode-text"
variant="base"
weight="bold"
>
{t("preferences.decentralization")}
</Typography>
<Switch
data-testid="decentralization-mode-switch"
checked={preferDecentralization}
onChange={setPreferDecentralization}
/>
</div>
<Typography variant="sm" className={{ root: "p-4" }}>
{t("preferences.decentralization.info")}
</Typography>
<Switch
data-testid="decentralization-mode-switch"
checked={preferDecentralization}
onChange={setPreferDecentralization}
/>
</div>
<Typography variant="sm" className={{ root: "p-4" }}>
{t("preferences.decentralization.info")}
</Typography>
</div>
)}
)}
{/* TODO: this setting is applied to both dev and staging environments but it's simply called "staging" mode.
We need to find a name that is compatible with the fact that this setting should be available in both the dev
and staging environments. Maybe preview mode? */}
{__ENVIRONMENT__ !== "prod" && (
{__ENVIRONMENT__ !== Environment.Production && (
<div className="flex flex-col border border-black dark:border-white rounded-lg">
<div className="flex gap-2 items-center justify-between p-4 border-b border-black dark:border-white">
<Typography
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export const CreateCampaignButton = ({
try {
const resolved = await Fetcher.resolveTemplates({
ipfsGatewayURL,
dataCDNURL: chain.serviceUrls.dataCdn,
preferDecentralization,
templates: [template],
});
Expand Down
52 changes: 19 additions & 33 deletions packages/frontend/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { http, type Transport } from "viem";
import { SUPPORTED_CHAIN, type SupportedChain } from "@carrot-kpi/sdk";
import type { SVGIcon } from "./icons/types";
import { ChainId } from "@carrot-kpi/sdk";
import { Environment } from "@carrot-kpi/shared-state";

export const CARROT_KPI_FRONTEND_I18N_NAMESPACE = "@carrot-kpi/frontend";

Expand All @@ -23,47 +24,32 @@ export interface CarrotChain extends SupportedChain {
icon: ChainIconData;
}

export const SUPPORTED_CHAINS: [CarrotChain, ...CarrotChain[]] =
__ENVIRONMENT__ === "dev"
? ([
{
...SUPPORTED_CHAIN[ChainId.ArbitrumSepolia],
icon: {
logo: ArbitrumLogo,
backgroundColor: "#213147",
},
},
] as const)
: __ENVIRONMENT__ === "staging"
? ([
{
...SUPPORTED_CHAIN[ChainId.Sepolia],
icon: {
logo: EthereumLogo,
backgroundColor: "#8637ea",
},
},
] as const)
: // FIXME: this is not a prod chain but it's here until we have an actual production deployment
([
{
...SUPPORTED_CHAIN[ChainId.ArbitrumSepolia],
icon: {
logo: ArbitrumLogo,
backgroundColor: "#213147",
},
},
] as const);
export const SUPPORTED_CHAINS: [CarrotChain, ...CarrotChain[]] = [
{
...SUPPORTED_CHAIN[ChainId.Sepolia],
icon: {
logo: EthereumLogo,
backgroundColor: "#8637ea",
},
},
{
...SUPPORTED_CHAIN[ChainId.ArbitrumSepolia],
icon: {
logo: ArbitrumLogo,
backgroundColor: "#213147",
},
},
] as const;

export const SUPPORTED_CHAIN_TRANSPORT: Record<ChainId, Transport> = {
[sepolia.id as number]: http(),
[arbitrumSepolia.id as number]: http(),
};

export const CARROT_DOMAIN =
__ENVIRONMENT__ === "prod"
__ENVIRONMENT__ === Environment.Production
? "carrot.community"
: __ENVIRONMENT__ === "staging"
: __ENVIRONMENT__ === Environment.Staging
? "staging.carrot.community"
: "dev.carrot.community";

Expand Down
1 change: 0 additions & 1 deletion packages/frontend/src/hooks/useSearchResolvedKPITokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export function useSearchResolvedKPITokens(searchQuery: string) {
return (
await Fetcher.resolveKPITokens({
ipfsGatewayURL,
dataCDNURL: chain.serviceUrls.dataCdn,
preferDecentralization,
kpiTokens: [kpiToken],
})
Expand Down
3 changes: 2 additions & 1 deletion packages/frontend/src/pages/home/hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { NAVBAR_LINKS } from "../../constants";
import VideoPoster from "../../images/video-poster.png";
import type { KPIToken } from "@carrot-kpi/sdk";
import { Navbar } from "../../components/ui/navbar";
import { Environment } from "@carrot-kpi/shared-state";

const plusIconStyles = cva(["invisible", "md:visible", "absolute"], {
variants: {
Expand Down Expand Up @@ -142,7 +143,7 @@ export const Hero = ({ featuredKPITokens }: HeroProps) => {
<Button variant="primary" size="big">
<Link to="/campaigns">{t("campaign.all")}</Link>
</Button>
{__ENVIRONMENT__ !== "library" && (
{__ENVIRONMENT__ !== Environment.Local && (
<CreateCampaignButton />
)}
</div>
Expand Down
3 changes: 2 additions & 1 deletion packages/frontend/src/react-app-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import {
type CarrotChain,
} from "./constants";
import type { Config } from "wagmi";
import type { Environment } from "@carrot-kpi/shared-state";

declare global {
const __ENVIRONMENT__: "dev" | "staging" | "prod" | "library";
const __ENVIRONMENT__: Environment;
const __INFURA_PROJECT_ID__: string;
const __WALLETCONNECT_PROJECT_ID__: string | undefined;
const __FATHOM_SITE_ID__: string | undefined;
Expand Down
21 changes: 14 additions & 7 deletions packages/frontend/src/standalone-entrypoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ import {
SUPPORTED_CHAINS,
} from "./constants";
import { HostStateProvider } from "./state";
import { ReactSharedStateProvider } from "@carrot-kpi/shared-state";
import {
useSetDevMode,
Environment,
ReactSharedStateProvider,
} from "@carrot-kpi/shared-state";
import {
useSetEnvironment,
useSetIPFSGatewayURL,
useSetTemplatePreviewMode,
} from "@carrot-kpi/react";
Expand Down Expand Up @@ -60,18 +63,19 @@ export const config = createConfig({
});

export const Root = () => {
const setDevMode = useSetDevMode();
const setEnvironment = useSetEnvironment();
const setTemplatePreviewMode = useSetTemplatePreviewMode();
const setIPFSGatewayURL = useSetIPFSGatewayURL();

setDevMode(false);
setTemplatePreviewMode(__ENVIRONMENT__ !== "prod");
setEnvironment(__ENVIRONMENT__);
setTemplatePreviewMode(__ENVIRONMENT__ !== Environment.Production);
setIPFSGatewayURL(IPFS_GATEWAY_URL);

return (
<SharedEntrypoint
config={config}
enableFathom={__ENVIRONMENT__ === "prod"}
// FIXME: enable this in production
enableFathom={false}
/>
);
};
Expand All @@ -89,7 +93,10 @@ root.render(
</StrictMode>,
);

if (__ENVIRONMENT__ === "prod" && "serviceWorker" in navigator) {
if (
__ENVIRONMENT__ !== Environment.Development &&
"serviceWorker" in navigator
) {
navigator.serviceWorker
.register("./sw.js")
.then(() => {
Expand Down
Loading

0 comments on commit c579660

Please sign in to comment.