feat(environment): feature flags

This commit is contained in:
asiaznik
2023-07-20 11:41:50 +02:00
parent 8ff46bab5b
commit e9935cbdca
3 changed files with 93 additions and 60 deletions
+24 -2
View File
@@ -12,7 +12,7 @@ import {
NodeCheckDocument,
NodeCheckTimeUpdateDocument,
} from '../utils/__generated__/NodeCheck';
import type { Environment } from '../types';
import type { Environment, FeatureFlags } from '../types';
import { Networks } from '../types';
import { compileErrors } from '../utils/compile-errors';
import { envSchema } from '../utils/validate-environment';
@@ -39,8 +39,11 @@ const VERSION = 1;
export const STORAGE_KEY = `vega_url_${VERSION}`;
const SUBSCRIPTION_TIMEOUT = 3000;
export const FLAGS = compileFeatureFlags();
export const useEnvironment = create<EnvStore>()((set, get) => ({
...compileEnvVars(),
...compileFeatureFlags(),
nodes: [],
status: 'default',
error: null,
@@ -372,6 +375,23 @@ function compileEnvVars() {
return env;
}
function compileFeatureFlags(): FeatureFlags {
return {
CONSOLE_ICEBERG_ORDERS: truthy.includes(
windowOrDefault('NX_CONSOLE_ICEBERG_ORDERS')
),
CONSOLE_STOP_ORDERS: truthy.includes(
windowOrDefault('NX_CONSOLE_STOP_ORDERS')
),
CONSOLE_SUCCESSOR_MARKETS: truthy.includes(
windowOrDefault('NX_CONSOLE_SUCCESSOR_MARKETS')
),
CONSOLE_PRODUCT_PERPETUALS: truthy.includes(
windowOrDefault('NX_CONSOLE_PRODUCT_PERPETUALS')
),
};
}
function parseNetworks(value?: string) {
if (value) {
try {
@@ -414,7 +434,7 @@ function getEtherscanUrl(
export function windowOrDefault(key: string, defaultValue?: string) {
if (typeof window !== 'undefined') {
// @ts-ignore avoid conflic in env
// @ts-ignore avoid conflict in env
if (window._env_ && window._env_[key]) {
// @ts-ignore presence has been check above
return window._env_[key];
@@ -422,3 +442,5 @@ export function windowOrDefault(key: string, defaultValue?: string) {
}
return defaultValue || undefined;
}
const truthy = ['1', 'true'];
+5 -1
View File
@@ -1,6 +1,9 @@
import type z from 'zod';
import type { tomlConfigSchema } from './utils/validate-configuration';
import type { envSchema } from './utils/validate-environment';
import type {
envSchema,
featureFlagsSchema,
} from './utils/validate-environment';
export enum Networks {
VALIDATOR_TESTNET = 'VALIDATOR_TESTNET',
@@ -12,5 +15,6 @@ export enum Networks {
MAINNET = 'MAINNET',
}
export type Environment = z.infer<typeof envSchema>;
export type FeatureFlags = z.infer<typeof featureFlagsSchema>;
export type Configuration = z.infer<typeof tomlConfigSchema>;
export const CUSTOM_NODE_KEY = 'custom' as const;
@@ -10,62 +10,69 @@ export enum Networks {
MAINNET = 'MAINNET',
}
const schemaObject = {
VEGA_URL: z.optional(z.string()),
VEGA_WALLET_URL: z.optional(z.string()),
VEGA_CONFIG_URL: z.optional(z.string()),
GIT_BRANCH: z.optional(z.string()),
GIT_COMMIT_HASH: z.optional(z.string()),
GIT_ORIGIN_URL: z.optional(z.string()),
GITHUB_FEEDBACK_URL: z.optional(z.string()),
ORACLE_PROOFS_URL: z.optional(z.string().url()),
VEGA_ENV: z.nativeEnum(Networks),
VEGA_CONSOLE_URL: z.optional(z.string()),
VEGA_EXPLORER_URL: z.optional(z.string()),
VEGA_TOKEN_URL: z.optional(z.string()),
VEGA_DOCS_URL: z.optional(z.string()),
VEGA_NETWORKS: z
.object(
Object.keys(Networks).reduce(
(acc, env) => ({
...acc,
[env]: z.optional(z.string()),
}),
{}
) as Record<Networks, z.ZodOptional<z.ZodString>>
)
.strict({
message: `All keys in NX_VEGA_NETWORKS must represent a valid environment: ${Object.keys(
Networks
).join(' | ')}`,
}),
ETHEREUM_PROVIDER_URL: z.string().url({
message:
'The NX_ETHEREUM_PROVIDER_URL environment variable must be a valid url',
}),
ETHERSCAN_URL: z.string().url({
message: 'The NX_ETHERSCAN_URL environment variable must be a valid url',
}),
HOSTED_WALLET_URL: z.optional(z.string()),
MAINTENANCE_PAGE: z.optional(z.boolean()),
ETH_LOCAL_PROVIDER_URL: z.optional(z.string()),
ETH_WALLET_MNEMONIC: z.optional(z.string()),
ANNOUNCEMENTS_CONFIG_URL: z.optional(z.string()),
VEGA_INCIDENT_URL: z.optional(z.string()),
APP_VERSION: z.optional(z.string()),
SENTRY_DSN: z.optional(z.string()),
TENDERMINT_URL: z.optional(z.string()),
TENDERMINT_WEBSOCKET_URL: z.optional(z.string()),
};
// combine schema above with custom rule to ensure either
// VEGA_URL or VEGA_CONFIG_URL are provided
export const envSchema = z.object(schemaObject).refine(
(data) => {
return !(!data.VEGA_URL && !data.VEGA_CONFIG_URL);
},
{
message:
'Must provide either NX_VEGA_CONFIG_URL or NX_VEGA_URL in the environment.',
}
);
export const envSchema = z
.object({
VEGA_URL: z.optional(z.string()),
VEGA_WALLET_URL: z.optional(z.string()),
VEGA_CONFIG_URL: z.optional(z.string()),
GIT_BRANCH: z.optional(z.string()),
GIT_COMMIT_HASH: z.optional(z.string()),
GIT_ORIGIN_URL: z.optional(z.string()),
GITHUB_FEEDBACK_URL: z.optional(z.string()),
ORACLE_PROOFS_URL: z.optional(z.string().url()),
VEGA_ENV: z.nativeEnum(Networks),
VEGA_CONSOLE_URL: z.optional(z.string()),
VEGA_EXPLORER_URL: z.optional(z.string()),
VEGA_TOKEN_URL: z.optional(z.string()),
VEGA_DOCS_URL: z.optional(z.string()),
VEGA_NETWORKS: z
.object(
Object.keys(Networks).reduce(
(acc, env) => ({
...acc,
[env]: z.optional(z.string()),
}),
{}
) as Record<Networks, z.ZodOptional<z.ZodString>>
)
.strict({
message: `All keys in NX_VEGA_NETWORKS must represent a valid environment: ${Object.keys(
Networks
).join(' | ')}`,
}),
ETHEREUM_PROVIDER_URL: z.string().url({
message:
'The NX_ETHEREUM_PROVIDER_URL environment variable must be a valid url',
}),
ETHERSCAN_URL: z.string().url({
message: 'The NX_ETHERSCAN_URL environment variable must be a valid url',
}),
HOSTED_WALLET_URL: z.optional(z.string()),
MAINTENANCE_PAGE: z.optional(z.boolean()),
ETH_LOCAL_PROVIDER_URL: z.optional(z.string()),
ETH_WALLET_MNEMONIC: z.optional(z.string()),
ANNOUNCEMENTS_CONFIG_URL: z.optional(z.string()),
VEGA_INCIDENT_URL: z.optional(z.string()),
APP_VERSION: z.optional(z.string()),
SENTRY_DSN: z.optional(z.string()),
TENDERMINT_URL: z.optional(z.string()),
TENDERMINT_WEBSOCKET_URL: z.optional(z.string()),
})
.refine(
(data) => {
return !(!data.VEGA_URL && !data.VEGA_CONFIG_URL);
},
{
message:
'Must provide either NX_VEGA_CONFIG_URL or NX_VEGA_URL in the environment.',
}
);
export const featureFlagsSchema = z.object({
CONSOLE_SUCCESSOR_MARKETS: z.optional(z.boolean()),
CONSOLE_STOP_ORDERS: z.optional(z.boolean()),
CONSOLE_ICEBERG_ORDERS: z.optional(z.boolean()),
CONSOLE_PRODUCT_PERPETUALS: z.optional(z.boolean()),
});