vega-frontend-monorepo/libs/network-switcher/src/hooks/use-environment.tsx
Dexter Edwards bcaab22891
Feat/dockerize frontends (#388)
* feat: unhardcode contract addresses

* fix: linting and tests

* feat: switch contract usage in token app to use unhardcoded addresses

* chore: remove other usage of hard coded contract addresses

* feat: convert contracts to classes, update claim contract to fix circular dependency

* feat: add hard coded contract addresses to contracts page

* fix: misc tidy up

* chore: rename ethers big num conversion func

* fix: remove pending transactions modal

* chore: add single toBigNum function that can accept number string or EthersBignNumber

* chore: delete unused tranche helpers and decimals functions from smart contracts lib

* feat: add faucetable token class

* fix: reset tx state after early exit from approve tx

* feat: re add transaction modal using zustand store

* fix: loader colors for eth wallet

* fix: pass ethereum config to gurantee existence before tx execution

* add docker image for building explorer

* add arg

* env file changes

* add docker file to build env file

* add requirement for env file in explorer

* fix env file syntax

* containers functional

* default to testnet

* make env flag logic consistent in all places

* pre populate env file

* ensure working for all projects

* address PR comment

* generalising env for token

* invert config dependency from ui toolkit

* fix: merge issues

* docs: running containers documentation

* style: lint

* fix: env varibales not being added properly

* chore: fix merge issues

* chore: fix docker file to support new exectutors

* chore: set address on all contracts as a property

* feat: pull token from contract rather than relying on env var

* chore: fix typing

* chore: remove duplicated prop

* chore: don't use chainId

* style: lint

* style: lint

* Merge branch 'master' into feat/dockerize-frontends

* Merge remote-tracking branch 'origin/master' into feat/dockerize-frontends

* test: revert changes to explorer e2e file

* fix: creating client without base causing token to error

* test: fix tests erroring in before hook due to file not being found

* chore: remove node env from configurable flags

Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2022-06-13 15:39:17 +01:00

184 lines
4.9 KiB
TypeScript

import type { Networks } from '@vegaprotocol/react-helpers';
import type { ReactNode } from 'react';
import { useState } from 'react';
import { createContext, useContext } from 'react';
const isBrowser = typeof window !== 'undefined';
declare global {
interface Window {
_env_?: Record<string, string>;
}
}
interface VegaContracts {
claimAddress: string;
lockedAddress: string;
}
export const ContractAddresses: { [key in Networks]: VegaContracts } = {
DEVNET: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994',
lockedAddress: '0x0',
},
STAGNET: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
STAGNET2: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
TESTNET: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
MAINNET: {
claimAddress: '0x0ee1fb382caf98e86e97e51f9f42f8b4654020f3',
lockedAddress: '0x78344c7305d73a7a0ac3c94cd9960f4449a1814e',
},
};
type EnvironmentProviderProps = {
definitions?: Partial<RawEnvironment>;
children?: ReactNode;
};
export const ENV_KEYS = [
'VEGA_URL',
'VEGA_ENV',
'VEGA_NETWORKS',
'ETHEREUM_CHAIN_ID',
'ETHEREUM_PROVIDER_URL',
'ETHERSCAN_URL',
] as const;
type EnvKey = typeof ENV_KEYS[number];
type RawEnvironment = Record<EnvKey, string>;
export type Environment = {
VEGA_URL: string;
VEGA_ENV: Networks;
VEGA_NETWORKS: Record<Networks, string>;
ETHEREUM_CHAIN_ID: number;
ETHEREUM_PROVIDER_URL: string;
ETHERSCAN_URL: string;
ADDRESSES: VegaContracts;
};
type EnvironmentState = Environment;
const getBundledEnvironmentValue = (key: EnvKey) => {
switch (key) {
// need to have these hardcoded so on build time we can insert sensible defaults
case 'VEGA_URL':
return process.env['NX_VEGA_URL'];
case 'VEGA_ENV':
return process.env['NX_VEGA_ENV'];
case 'ETHEREUM_CHAIN_ID':
return process.env['NX_ETHEREUM_CHAIN_ID'];
case 'ETHEREUM_PROVIDER_URL':
return process.env['NX_ETHEREUM_PROVIDER_URL'];
case 'ETHERSCAN_URL':
return process.env['NX_ETHERSCAN_URL'];
case 'VEGA_NETWORKS':
return process.env['NX_VEGA_NETWORKS'];
}
};
const transformValue = (key: EnvKey, value?: string) => {
switch (key) {
case 'VEGA_ENV':
return value as Networks;
case 'ETHEREUM_CHAIN_ID':
return value && Number(value);
case 'VEGA_NETWORKS': {
if (value) {
try {
return JSON.parse(value);
} catch (e) {
console.warn(
'Error parsing the "NX_VEGA_NETWORKS" environment variable. Make sure it has a valid JSON format.'
);
return undefined;
}
}
return undefined;
}
default:
return value;
}
};
const getValue = (key: EnvKey, definitions: Partial<RawEnvironment> = {}) => {
if (!isBrowser) {
return transformValue(
key,
definitions[key] ?? getBundledEnvironmentValue(key)
);
}
return transformValue(
key,
window._env_?.[key] ?? definitions[key] ?? getBundledEnvironmentValue(key)
);
};
const compileEnvironment = (
definitions?: Partial<RawEnvironment>
): Environment => {
const environment = ENV_KEYS.reduce(
(acc, key) => ({
...acc,
[key]: getValue(key, definitions),
}),
{} as Environment
);
return {
...environment,
ADDRESSES: ContractAddresses[environment['VEGA_ENV']],
VEGA_NETWORKS: {
[environment.VEGA_ENV]: isBrowser
? window.location.href
: environment.VEGA_NETWORKS[environment.VEGA_ENV],
...environment.VEGA_NETWORKS,
},
};
};
const EnvironmentContext = createContext({} as EnvironmentState);
export const EnvironmentProvider = ({
definitions,
children,
}: EnvironmentProviderProps) => {
const [environment] = useState<Environment>(compileEnvironment(definitions));
const missingKeys = Object.keys(environment)
.filter((key) => typeof environment[key as EnvKey] === undefined)
.map((key) => `"${key}"`)
.join(', ');
if (missingKeys.length) {
throw new Error(
`Error setting up the app environment. The following variables are missing from your environment: ${missingKeys}.`
);
}
return (
<EnvironmentContext.Provider value={environment}>
{children}
</EnvironmentContext.Provider>
);
};
export const useEnvironment = () => {
const context = useContext(EnvironmentContext);
if (context === undefined) {
throw new Error(
'Error running "useEnvironment". No context found, make sure your component is wrapped in an <EnvironmentProvider />.'
);
}
return context;
};