Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
297ebb0180 | ||
|
|
8fab8dad6c | ||
|
|
76bf45b461 | ||
|
|
f128f41ea0 | ||
|
|
fcb992b64e | ||
|
|
1251c8b89b |
@@ -1,7 +1,7 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_ENV=VALIDATOR_TESTNET
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
|
||||
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/query
|
||||
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/graphql
|
||||
NX_VEGA_REST=https://api.validators-testnet.vega.xyz/
|
||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
|
||||
@@ -22,29 +22,3 @@ query ExplorerFutureEpoch {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# query ExplorerEpoch($id: ID!) {
|
||||
#
|
||||
##### This could be useful for calculating roughly when a future epoch will
|
||||
##### occur, but epoch not exist results in a total error
|
||||
# networkParameter(key: "validators.epoch.length") {
|
||||
# value
|
||||
# }
|
||||
#
|
||||
##### This could be useful for relating where we are in time, but as above
|
||||
##### the total failure caused by epoch(id) not existing
|
||||
##### means this is useful
|
||||
# currentEpoch: epoch {
|
||||
# id
|
||||
# }
|
||||
#
|
||||
# epoch(id: $id) {
|
||||
# id
|
||||
# timestamps {
|
||||
# start
|
||||
# end
|
||||
# firstBlock
|
||||
# lastBlock
|
||||
# }
|
||||
# }
|
||||
#}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"noPropertyAccessFromIndexSignature": false,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"lib": ["es5", "es6", "dom", "dom.iterable"]
|
||||
"lib": ["es2021", "dom", "dom.iterable"]
|
||||
},
|
||||
"exclude": ["./src/types/explorer.d.ts"],
|
||||
"include": [],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_ENV=VALIDATOR_TESTNET
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
|
||||
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/query
|
||||
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/graphql
|
||||
NX_VEGA_REST=https://api.validators-testnet.vega.xyz/
|
||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": false,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"lib": ["es5", "es6", "dom", "dom.iterable"]
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": [],
|
||||
"references": [
|
||||
|
||||
@@ -2761,7 +2761,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "86666.297",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "66304.3808499140392169605",
|
||||
"locked_amount": "66243.522619730595190252",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "86666.297",
|
||||
@@ -2827,7 +2827,7 @@
|
||||
"tranche_end": "2023-06-01T00:00:00.000Z",
|
||||
"total_added": "2500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1267.09671983109475",
|
||||
"locked_amount": "1263.57600732600725",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
@@ -2948,7 +2948,7 @@
|
||||
"tranche_end": "2023-09-01T00:00:00.000Z",
|
||||
"total_added": "17500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "17500",
|
||||
"locked_amount": "17498.8903985507255",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "12500",
|
||||
@@ -3215,7 +3215,7 @@
|
||||
"tranche_end": "2023-08-01T00:00:00.000Z",
|
||||
"total_added": "37500",
|
||||
"total_removed": "3376.096819125",
|
||||
"locked_amount": "31749.58035988336125",
|
||||
"locked_amount": "31696.477900552485",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -3370,7 +3370,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "66243.886445125581005415",
|
||||
"locked_amount": "66183.0837404197105596",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -3436,7 +3436,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "62600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "31942.23161466261138",
|
||||
"locked_amount": "31898.27305936073208",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10000",
|
||||
@@ -3629,7 +3629,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "2743.0772767630645",
|
||||
"locked_amount": "2739.566210045662",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -3840,7 +3840,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "97499.58",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "8201.2833284291343546228",
|
||||
"locked_amount": "8141.6415391408092444606",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "97499.58",
|
||||
@@ -3873,7 +3873,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "135173.4239508",
|
||||
"total_removed": "98230.390980249184455396",
|
||||
"locked_amount": "11209.738417463709158183541612",
|
||||
"locked_amount": "11128.218388231931879326063704",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "135173.4239508",
|
||||
@@ -3919,7 +3919,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "32499.86",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "3450.1382676825368276502",
|
||||
"locked_amount": "3425.0479968875506615442",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "32499.86",
|
||||
@@ -3952,7 +3952,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "10833.29",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1122.9865267813859264897",
|
||||
"locked_amount": "1114.8198871078435790832",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10833.29",
|
||||
@@ -3985,7 +3985,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "22749.93",
|
||||
"total_removed": "4720.860935375",
|
||||
"locked_amount": "4197.9744516197632635414",
|
||||
"locked_amount": "4167.4457285340302852478",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "6500",
|
||||
@@ -4137,7 +4137,7 @@
|
||||
"tranche_end": "2023-05-01T00:00:00.000Z",
|
||||
"total_added": "22500",
|
||||
"total_removed": "4913.13257745",
|
||||
"locked_amount": "7613.284127532228",
|
||||
"locked_amount": "7581.4226519337009",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -4412,7 +4412,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "928642.9598472029154",
|
||||
"locked_amount": "495583.358230088177384699",
|
||||
"locked_amount": "494221.11463625557046169",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -36792,7 +36792,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "615950.831401702010493",
|
||||
"locked_amount": "786040.402529665382116142762",
|
||||
"locked_amount": "783947.108408790236382843098",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -38140,8 +38140,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "582201.49676312452960452",
|
||||
"locked_amount": "8086936.3843934726821727115196371031454447",
|
||||
"total_removed": "584996.67274505202169452",
|
||||
"locked_amount": "8079513.697843178693280892781044398053528",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -38670,6 +38670,16 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x1438fbbc780cb382033855d295fa2511deed15cd64506a62ae4e3cfe82b3678e"
|
||||
},
|
||||
{
|
||||
"amount": "2345.954988",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tx": "0x1887d1fb77d9fa555dd5b55da307edc91e395f3a7e0ca5f874740f5a10077cdf"
|
||||
},
|
||||
{
|
||||
"amount": "449.22099392749209",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tx": "0x3c76f03b71481a44c6ba2c7cea407f5f1bac60bcaa9242af18de287f94c8ed90"
|
||||
},
|
||||
{
|
||||
"amount": "535.4042378778335",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -41899,6 +41909,12 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0x525f9427c131bc2fdea7f556d16b7781faaa41e09c7735d1c02d1f7585cc49ab"
|
||||
},
|
||||
{
|
||||
"amount": "449.22099392749209",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x3c76f03b71481a44c6ba2c7cea407f5f1bac60bcaa9242af18de287f94c8ed90"
|
||||
},
|
||||
{
|
||||
"amount": "1640.93679110232897",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
@@ -42141,8 +42157,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "150551.801",
|
||||
"withdrawn_tokens": "73436.73551735372338",
|
||||
"remaining_tokens": "77115.06548264627662"
|
||||
"withdrawn_tokens": "73885.95651128121547",
|
||||
"remaining_tokens": "76665.84448871878453"
|
||||
},
|
||||
{
|
||||
"address": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148",
|
||||
@@ -42344,6 +42360,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "2345.954988",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x1887d1fb77d9fa555dd5b55da307edc91e395f3a7e0ca5f874740f5a10077cdf"
|
||||
},
|
||||
{
|
||||
"amount": "2820.55961",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
@@ -42556,8 +42578,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200000",
|
||||
"withdrawn_tokens": "95806.869254",
|
||||
"remaining_tokens": "104193.130746"
|
||||
"withdrawn_tokens": "98152.824242",
|
||||
"remaining_tokens": "101847.175758"
|
||||
},
|
||||
{
|
||||
"address": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01",
|
||||
@@ -43916,7 +43938,7 @@
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "5577113.077460725181649906",
|
||||
"locked_amount": "1744362.808205403023648882076279678",
|
||||
"locked_amount": "1737510.231376472448763806568635843",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@@ -50985,7 +51007,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "3077573.36197477479025324",
|
||||
"locked_amount": "372304.891800204182140687038857991",
|
||||
"locked_amount": "369597.397251054113600109778074383",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "552496.6455",
|
||||
@@ -53057,7 +53079,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "34992.4553336210685",
|
||||
"locked_amount": "124552.59497932319889005659868088",
|
||||
"locked_amount": "124220.90056009124187109393607304",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import type { ClientOptions } from '@vegaprotocol/apollo-client';
|
||||
import { createClient } from '@vegaprotocol/apollo-client';
|
||||
import { Networks } from '../types';
|
||||
import { useEnvironment } from './use-environment';
|
||||
import { STORAGE_KEY, useEnvironment } from './use-environment';
|
||||
|
||||
const noop = () => {
|
||||
/* no op*/
|
||||
};
|
||||
|
||||
jest.mock('@vegaprotocol/apollo-client', () => ({
|
||||
createClient: () => ({
|
||||
jest.mock('@vegaprotocol/apollo-client');
|
||||
jest.mock('zustand');
|
||||
|
||||
const mockCreateClient = createClient as jest.Mock;
|
||||
const createDefaultMockClient = () => {
|
||||
return () => ({
|
||||
query: () =>
|
||||
Promise.resolve({
|
||||
data: {
|
||||
@@ -25,12 +31,10 @@ jest.mock('@vegaprotocol/apollo-client', () => ({
|
||||
obj.next();
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
jest.mock('zustand');
|
||||
});
|
||||
};
|
||||
|
||||
global.fetch = jest.fn();
|
||||
|
||||
// eslint-disable-next-line
|
||||
const setupFetch = (result: any) => {
|
||||
return () => {
|
||||
@@ -56,6 +60,17 @@ const mockEnvVars = {
|
||||
|
||||
describe('useEnvironment', () => {
|
||||
const env = process.env;
|
||||
// eslint-disable-next-line
|
||||
let warn: any;
|
||||
|
||||
beforeAll(() => {
|
||||
warn = console.warn;
|
||||
console.warn = noop;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
console.warn = warn;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
@@ -73,6 +88,9 @@ describe('useEnvironment', () => {
|
||||
|
||||
// @ts-ignore clear mocked node config fetch
|
||||
fetch.mockClear();
|
||||
|
||||
// reset default apollo client behaviour
|
||||
mockCreateClient.mockImplementation(createDefaultMockClient());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -92,6 +110,7 @@ describe('useEnvironment', () => {
|
||||
];
|
||||
// @ts-ignore: typscript doesn't recognise the mock implementation
|
||||
global.fetch.mockImplementation(setupFetch({ hosts: nodes }));
|
||||
|
||||
const { result } = setup();
|
||||
|
||||
expect(result.current.status).toBe('default');
|
||||
@@ -107,10 +126,169 @@ describe('useEnvironment', () => {
|
||||
});
|
||||
|
||||
// resulting VEGA_URL should be one of the nodes from the config
|
||||
expect(
|
||||
result.current.VEGA_URL === nodes[0] ||
|
||||
result.current.VEGA_URL === nodes[1]
|
||||
).toBe(true);
|
||||
expect(nodes.includes(result.current.VEGA_URL as string)).toBe(true);
|
||||
expect(result.current).toMatchObject({
|
||||
...mockEnvVars,
|
||||
nodes,
|
||||
});
|
||||
expect(fetch).toHaveBeenCalledTimes(1);
|
||||
expect(fetch).toHaveBeenCalledWith(configUrl);
|
||||
});
|
||||
|
||||
it('uses the first successfully responding node', async () => {
|
||||
jest.useFakeTimers();
|
||||
const configUrl = 'https://vega.xyz/testnet-config.json';
|
||||
process.env['NX_VEGA_CONFIG_URL'] = configUrl;
|
||||
|
||||
const slowNode = 'https://api.n00.foo.vega.xyz';
|
||||
const slowWait = 2000;
|
||||
const fastNode = 'https://api.n01.foo.vega.xyz';
|
||||
const fastWait = 1000;
|
||||
const nodes = [slowNode, fastNode];
|
||||
// @ts-ignore: typscript doesn't recognise the mock implementation
|
||||
global.fetch.mockImplementation(setupFetch({ hosts: nodes }));
|
||||
|
||||
mockCreateClient.mockImplementation((obj: ClientOptions) => ({
|
||||
query: () =>
|
||||
new Promise((resolve) => {
|
||||
const wait = obj.url === fastNode ? fastWait : slowWait;
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
data: {
|
||||
statistics: {
|
||||
chainId: 'chain-id',
|
||||
blockHeight: '100',
|
||||
vegaTime: new Date().toISOString(),
|
||||
},
|
||||
},
|
||||
});
|
||||
}, wait);
|
||||
}),
|
||||
subscribe: () => ({
|
||||
// eslint-disable-next-line
|
||||
subscribe: (obj: any) => {
|
||||
obj.next();
|
||||
},
|
||||
}),
|
||||
}));
|
||||
const { result } = setup();
|
||||
|
||||
expect(result.current.status).toBe('default');
|
||||
|
||||
act(() => {
|
||||
result.current.initialize();
|
||||
});
|
||||
|
||||
expect(result.current.status).toBe('pending');
|
||||
|
||||
// wait for nodes request to finish before running timer
|
||||
await waitFor(() => {
|
||||
expect(result.current.nodes).toEqual(nodes);
|
||||
});
|
||||
|
||||
jest.runAllTimers();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.status).toEqual('success');
|
||||
});
|
||||
|
||||
expect(result.current.VEGA_URL).toBe(fastNode);
|
||||
expect(localStorage.getItem(STORAGE_KEY)).toBe(fastNode);
|
||||
expect(result.current).toMatchObject({
|
||||
...mockEnvVars,
|
||||
nodes,
|
||||
});
|
||||
expect(fetch).toHaveBeenCalledTimes(1);
|
||||
expect(fetch).toHaveBeenCalledWith(configUrl);
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('passes a node if both queries and subscriptions working', async () => {
|
||||
const configUrl = 'https://vega.xyz/testnet-config.json';
|
||||
process.env['NX_VEGA_CONFIG_URL'] = configUrl;
|
||||
const successNode = 'https://api.n01.foo.vega.xyz';
|
||||
const failNode = 'https://api.n00.foo.vega.xyz';
|
||||
const nodes = [failNode, successNode];
|
||||
// @ts-ignore: typscript doesn't recognise the mock implementation
|
||||
global.fetch.mockImplementation(setupFetch({ hosts: nodes }));
|
||||
mockCreateClient.mockImplementation((clientOptions: ClientOptions) => ({
|
||||
query: () =>
|
||||
Promise.resolve({
|
||||
data: {
|
||||
statistics: {
|
||||
chainId: 'chain-id',
|
||||
blockHeight: '100',
|
||||
vegaTime: new Date().toISOString(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
subscribe: () => ({
|
||||
// eslint-disable-next-line
|
||||
subscribe: (obj: any) => {
|
||||
if (clientOptions.url === failNode) {
|
||||
// make n00 fail the subscription
|
||||
obj.error();
|
||||
} else {
|
||||
obj.next();
|
||||
}
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
const { result } = setup();
|
||||
|
||||
expect(result.current.status).toBe('default');
|
||||
|
||||
act(() => {
|
||||
result.current.initialize();
|
||||
});
|
||||
|
||||
expect(result.current.status).toBe('pending');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.status).toBe('success');
|
||||
});
|
||||
|
||||
expect(result.current.VEGA_URL).toBe(successNode);
|
||||
expect(localStorage.getItem(STORAGE_KEY)).toBe(successNode);
|
||||
});
|
||||
|
||||
it('fails initialization if no suitable node is found', async () => {
|
||||
const configUrl = 'https://vega.xyz/testnet-config.json';
|
||||
process.env['NX_VEGA_CONFIG_URL'] = configUrl;
|
||||
const nodes = [
|
||||
'https://api.n00.foo.vega.xyz',
|
||||
'https://api.n01.foo.vega.xyz',
|
||||
];
|
||||
// @ts-ignore: typscript doesn't recognise the mock implementation
|
||||
global.fetch.mockImplementation(setupFetch({ hosts: nodes }));
|
||||
|
||||
// set all clients to fail both query and subscription
|
||||
mockCreateClient.mockImplementation(() => ({
|
||||
query: () => Promise.reject(),
|
||||
subscribe: () => ({
|
||||
// eslint-disable-next-line
|
||||
subscribe: (obj: any) => {
|
||||
obj.error();
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
const { result } = setup();
|
||||
|
||||
expect(result.current.status).toBe('default');
|
||||
|
||||
act(() => {
|
||||
result.current.initialize();
|
||||
});
|
||||
|
||||
expect(result.current.status).toBe('pending');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.status).toBe('failed');
|
||||
});
|
||||
|
||||
expect(result.current.VEGA_URL).toBe(undefined); // VEGA_URL is unset, app should handle some UI
|
||||
expect(result.current).toMatchObject({
|
||||
...mockEnvVars,
|
||||
nodes,
|
||||
@@ -154,9 +332,12 @@ describe('useEnvironment', () => {
|
||||
process.env['NX_VEGA_URL'] = url;
|
||||
process.env['NX_VEGA_CONFIG_URL'] = undefined;
|
||||
const { result } = setup();
|
||||
await act(async () => {
|
||||
act(() => {
|
||||
result.current.initialize();
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(result.current.status).toBe('success');
|
||||
});
|
||||
expect(result.current).toMatchObject({
|
||||
VEGA_URL: url,
|
||||
VEGA_CONFIG_URL: undefined,
|
||||
@@ -174,16 +355,16 @@ describe('useEnvironment', () => {
|
||||
// @ts-ignore setup mock fetch for config url
|
||||
global.fetch.mockImplementation(setupFetch({ hosts: nodes }));
|
||||
const { result } = setup();
|
||||
await act(async () => {
|
||||
act(() => {
|
||||
result.current.initialize();
|
||||
});
|
||||
expect(typeof result.current.VEGA_URL).toEqual('string');
|
||||
expect(result.current.VEGA_URL).not.toBeFalsy();
|
||||
await waitFor(() => {
|
||||
expect(result.current.status).toBe('success');
|
||||
});
|
||||
expect(nodes.includes(result.current.VEGA_URL as string)).toBe(true);
|
||||
});
|
||||
|
||||
it('handles error if node config cannot be fetched', async () => {
|
||||
const warn = console.warn;
|
||||
console.warn = noop;
|
||||
const configUrl = 'https://vega.xyz/testnet-config.json';
|
||||
process.env['NX_VEGA_CONFIG_URL'] = configUrl;
|
||||
process.env['NX_VEGA_URL'] = undefined;
|
||||
@@ -196,16 +377,14 @@ describe('useEnvironment', () => {
|
||||
result.current.initialize();
|
||||
});
|
||||
expect(result.current.status).toEqual('failed');
|
||||
expect(typeof result.current.error).toBe('string');
|
||||
expect(result.current.error).toBeTruthy();
|
||||
expect(result.current.error).toBe(
|
||||
`Failed to fetch node config from ${configUrl}`
|
||||
);
|
||||
expect(fetch).toHaveBeenCalledTimes(1);
|
||||
expect(fetch).toHaveBeenCalledWith(configUrl);
|
||||
console.warn = warn;
|
||||
});
|
||||
|
||||
it('handles an invalid node config', async () => {
|
||||
const warn = console.warn;
|
||||
console.warn = noop;
|
||||
const configUrl = 'https://vega.xyz/testnet-config.json';
|
||||
process.env['NX_VEGA_CONFIG_URL'] = configUrl;
|
||||
process.env['NX_VEGA_URL'] = undefined;
|
||||
@@ -216,11 +395,11 @@ describe('useEnvironment', () => {
|
||||
result.current.initialize();
|
||||
});
|
||||
expect(result.current.status).toEqual('failed');
|
||||
expect(typeof result.current.error).toBe('string');
|
||||
expect(result.current.error).toBeTruthy();
|
||||
expect(result.current.error).toBe(
|
||||
`Failed to fetch node config from ${configUrl}`
|
||||
);
|
||||
expect(fetch).toHaveBeenCalledTimes(1);
|
||||
expect(fetch).toHaveBeenCalledWith(configUrl);
|
||||
console.warn = warn;
|
||||
});
|
||||
|
||||
it('uses stored url', async () => {
|
||||
@@ -231,7 +410,7 @@ describe('useEnvironment', () => {
|
||||
setupFetch({ hosts: ['http://foo.bar.com'] })
|
||||
);
|
||||
const url = 'https://api.n00.foo.com';
|
||||
localStorage.setItem('vega_url', url);
|
||||
localStorage.setItem(STORAGE_KEY, url);
|
||||
const { result } = setup();
|
||||
await act(async () => {
|
||||
result.current.initialize();
|
||||
@@ -254,6 +433,6 @@ describe('useEnvironment', () => {
|
||||
result.current.setUrl(newUrl);
|
||||
});
|
||||
expect(result.current.VEGA_URL).toBe(newUrl);
|
||||
expect(localStorage.getItem('vega_url')).toBe(newUrl);
|
||||
expect(localStorage.getItem(STORAGE_KEY)).toBe(newUrl);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ type Actions = {
|
||||
export type Env = Environment & EnvState;
|
||||
export type EnvStore = Env & Actions;
|
||||
|
||||
const STORAGE_KEY = 'vega_url';
|
||||
export const STORAGE_KEY = 'vega_url';
|
||||
const SUBSCRIPTION_TIMEOUT = 3000;
|
||||
|
||||
export const useEnvironment = create<EnvStore>((set, get) => ({
|
||||
@@ -168,9 +168,15 @@ const fetchConfig = async (url?: string) => {
|
||||
* Find a suitable node by running a test query and test
|
||||
* subscription, against a list of clients, first to resolve wins
|
||||
*/
|
||||
const findNode = (clients: ClientCollection): Promise<string | null> => {
|
||||
const findNode = async (clients: ClientCollection): Promise<string | null> => {
|
||||
const tests = Object.entries(clients).map((args) => testNode(...args));
|
||||
return Promise.race(tests);
|
||||
try {
|
||||
const url = await Promise.any(tests);
|
||||
return url;
|
||||
} catch {
|
||||
// All tests rejected, no suitable node found
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -180,19 +186,21 @@ const testNode = async (
|
||||
url: string,
|
||||
client: Client
|
||||
): Promise<string | null> => {
|
||||
try {
|
||||
const results = await Promise.all([
|
||||
testQuery(client),
|
||||
testSubscription(client),
|
||||
]);
|
||||
if (results[0] && results[1]) {
|
||||
return url;
|
||||
}
|
||||
return null;
|
||||
} catch (err) {
|
||||
console.warn(`Tests failed for ${url}`);
|
||||
return null;
|
||||
const results = await Promise.all([
|
||||
// these promises will only resolve with true/false
|
||||
testQuery(client),
|
||||
testSubscription(client),
|
||||
]);
|
||||
if (results[0] && results[1]) {
|
||||
return url;
|
||||
}
|
||||
|
||||
const message = `Tests failed for node: ${url}`;
|
||||
console.warn(message);
|
||||
|
||||
// throwing here will mean this tests is ignored and a different
|
||||
// node that hopefully does resolve will fulfill the Promise.any
|
||||
throw new Error(message);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,9 +21,11 @@ import type { NetworkParamsQuery } from '@vegaprotocol/react-helpers';
|
||||
|
||||
const mockWeb3Provider = jest.fn();
|
||||
|
||||
let mockChainId = 111111;
|
||||
jest.mock('@web3-react/core', () => ({
|
||||
useWeb3React: () => ({
|
||||
provider: mockWeb3Provider(),
|
||||
chainId: mockChainId,
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -63,15 +65,16 @@ jest.mock('./use-get-withdraw-delay', () => ({
|
||||
useGetWithdrawDelay: () => mockUseGetWithdrawDelay(),
|
||||
}));
|
||||
|
||||
const mockUseEthereumConfig = jest.fn(() => ({
|
||||
const mockUseEthereumConfig = {
|
||||
collateral_bridge_contract: {
|
||||
address: 'address',
|
||||
},
|
||||
}));
|
||||
chain_id: '111111',
|
||||
};
|
||||
|
||||
jest.mock('./use-ethereum-config', () => ({
|
||||
useEthereumConfig: () => ({
|
||||
config: mockUseEthereumConfig(),
|
||||
config: mockUseEthereumConfig,
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -301,4 +304,19 @@ describe('useEthWithdrawApprovalsManager', () => {
|
||||
erc20WithdrawalApproval.signatures,
|
||||
]);
|
||||
});
|
||||
|
||||
it('detect wrong chainId', () => {
|
||||
mockChainId = 1;
|
||||
const transaction = createWithdrawTransaction();
|
||||
mockEthTransactionStoreState.mockReturnValue({ create });
|
||||
mockEthWithdrawApprovalsStoreState.mockReturnValue({
|
||||
transactions: [transaction],
|
||||
update,
|
||||
});
|
||||
render();
|
||||
expect(update.mock.calls[0][1].status).toEqual(ApprovalStatus.Error);
|
||||
expect(update.mock.calls[0][1].message).toEqual(
|
||||
'You are on the wrong network'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ export const useEthWithdrawApprovalsManager = () => {
|
||||
const getThreshold = useGetWithdrawThreshold();
|
||||
const getDelay = useGetWithdrawDelay();
|
||||
const { query } = useApolloClient();
|
||||
const { provider } = useWeb3React();
|
||||
const { provider, chainId } = useWeb3React();
|
||||
const { config } = useEthereumConfig();
|
||||
const createEthTransaction = useEthTransactionStore((state) => state.create);
|
||||
const update = useEthWithdrawApprovalsStore((state) => state.update);
|
||||
@@ -57,6 +57,13 @@ export const useEthWithdrawApprovalsManager = () => {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (chainId?.toString() !== config?.chain_id) {
|
||||
update(transaction.id, {
|
||||
status: ApprovalStatus.Error,
|
||||
message: t(`You are on the wrong network`),
|
||||
});
|
||||
return;
|
||||
}
|
||||
update(transaction.id, {
|
||||
status: ApprovalStatus.Pending,
|
||||
message: t('Verifying withdrawal approval'),
|
||||
@@ -131,5 +138,6 @@ export const useEthWithdrawApprovalsManager = () => {
|
||||
query,
|
||||
transaction,
|
||||
update,
|
||||
chainId,
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -216,7 +216,7 @@ export const getVerifyDialogProps = (status: ApprovalStatus) => {
|
||||
|
||||
export const VerificationStatus = ({ state }: { state: VerifyState }) => {
|
||||
if (state.status === ApprovalStatus.Error) {
|
||||
return <p>{t('Something went wrong')}</p>;
|
||||
return <p>{state.message || t('Something went wrong')}</p>;
|
||||
}
|
||||
|
||||
if (state.status === ApprovalStatus.Pending) {
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"module": "esnext",
|
||||
"lib": ["es2017", "dom"],
|
||||
"lib": ["es2021", "dom"],
|
||||
"skipLibCheck": true,
|
||||
"skipDefaultLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
Reference in New Issue
Block a user