-
- {GIT_COMMIT_HASH && (
-
- {t('Version')}:{' '}
-
- {GIT_COMMIT_HASH}
-
-
- )}
-
+ <>
+
+
+
+ >
);
};
diff --git a/apps/liquidity-provision-dashboard/src/app/app.tsx b/apps/liquidity-provision-dashboard/src/app/app.tsx
index 757b88c0f..357d05186 100644
--- a/apps/liquidity-provision-dashboard/src/app/app.tsx
+++ b/apps/liquidity-provision-dashboard/src/app/app.tsx
@@ -1,3 +1,5 @@
+import type { InMemoryCacheConfig } from '@apollo/client';
+import { NetworkLoader, useInitializeEnv } from '@vegaprotocol/environment';
import { useRoutes } from 'react-router-dom';
import '../styles.scss';
@@ -5,14 +7,40 @@ import { Navbar } from './components/navbar';
import { routerConfig } from './routes/router-config';
+const cache: InMemoryCacheConfig = {
+ typePolicies: {
+ Market: {
+ merge: true,
+ },
+ Party: {
+ merge: true,
+ },
+ Query: {},
+ Account: {
+ keyFields: false,
+ fields: {
+ balanceFormatted: {},
+ },
+ },
+ Node: {
+ keyFields: false,
+ },
+ Instrument: {
+ keyFields: false,
+ },
+ },
+};
const AppRouter = () => useRoutes(routerConfig);
export function App() {
+ useInitializeEnv();
return (
-
+
+
+
);
}
diff --git a/apps/liquidity-provision-dashboard/src/main.tsx b/apps/liquidity-provision-dashboard/src/main.tsx
index addcc9921..7615e405e 100644
--- a/apps/liquidity-provision-dashboard/src/main.tsx
+++ b/apps/liquidity-provision-dashboard/src/main.tsx
@@ -1,44 +1,15 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
-import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
import App from './app/app';
-import type { InMemoryCacheConfig } from '@apollo/client';
const rootElement = document.getElementById('root');
const root = rootElement && createRoot(rootElement);
-const cache: InMemoryCacheConfig = {
- typePolicies: {
- Market: {
- merge: true,
- },
- Party: {
- merge: true,
- },
- Query: {},
- Account: {
- keyFields: false,
- fields: {
- balanceFormatted: {},
- },
- },
- Node: {
- keyFields: false,
- },
- Instrument: {
- keyFields: false,
- },
- },
-};
root?.render(
-
-
-
-
-
+
);
diff --git a/apps/multisig-signer/.env b/apps/multisig-signer/.env
index 02483fefb..ddb4546bd 100644
--- a/apps/multisig-signer/.env
+++ b/apps/multisig-signer/.env
@@ -2,3 +2,4 @@ NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
+
diff --git a/apps/multisig-signer/src/app/app.tsx b/apps/multisig-signer/src/app/app.tsx
index f20c6abbe..4707f6f50 100644
--- a/apps/multisig-signer/src/app/app.tsx
+++ b/apps/multisig-signer/src/app/app.tsx
@@ -3,9 +3,9 @@ import classnames from 'classnames';
import { useEffect, useMemo, useState } from 'react';
import { BrowserTracing } from '@sentry/tracing';
import {
- EnvironmentProvider,
NetworkLoader,
useEnvironment,
+ useInitializeEnv,
} from '@vegaprotocol/environment';
import { AsyncRenderer, Button, Lozenge } from '@vegaprotocol/ui-toolkit';
import type { EthereumConfig } from '@vegaprotocol/web3';
@@ -64,6 +64,7 @@ function App() {
environment: VEGA_ENV,
});
}, [VEGA_ENV]);
+
const Connectors = useMemo(() => {
if (config?.chain_id) {
return createConnectors(ETHEREUM_PROVIDER_URL, Number(config.chain_id));
@@ -107,12 +108,11 @@ const Wrapper = () => {
},
},
};
+ useInitializeEnv();
return (
-
-
-
-
-
+
+
+
);
};
diff --git a/apps/token/src/app.tsx b/apps/token/src/app.tsx
index 31321f7de..525b6f6b2 100644
--- a/apps/token/src/app.tsx
+++ b/apps/token/src/app.tsx
@@ -24,8 +24,8 @@ import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { useEthereumConfig } from '@vegaprotocol/web3';
import {
useEnvironment,
- EnvironmentProvider,
NetworkLoader,
+ useInitializeEnv,
} from '@vegaprotocol/environment';
import { createConnectors } from './lib/web3-connectors';
import { ENV } from './config/env';
@@ -166,12 +166,12 @@ const AppContainer = () => {
};
function App() {
+ useInitializeEnv();
+
return (
-
-
-
-
-
+
+
+
);
}
diff --git a/apps/token/src/components/nav/nav.spec.tsx b/apps/token/src/components/nav/nav.spec.tsx
index 54ed7b30c..3d29a4e38 100644
--- a/apps/token/src/components/nav/nav.spec.tsx
+++ b/apps/token/src/components/nav/nav.spec.tsx
@@ -1,23 +1,18 @@
import { render, screen, within } from '@testing-library/react';
-import { EnvironmentProvider, Networks } from '@vegaprotocol/environment';
import { MemoryRouter } from 'react-router-dom';
import { Nav } from './nav';
jest.mock('@vegaprotocol/environment', () => ({
...jest.requireActual('@vegaprotocol/environment'),
NetworkSwitcher: () =>
,
+ useEnvironment: () => ({ VEGA_ENV: 'MAINNET' }),
}));
const renderComponent = (initialEntries?: string[]) => {
return render(
-
-
-
-
-
+
+
+
);
};
diff --git a/apps/trading-e2e/src/integration/markets.cy.ts b/apps/trading-e2e/src/integration/markets.cy.ts
index f21521cc9..c0cfac48f 100644
--- a/apps/trading-e2e/src/integration/markets.cy.ts
+++ b/apps/trading-e2e/src/integration/markets.cy.ts
@@ -145,8 +145,9 @@ describe('markets table', { tags: '@smoke' }, () => {
proposal: { terms: { enactmentDatetime: '2023-01-31 12:00:01' } },
});
});
- cy.visit('/');
cy.visit('#/markets/market-0');
+ cy.url().should('contain', 'market-0');
+ cy.getByTestId('dialog-close').click();
cy.getByTestId('item-value').contains('Opening auction').realHover();
cy.getByTestId('opening-auction-sub-status').should(
'contain.text',
@@ -155,8 +156,7 @@ describe('markets table', { tags: '@smoke' }, () => {
const now = new Date(Date.parse('2023-01-30 12:00:01')).getTime();
cy.clock(now, ['Date']); // Set "now" to BEFORE reservation
- cy.visit('/');
- cy.visit('#/markets/market-0');
+ cy.reload();
cy.getByTestId('item-value').contains('Opening auction').realHover();
cy.getByTestId('opening-auction-sub-status').should(
'contain.text',
diff --git a/apps/trading/components/app-loader/app-failure.tsx b/apps/trading/components/app-loader/app-failure.tsx
new file mode 100644
index 000000000..0057955ed
--- /dev/null
+++ b/apps/trading/components/app-loader/app-failure.tsx
@@ -0,0 +1,30 @@
+import { t } from '@vegaprotocol/react-helpers';
+import { Button } from '@vegaprotocol/ui-toolkit';
+import { useGlobalStore } from '../../stores';
+
+export const AppFailure = ({
+ title,
+ error,
+}: {
+ title: string;
+ error?: string | null;
+}) => {
+ const { setNodeSwitcher } = useGlobalStore((store) => ({
+ nodeSwitcherOpen: store.nodeSwitcherDialog,
+ setNodeSwitcher: (open: boolean) =>
+ store.update({ nodeSwitcherDialog: open }),
+ }));
+ const nonIdealWrapperClasses =
+ 'h-full min-h-screen flex items-center justify-center';
+ return (
+
+
+
{title}
+ {error &&
{error}
}
+
+
+
+ );
+};
diff --git a/apps/trading/components/app-loader/app-loader.tsx b/apps/trading/components/app-loader/app-loader.tsx
new file mode 100644
index 000000000..d8f0495c5
--- /dev/null
+++ b/apps/trading/components/app-loader/app-loader.tsx
@@ -0,0 +1,96 @@
+import type { InMemoryCacheConfig } from '@apollo/client';
+import {
+ NetworkLoader,
+ NodeGuard,
+ useEnvironment,
+} from '@vegaprotocol/environment';
+import { t } from '@vegaprotocol/react-helpers';
+import { MaintenancePage } from '@vegaprotocol/ui-toolkit';
+import { VegaWalletProvider } from '@vegaprotocol/wallet';
+import dynamic from 'next/dynamic';
+import type { ReactNode } from 'react';
+import { AppFailure } from './app-failure';
+import { Web3Provider } from './web3-provider';
+
+const DynamicLoader = dynamic(() => import('../preloader/preloader'), {
+ loading: () => <>Loading...>,
+});
+
+export const AppLoader = ({ children }: { children: ReactNode }) => {
+ const { error, VEGA_URL, MAINTENANCE_PAGE } = useEnvironment((store) => ({
+ error: store.error,
+ VEGA_URL: store.VEGA_URL,
+ MAINTENANCE_PAGE: store.MAINTENANCE_PAGE,
+ }));
+
+ if (MAINTENANCE_PAGE) {
+ return
;
+ }
+
+ return (
+
}
+ failure={
+
+ }
+ >
+
}
+ failure={
}
+ >
+
+ {children}
+
+
+
+ );
+};
+
+const cacheConfig: InMemoryCacheConfig = {
+ typePolicies: {
+ Account: {
+ keyFields: false,
+ fields: {
+ balanceFormatted: {},
+ },
+ },
+ Instrument: {
+ keyFields: false,
+ },
+ TradableInstrument: {
+ keyFields: ['instrument'],
+ },
+ Product: {
+ keyFields: ['settlementAsset', ['id']],
+ },
+ MarketData: {
+ keyFields: ['market', ['id']],
+ },
+ Node: {
+ keyFields: false,
+ },
+ Withdrawal: {
+ fields: {
+ pendingOnForeignChain: {
+ read: (isPending = false) => isPending,
+ },
+ },
+ },
+ ERC20: {
+ keyFields: ['contractAddress'],
+ },
+ PositionUpdate: {
+ keyFields: false,
+ },
+ AccountUpdate: {
+ keyFields: false,
+ },
+ Party: {
+ keyFields: false,
+ },
+ Fees: {
+ keyFields: false,
+ },
+ },
+};
diff --git a/apps/trading/components/app-loader/index.tsx b/apps/trading/components/app-loader/index.tsx
index 9a1565fd9..624edba38 100644
--- a/apps/trading/components/app-loader/index.tsx
+++ b/apps/trading/components/app-loader/index.tsx
@@ -1,121 +1,3 @@
-import type { ReactNode } from 'react';
-import { useEffect } from 'react';
-import { NetworkLoader, useEnvironment } from '@vegaprotocol/environment';
-import type { InMemoryCacheConfig } from '@apollo/client';
-import {
- useEthereumConfig,
- createConnectors,
- Web3Provider as Web3ProviderInternal,
- useWeb3ConnectStore,
-} from '@vegaprotocol/web3';
-import { AsyncRenderer, Loader } from '@vegaprotocol/ui-toolkit';
-
-interface AppLoaderProps {
- children: ReactNode;
-}
-
-/**
- * Component to handle any app initialization, startup queries and other things
- * that must happen for it can be used
- */
-export function AppLoader({ children }: AppLoaderProps) {
- return (
-
} cache={cacheConfig}>
- {children}
-
- );
-}
-
-export const Web3Provider = ({ children }: { children: ReactNode }) => {
- const { config, loading, error } = useEthereumConfig();
- const { ETHEREUM_PROVIDER_URL, ETH_LOCAL_PROVIDER_URL, ETH_WALLET_MNEMONIC } =
- useEnvironment();
- const [connectors, initializeConnectors] = useWeb3ConnectStore((store) => [
- store.connectors,
- store.initialize,
- ]);
-
- useEffect(() => {
- if (config?.chain_id) {
- return initializeConnectors(
- createConnectors(
- ETHEREUM_PROVIDER_URL,
- Number(config?.chain_id),
- ETH_LOCAL_PROVIDER_URL,
- ETH_WALLET_MNEMONIC
- ),
- Number(config.chain_id)
- );
- }
- }, [
- config?.chain_id,
- ETHEREUM_PROVIDER_URL,
- initializeConnectors,
- ETH_LOCAL_PROVIDER_URL,
- ETH_WALLET_MNEMONIC,
- ]);
-
- return (
-
{
- if (!d) return true;
- return d.length < 1;
- }}
- >
-
- <>{children}>
-
-
- );
-};
-
-const cacheConfig: InMemoryCacheConfig = {
- typePolicies: {
- Account: {
- keyFields: false,
- fields: {
- balanceFormatted: {},
- },
- },
- Instrument: {
- keyFields: false,
- },
- TradableInstrument: {
- keyFields: ['instrument'],
- },
- Product: {
- keyFields: ['settlementAsset', ['id']],
- },
- MarketData: {
- keyFields: ['market', ['id']],
- },
- Node: {
- keyFields: false,
- },
- Withdrawal: {
- fields: {
- pendingOnForeignChain: {
- read: (isPending = false) => isPending,
- },
- },
- },
- ERC20: {
- keyFields: ['contractAddress'],
- },
- PositionUpdate: {
- keyFields: false,
- },
- AccountUpdate: {
- keyFields: false,
- },
- Party: {
- keyFields: false,
- },
- Fees: {
- keyFields: false,
- },
- },
-};
+export * from './app-failure';
+export * from './app-loader';
+export * from './web3-provider';
diff --git a/apps/trading/components/app-loader/web3-provider.tsx b/apps/trading/components/app-loader/web3-provider.tsx
new file mode 100644
index 000000000..290d9309c
--- /dev/null
+++ b/apps/trading/components/app-loader/web3-provider.tsx
@@ -0,0 +1,58 @@
+import {
+ useEthereumConfig,
+ createConnectors,
+ Web3Provider as Web3ProviderInternal,
+ useWeb3ConnectStore,
+} from '@vegaprotocol/web3';
+import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
+import { t } from '@vegaprotocol/react-helpers';
+import { useEnvironment } from '@vegaprotocol/environment';
+import type { ReactNode } from 'react';
+import { useEffect } from 'react';
+
+export const Web3Provider = ({ children }: { children: ReactNode }) => {
+ const { config, loading, error } = useEthereumConfig();
+ const { ETHEREUM_PROVIDER_URL, ETH_LOCAL_PROVIDER_URL, ETH_WALLET_MNEMONIC } =
+ useEnvironment();
+ const [connectors, initializeConnectors] = useWeb3ConnectStore((store) => [
+ store.connectors,
+ store.initialize,
+ ]);
+
+ useEffect(() => {
+ if (config?.chain_id) {
+ return initializeConnectors(
+ createConnectors(
+ ETHEREUM_PROVIDER_URL,
+ Number(config?.chain_id),
+ ETH_LOCAL_PROVIDER_URL,
+ ETH_WALLET_MNEMONIC
+ ),
+ Number(config.chain_id)
+ );
+ }
+ }, [
+ config?.chain_id,
+ ETHEREUM_PROVIDER_URL,
+ initializeConnectors,
+ ETH_LOCAL_PROVIDER_URL,
+ ETH_WALLET_MNEMONIC,
+ ]);
+
+ return (
+
{
+ if (!d) return true;
+ return d.length < 1;
+ }}
+ noDataMessage={t('Could not fetch Ethereum configuration')}
+ >
+
+ <>{children}>
+
+
+ );
+};
diff --git a/apps/trading/components/footer/footer.spec.tsx b/apps/trading/components/footer/footer.spec.tsx
index 687a3fbe6..b44e54c48 100644
--- a/apps/trading/components/footer/footer.spec.tsx
+++ b/apps/trading/components/footer/footer.spec.tsx
@@ -1,57 +1,38 @@
import { fireEvent, render, screen } from '@testing-library/react';
-import { Footer, NodeHealth } from './footer';
-import { useEnvironment } from '@vegaprotocol/environment';
+import { NodeUrl, NodeHealth } from './footer';
-jest.mock('@vegaprotocol/environment');
-
-describe('Footer', () => {
+describe('NodeUrl', () => {
it('can open node switcher by clicking the node url', () => {
const mockOpenNodeSwitcher = jest.fn();
- const node = 'n99.somenetwork.vega.xyz';
+ const node = 'https://api.n99.somenetwork.vega.xyz';
- // @ts-ignore mock env hook
- useEnvironment.mockImplementation(() => ({
- VEGA_URL: `https://api.${node}/graphql`,
- blockDifference: 0,
- setNodeSwitcherOpen: mockOpenNodeSwitcher,
- }));
+ render(
);
- render(
);
-
- fireEvent.click(screen.getByText(node));
- expect(mockOpenNodeSwitcher).toHaveBeenCalled();
- });
-
- it('can open node switcher by clicking health', () => {
- const mockOpenNodeSwitcher = jest.fn();
- const node = 'n99.somenetwork.vega.xyz';
-
- // @ts-ignore mock env hook
- useEnvironment.mockImplementation(() => ({
- VEGA_URL: `https://api.${node}/graphql`,
- blockDifference: 0,
- setNodeSwitcherOpen: mockOpenNodeSwitcher,
- }));
-
- render(
);
-
- fireEvent.click(screen.getByText('Operational'));
+ fireEvent.click(screen.getByText(/n99/));
expect(mockOpenNodeSwitcher).toHaveBeenCalled();
});
});
describe('NodeHealth', () => {
+ const mockOpenNodeSwitcher = jest.fn();
const cases = [
{ diff: 0, classname: 'bg-vega-green-550', text: 'Operational' },
{ diff: 5, classname: 'bg-warning', text: '5 Blocks behind' },
- { diff: -1, classname: 'bg-danger', text: 'Non operational' },
+ { diff: null, classname: 'bg-danger', text: 'Non operational' },
];
it.each(cases)(
'renders correct text and indicator color for $diff block difference',
(elem) => {
- render(
);
+ render(
+
+ );
expect(screen.getByTestId('indicator')).toHaveClass(elem.classname);
expect(screen.getByText(elem.text)).toBeInTheDocument();
+ fireEvent.click(screen.getByText(elem.text));
+ expect(mockOpenNodeSwitcher).toHaveBeenCalled();
}
);
});
diff --git a/apps/trading/components/footer/footer.tsx b/apps/trading/components/footer/footer.tsx
index 069a4c171..ff675cad7 100644
--- a/apps/trading/components/footer/footer.tsx
+++ b/apps/trading/components/footer/footer.tsx
@@ -1,9 +1,15 @@
-import { useEnvironment } from '@vegaprotocol/environment';
+import { useEnvironment, useNodeHealth } from '@vegaprotocol/environment';
import { t, useNavigatorOnline } from '@vegaprotocol/react-helpers';
import { ButtonLink, Indicator, Intent } from '@vegaprotocol/ui-toolkit';
+import { useGlobalStore } from '../../stores';
export const Footer = () => {
- const { VEGA_URL, blockDifference, setNodeSwitcherOpen } = useEnvironment();
+ const { VEGA_URL } = useEnvironment();
+ const setNodeSwitcher = useGlobalStore(
+ (store) => (open: boolean) => store.update({ nodeSwitcherDialog: open })
+ );
+ const { blockDiff } = useNodeHealth();
+
return (
);
}
-const DynamicLoader = dynamic(
- () => import('../components/preloader/preloader'),
- {
- loading: () => <>Loading...>,
- }
-);
-
function VegaTradingApp(props: AppProps) {
- const [mounted, setMounted] = useState(false);
+ const status = useEnvironment((store) => store.status);
+ const { nodeSwitcherOpen, setNodeSwitcher } = useGlobalStore((store) => ({
+ nodeSwitcherOpen: store.nodeSwitcherDialog,
+ setNodeSwitcher: (open: boolean) =>
+ store.update({ nodeSwitcherDialog: open }),
+ }));
- // Hash router requires access to the document object. At compile time that doesn't exist
- // so we need to ensure client side rendering only from this point onwards in
- // the component tree
- useEffect(() => {
- setMounted(true);
- }, []);
+ useInitializeEnv();
- if (!mounted) {
- return