feat(environment): feature flags
This commit is contained in:
@@ -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'];
|
||||
|
||||
@@ -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()),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user