Merge branch 'master' of github.com:vegaprotocol/frontend-monorepo

This commit is contained in:
madalinaraicu 2022-06-21 13:49:26 +02:00
commit 4df9633c98
182 changed files with 4353 additions and 1480 deletions

5
.dockerignore Normal file
View File

@ -0,0 +1,5 @@
dist/*
node_modules/*
tmp/*
.dockerignore
Dockerfile

View File

@ -2,7 +2,7 @@ name: Generate tranches
on:
schedule:
- cron: '0 8 * * *'
- cron: '0 */6 * * *'
jobs:
master:

29
Dockerfile Normal file
View File

@ -0,0 +1,29 @@
# Build container
FROM node:16.14.0-alpine as build
WORKDIR /app
# Argument to allow building of different apps
ARG APP
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY yarn.lock ./
COPY . ./
RUN yarn
RUN yarn nx build $APP
# Production environment
FROM nginx:stable-alpine
ARG APP
COPY --from=build /app/dist/apps/$APP /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
WORKDIR /usr/share/nginx/html
COPY ./env.sh .
COPY ./apps/$APP/.env .env
# Add bash
RUN apk add --no-cache bash
RUN chmod +x ./env.sh
CMD ["/bin/bash", "-c", "/usr/share/nginx/html/env.sh && nginx -g \"daemon off;\""]

View File

@ -47,11 +47,11 @@ For shared Cypress logic, commands and steps.
### [Web3](./libs/web3)
A ulitity library for connecting to the Ethereum network and interacting with Vega Web3 contracts.
A utility library for connecting to the Ethereum network and interacting with Vega Web3 contracts.
### [React Helpers](./libs/react-helpers)
Generic react helpers that can be used across multilpe applications, along with other utilties.
Generic react helpers that can be used across multilpe applications, along with other utilities.
# 💻 Develop
@ -103,24 +103,42 @@ In CI linting, formatting and also run. These checks can be seen in the [CI work
Visit the [Nx Documentation](https://nx.dev/getting-started/intro) to learn more.
# Vegacapsule
# Docker & Vegacapsule
## Explorer
## Docker
Follow the following steps to start using a local network with the Vega Explorer:
The [Dockerfile](./Dockerfile) for running the frontends is pretty basic, merely building the application with the APP arg that is passed in and serving the application from [nginx](./nginx/nginx.conf). The only complexity that exists is that there is a script which allows the passing of run time environment variables to the containers. See configuration below for how to do this.
1. Prepare vegacapsule. Follow the [Vegacapsule instructions](https://github.com/vegaprotocol/vegacapsule#quick-start)
2. Build the explorer frontend application
3. Start the explorer frontend application with the `.env.vegacapsule` env file
4. Go to [http://localhost:3000](http://localhost:3000) in your browser
If you simply want to run Explorer locally, without using a local network:
You can build any of the containers locally with the following command:
```bash
cd apps/explorer && cp .env.testnet .env.local
yarn nx run explorer:serve
docker build . --build-arg APP=[YOUR APP] --tag=[TAG]
```
In order to run a container:
```bash
docker run -p 3000:80 [TAG]
```
## Config
As environment variables are build time and not run time in frontend applications. We have built a system which allows for passing run time environment variables, this generates a JSON file that will override the default environment variables that the container was built with (which is always testnet, using the default .env files).
In order to override specific environment variables you can pass these to the container like this:
```bash
docker run -e NX_VEGA_URL=https://n04.d.vega.xyz/query -p 3000:80 [TAG]
```
Which will now point the app to use a devnet data node. To see a list of all possible config properties see the readme.md for each app in the app directory.
## Vega capsule
Coming soon! You will be able to run the containers within Vega Capsule.
You can run against a local instance of Vega Capsule today by using the .env.capsule present in the apps.
# 📑 License
[MIT](./LICENSE)

View File

@ -1,11 +1,11 @@
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = 'http://localhost:26617'
NX_TENDERMINT_WEBSOCKET_URL = 'wss://localhost:26617/websocket'
NX_VEGA_URL = "http://localhost:3028/query"
NX_VEGA_ENV = 'LOCAL'
NX_VEGA_REST = 'http://localhost:3029'
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=LOCAL
NX_VEGA_REST=http://localhost:3029
CYPRESS_VEGA_TENDERMINT_URL='http://localhost:26617'
CYPRESS_VEGA_TENDERMINT_URL=http://localhost:26617
NX_EXPLORER_ASSETS=1
NX_EXPLORER_GENESIS=1

View File

@ -1,10 +1,10 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://n04.d.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://n04.d.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://n04.d.vega.xyz/query"
NX_VEGA_ENV = 'DEVNET'
NX_VEGA_REST = 'https://n04.d.vega.xyz/datanode/rest'
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n04.d.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
NX_VEGA_URL=https://n04.d.vega.xyz/query
NX_VEGA_ENV=DEVNET
NX_VEGA_REST=https://n04.d.vega.xyz/datanode/rest
# App flags
NX_EXPLORER_ASSETS=1

View File

@ -1,10 +1,10 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://mainnet-observer-proxy01.ops.vega.xyz/"
NX_TENDERMINT_WEBSOCKET_URL = "wss://mainnet-observer-proxy01.ops.vega.xyz/websocket"
NX_VEGA_URL = "https://api.token.vega.xyz/query"
NX_VEGA_ENV = 'MAINNET'
NX_VEGA_REST = 'https://api.token.vega.xyz/'
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://mainnet-observer-proxy01.ops.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
NX_VEGA_URL=https://api.token.vega.xyz/query
NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/
# App flags
NX_EXPLORER_ASSETS=1

View File

@ -1,10 +1,10 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://n03.s.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://n03.s.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://n03.s.vega.xyz/query"
NX_VEGA_ENV = 'STAGNET'
NX_VEGA_REST = 'https://n03.s.vega.xyz/datanode/rest'
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n03.s.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n03.s.vega.xyz/tm/websocket
NX_VEGA_URL=https://n03.s.vega.xyz/query
NX_VEGA_ENV=STAGNET
NX_VEGA_REST=https://n03.s.vega.xyz/datanode/rest
# App flags
NX_EXPLORER_ASSETS=1

View File

@ -1,10 +1,10 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://n03.stagnet2.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://n03.stagnet2.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://n03.stagnet2.vega.xyz/query"
NX_VEGA_ENV = 'STAGNET2'
NX_VEGA_REST = 'https://n01.stagnet2.vega.xyz/datanode/rest'
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n03.stagnet2.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n03.stagnet2.vega.xyz/tm/websocket
NX_VEGA_URL=https://n03.stagnet2.vega.xyz/query
NX_VEGA_ENV=STAGNET2
NX_VEGA_REST=https://n01.stagnet2.vega.xyz/datanode/rest
# App flags
NX_EXPLORER_ASSETS=1

View File

@ -1,10 +1,10 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://lb.testnet.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://lb.testnet.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
NX_VEGA_ENV = 'TESTNET'
NX_VEGA_REST = 'https://lb.testnet.vega.xyz/datanode/rest'
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://lb.testnet.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://lb.testnet.vega.xyz/datanode/rest
# App flags
NX_EXPLORER_ASSETS=1

View File

@ -1,31 +1,18 @@
# React Environment Variables
# https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#expanding-environment-variables-in-env
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=LOCAL
NX_VEGA_REST=http://localhost:3029
# Netlify Environment Variables
# https://www.netlify.com/docs/continuous-deployment/#environment-variables
NX_VERSION=$npm_package_version
NX_REPOSITORY_URL=$REPOSITORY_URL
NX_BRANCH=$BRANCH
NX_PULL_REQUEST=$PULL_REQUEST
NX_HEAD=$HEAD
NX_COMMIT_REF=$COMMIT_REF
NX_CONTEXT=$CONTEXT
NX_REVIEW_ID=$REVIEW_ID
NX_INCOMING_HOOK_TITLE=$INCOMING_HOOK_TITLE
NX_INCOMING_HOOK_URL=$INCOMING_HOOK_URL
NX_INCOMING_HOOK_BODY=$INCOMING_HOOK_BODY
NX_URL=$URL
NX_DEPLOY_URL=$DEPLOY_URL
NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
NX_CHAIN_EXPLORER_URL = 'https://explorer.vega.trading/.netlify/functions/chain-explorer-api'
NX_TENDERMINT_URL = 'https://lb.testnet.vega.xyz/tm'
NX_TENDERMINT_WEBSOCKET_URL = 'wss://lb.testnet.vega.xyz/tm/websocket'
NX_VEGA_URL = 'https://lb.testnet.vega.xyz/query'
NX_VEGA_ENV = 'TESTNET'
NX_VEGA_REST = 'https://lb.testnet.vega.xyz/datanode/rest'
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://lb.testnet.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://lb.testnet.vega.xyz/datanode/rest
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
CYPRESS_VEGA_TENDERMINT_URL='https://lb.testnet.vega.xyz/tm'
CYPRESS_VEGA_TENDERMINT_URL=https://lb.testnet.vega.xyz/tm
# App flags
NX_EXPLORER_ASSETS=1
@ -34,3 +21,4 @@ NX_EXPLORER_GOVERNANCE = 1
NX_EXPLORER_NETWORK_PARAMETERS=1
NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
NX_EXPLORER_MARKETS=1

View File

@ -1,11 +1,11 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "http://localhost:26617"
NX_TENDERMINT_WEBSOCKET_URL = "wss://localhost:26617/websocket"
NX_VEGA_URL = "http://localhost:3028/query"
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV = 'LOCAL'
NX_VEGA_REST = 'http://localhost:3029'
NX_VEGA_ENV=LOCAL
NX_VEGA_REST=http://localhost:3029
# App flags
NX_EXPLORER_ASSETS=1

View File

@ -1,8 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://n04.d.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://n04.d.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://n04.d.vega.xyz/query"
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n04.d.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
NX_VEGA_URL=https://n04.d.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV = 'DEVNET'
NX_VEGA_REST = 'https://n04.d.vega.xyz/datanode/rest'
NX_VEGA_ENV=DEVNET
NX_VEGA_REST=https://n04.d.vega.xyz/datanode/rest

View File

@ -1,8 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://mainnet-observer-proxy01.ops.vega.xyz/"
NX_TENDERMINT_WEBSOCKET_URL = "wss://mainnet-observer-proxy01.ops.vega.xyz/websocket"
NX_VEGA_URL = "https://api.token.vega.xyz/query"
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://mainnet-observer-proxy01.ops.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
NX_VEGA_URL=https://api.token.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV = 'MAINNET'
NX_VEGA_REST = 'https://api.token.vega.xyz/'
NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/

View File

@ -1,8 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://n03.s.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://n03.s.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://n03.s.vega.xyz/query"
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n03.s.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n03.s.vega.xyz/tm/websocket
NX_VEGA_URL=https://n03.s.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV = 'STAGNET'
NX_VEGA_REST = 'https://n03.s.vega.xyz/datanode/rest'
NX_VEGA_ENV=STAGNET
NX_VEGA_REST=https://n03.s.vega.xyz/datanode/rest

View File

@ -1,8 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://n03.stagnet2.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://n03.stagnet2.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://n03.stagnet2.vega.xyz/query"
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n03.stagnet2.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n03.stagnet2.vega.xyz/tm/websocket
NX_VEGA_URL=https://n03.stagnet2.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV = 'STAGNET2'
NX_VEGA_REST = 'https://n01.stagnet2.vega.xyz/datanode/rest'
NX_VEGA_ENV=STAGNET2
NX_VEGA_REST=https://n01.stagnet2.vega.xyz/datanode/rest

View File

@ -1,8 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL = "https://explorer.vega.trading/.netlify/functions/chain-explorer-api"
NX_TENDERMINT_URL = "https://lb.testnet.vega.xyz/tm"
NX_TENDERMINT_WEBSOCKET_URL = "wss://lb.testnet.vega.xyz/tm/websocket"
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://lb.testnet.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV = 'TESTNET'
NX_VEGA_REST = 'https://lb.testnet.vega.xyz/datanode/rest'
NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://lb.testnet.vega.xyz/datanode/rest

View File

@ -0,0 +1,7 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=http://localhost:26607/
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
NX_VEGA_URL=http://localhost:3003/query
NX_VEGA_ENV=CUSTOM
NX_VEGA_REST=http://localhost:3029/rest

5
apps/explorer/index.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference types="react-scripts" />
interface Window {
_env_?: Record<string, string>;
}

View File

@ -0,0 +1,33 @@
const windowOrDefault = (key: string) => {
if (window._env_ && window._env_[key]) {
return window._env_[key] as string;
}
return (process.env[key] as string) || '';
};
const truthy = ['1', 'true'];
export const ENV = {
// Data sources
// Environment
dsn: windowOrDefault('NX_EXPLORER_SENTRY_DSN'),
envName: windowOrDefault('NX_VEGA_ENV'),
dataSources: {
chainExplorerUrl: windowOrDefault('NX_CHAIN_EXPLORER_URL'),
tendermintUrl: windowOrDefault('NX_TENDERMINT_URL'),
tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'),
dataNodeUrl: windowOrDefault('NX_VEGA_URL'),
restEndpoint: windowOrDefault('NX_VEGA_REST'),
},
flags: {
assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')),
genesis: truthy.includes(windowOrDefault('NX_EXPLORER_GENESIS')),
governance: truthy.includes(windowOrDefault('NX_EXPLORER_GOVERNANCE')),
markets: truthy.includes(windowOrDefault('NX_EXPLORER_MARKETS')),
networkParameters: truthy.includes(
windowOrDefault('NX_EXPLORER_NETWORK_PARAMETERS')
),
parties: truthy.includes(windowOrDefault('NX_EXPLORER_PARTIES')),
validators: truthy.includes(windowOrDefault('NX_EXPLORER_VALIDATORS')),
},
};

View File

@ -0,0 +1,5 @@
import { ENV } from './env';
export default {
...ENV.flags,
};

View File

@ -1,8 +1,5 @@
import { ENV } from './env';
export const DATA_SOURCES = {
chainExplorerUrl: process.env['NX_CHAIN_EXPLORER_URL'] as string,
tendermintUrl: process.env['NX_TENDERMINT_URL'] as string,
tendermintWebsocketUrl: process.env['NX_TENDERMINT_WEBSOCKET_URL'] as string,
dataNodeUrl: process.env['NX_VEGA_URL'] as string,
envName: process.env['NX_VEGA_ENV'] as string,
restEndpoint: process.env['NX_VEGA_REST'] as string,
...ENV.dataSources,
};

View File

@ -1,13 +0,0 @@
const truthy = ['1', 'true'];
export default {
assets: truthy.includes(process.env['NX_EXPLORER_ASSETS'] || ''),
genesis: truthy.includes(process.env['NX_EXPLORER_GENESIS'] || ''),
governance: truthy.includes(process.env['NX_EXPLORER_GOVERNANCE'] || ''),
markets: truthy.includes(process.env['NX_EXPLORER_MARKETS'] || ''),
networkParameters: truthy.includes(
process.env['NX_EXPLORER_NETWORK_PARAMETERS'] || ''
),
parties: truthy.includes(process.env['NX_EXPLORER_PARTIES'] || ''),
validators: truthy.includes(process.env['NX_EXPLORER_VALIDATORS'] || ''),
};

View File

@ -1,7 +1,8 @@
import { DATA_SOURCES } from '../../config';
import { StatsManager } from '@vegaprotocol/network-stats';
import { ENV } from '../../config/env';
const envName = DATA_SOURCES.envName;
const envName = ENV.envName;
const restEndpoint = DATA_SOURCES.restEndpoint;
const statsEndpoint = `${restEndpoint}/statistics`;
const nodesEndpoint = `${restEndpoint}/nodes-data`;

View File

@ -24,10 +24,10 @@ describe('NetworkParametersTable', () => {
);
const rows = screen.getAllByTestId('key-value-table-row');
expect(rows[0].children[0]).toHaveTextContent(
'market.fee.factors.infrastructureFee'
'Market Fee Factors Infrastructure Fee'
);
expect(rows[1].children[0]).toHaveTextContent(
'market.liquidityProvision.minLpStakeQuantumMultiple'
'Market Liquidity Provision Min Lp Stake Quantum Multiple'
);
expect(rows[0].children[1]).toHaveTextContent('0.0005');
expect(rows[1].children[1]).toHaveTextContent('1');
@ -54,10 +54,10 @@ describe('NetworkParametersTable', () => {
);
const rows = screen.getAllByTestId('key-value-table-row');
expect(rows[0].children[0]).toHaveTextContent(
'market.fee.factors.infrastructureFee'
'Market Fee Factors Infrastructure Fee'
);
expect(rows[1].children[0]).toHaveTextContent(
'market.liquidityProvision.minLpStakeQuantumMultiple'
'Market Liquidity Provision Min Lp Stake Quantum Multiple'
);
expect(rows[0].children[1]).toHaveTextContent('0.0005');
expect(rows[1].children[1]).toHaveTextContent('1');

View File

@ -16,6 +16,7 @@ import type {
NetworkParametersQuery_networkParameters,
} from './__generated__/NetworkParametersQuery';
import orderBy from 'lodash/orderBy';
import startCase from 'lodash/startCase';
const BIG_NUMBER_PARAMS = [
'spam.protection.delegation.min.tokens',
@ -42,7 +43,7 @@ export const renderRow = ({
const isSyntaxRow = isJsonObject(value);
return (
<KeyValueTableRow key={key} inline={!isSyntaxRow}>
{key}
{startCase(key)}
{isSyntaxRow ? (
<SyntaxHighlighter data={JSON.parse(value)} />
) : isNaN(Number(value)) ? (

View File

@ -14,7 +14,7 @@ import { Blocks } from './blocks/home';
import { Tx } from './txs/id';
import { Txs as TxHome } from './txs/home';
import { PendingTxs } from './pending';
import flags from '../lib/flags';
import flags from '../config/flags';
import { t } from '@vegaprotocol/react-helpers';
import { Routes } from './route-names';
import { NetworkParameters } from './network-parameters';

View File

@ -0,0 +1 @@
window._env_ = {};

View File

@ -18,6 +18,7 @@
href="https://static.vega.xyz/favicon.ico"
/>
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
<script src="./assets/env-config.js"></script>
</head>
<body>
<div id="root"></div>

View File

@ -6,8 +6,9 @@ import { BrowserRouter } from 'react-router-dom';
import './styles.css';
import App from './app/app';
import { ENV } from './app/config/env';
const dsn = process.env['NX_EXPLORER_SENTRY_DSN'];
const { dsn } = ENV;
/* istanbul ignore next */
if (dsn) {
@ -15,7 +16,7 @@ if (dsn) {
dsn,
integrations: [new BrowserTracing()],
tracesSampleRate: 1,
environment: process.env['NX_VEGA_ENV'],
environment: ENV.envName,
});
}

View File

@ -21,6 +21,6 @@ NX_URL=$URL
NX_DEPLOY_URL=$DEPLOY_URL
NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
NX_VEGA_ENV = 'TESTNET'
NX_VEGA_REST = 'https://lb.testnet.vega.xyz/datanode/rest'
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://lb.testnet.vega.xyz/datanode/rest

View File

@ -0,0 +1,79 @@
describe('market list', () => {
describe('simple url', () => {
beforeEach(() => {
cy.visit('/markets');
});
it('selects menus', () => {
cy.get('.MuiDrawer-root [aria-current]').should('have.text', 'Markets');
cy.getByTestId('state-trigger').should('have.text', 'Active');
cy.get('[aria-label="Future"]').click();
cy.get('[data-testid="market-assets-menu"] a.active').should(
'have.text',
'All'
);
});
it('navigation should make possibly shortest url', () => {
cy.location('pathname').should('equal', '/markets');
cy.getByTestId('state-trigger').click();
cy.get('[role=menuitemcheckbox]').contains('All').click();
cy.location('pathname').should('equal', '/markets/all');
cy.get('[aria-label="Future"]').click();
cy.location('pathname').should('eq', '/markets/all/Future');
let asset = '';
cy.getByTestId('market-assets-menu')
.children()
.then((children) => {
if (children.length > 1) {
asset = children[1].innerText;
if (asset) {
cy.wrap(children[1]).click();
cy.location('pathname').should(
'match',
new RegExp(`/markets/all/Future/${asset}`, 'i')
);
cy.get('a').contains('All Markets').click();
cy.location('pathname').should('eq', '/markets/all');
}
}
});
cy.getByTestId('state-trigger').click();
cy.get('[role=menuitemcheckbox]').contains('Active').click();
cy.location('pathname').should('equal', '/markets');
});
});
describe('url params should select filters', () => {
it('suspended status', () => {
cy.visit('/markets/Suspended');
cy.getByTestId('state-trigger').should('have.text', 'Suspended');
});
it('last asset (if exists)', () => {
cy.intercept('POST', '/query').as('Filters');
cy.visit('/markets');
cy.wait('@Filters').then((filters) => {
if (filters?.response?.body.data.markets.length) {
const asset =
filters.response.body.data.markets[0].tradableInstrument.instrument
.product.settlementAsset.symbol;
cy.visit(`/markets/Suspended/Future/${asset}`);
cy.getByTestId('market-assets-menu')
.find('a.active')
.should('have.text', asset);
}
});
});
it('Future product', () => {
cy.visit('/markets/Suspended/Future');
cy.getByTestId('market-products-menu')
.find('a.active')
.should('have.text', 'Future');
});
});
});

View File

@ -13,5 +13,6 @@
// https://on.cypress.io/configuration
// ***********************************************************
import '@vegaprotocol/cypress';
// Import commands.js using ES2015 syntax:
import './commands';

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_URL = "http://localhost:3028/query"
NX_VEGA_ENV = 'LOCAL'
NX_VEGA_REST = 'http://localhost:3029'
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=LOCAL
NX_VEGA_REST=http://localhost:3029

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_URL = "https://n04.d.vega.xyz/query"
NX_VEGA_ENV = 'DEVNET'
NX_VEGA_REST = 'https://n04.d.vega.xyz/datanode/rest'
NX_VEGA_URL=https://n04.d.vega.xyz/query
NX_VEGA_ENV=DEVNET
NX_VEGA_REST=https://n04.d.vega.xyz/datanode/rest

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_URL = "https://api.token.vega.xyz/query"
NX_VEGA_ENV = 'MAINNET'
NX_VEGA_REST = 'https://api.token.vega.xyz/'
NX_VEGA_URL=https://api.token.vega.xyz/query
NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_URL = "https://n03.s.vega.xyz/query"
NX_VEGA_ENV = 'STAGNET'
NX_VEGA_REST = 'https://n03.s.vega.xyz/datanode/rest'
NX_VEGA_URL=https://n03.s.vega.xyz/query
NX_VEGA_ENV=STAGNET
NX_VEGA_REST=https://n03.s.vega.xyz/datanode/rest

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_URL = "https://n03.stagnet2.vega.xyz/query"
NX_VEGA_ENV = 'STAGNET2'
NX_VEGA_REST = 'https://n01.stagnet2.vega.xyz/datanode/rest'
NX_VEGA_URL=https://n03.stagnet2.vega.xyz/query
NX_VEGA_ENV=STAGNET2
NX_VEGA_REST=https://n01.stagnet2.vega.xyz/datanode/rest

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
NX_VEGA_ENV = 'TESTNET'
NX_VEGA_REST = 'https://lb.testnet.vega.xyz/datanode/rest'
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://lb.testnet.vega.xyz/datanode/rest

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import { theme } from '@vegaprotocol/tailwindcss-config';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import type { ReactElement } from 'react';
import { useEffect } from 'react';
import Drawer from '@mui/material/Drawer';

View File

@ -0,0 +1,55 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
// ====================================================
// GraphQL query operation: MarketFilters
// ====================================================
export interface MarketFilters_markets_tradableInstrument_instrument_product_settlementAsset {
__typename: "Asset";
/**
* The symbol of the asset (e.g: GBP)
*/
symbol: string;
}
export interface MarketFilters_markets_tradableInstrument_instrument_product {
__typename: "Future";
/**
* The name of the asset (string)
*/
settlementAsset: MarketFilters_markets_tradableInstrument_instrument_product_settlementAsset;
}
export interface MarketFilters_markets_tradableInstrument_instrument {
__typename: "Instrument";
/**
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
*/
product: MarketFilters_markets_tradableInstrument_instrument_product;
}
export interface MarketFilters_markets_tradableInstrument {
__typename: "TradableInstrument";
/**
* An instance of or reference to a fully specified instrument.
*/
instrument: MarketFilters_markets_tradableInstrument_instrument;
}
export interface MarketFilters_markets {
__typename: "Market";
/**
* An instance of or reference to a tradable instrument.
*/
tradableInstrument: MarketFilters_markets_tradableInstrument;
}
export interface MarketFilters {
/**
* One or more instruments that are trading on the VEGA network
*/
markets: MarketFilters_markets[] | null;
}

View File

@ -1,5 +1,6 @@
import { Intent } from '@vegaprotocol/ui-toolkit';
import { MarketState } from '@vegaprotocol/types';
import { t } from '@vegaprotocol/react-helpers';
export const MARKET_STATUS: Record<MarketState | '', Intent> = {
[MarketState.Active]: Intent.Success,
@ -13,3 +14,16 @@ export const MARKET_STATUS: Record<MarketState | '', Intent> = {
[MarketState.TradingTerminated]: Intent.Danger,
'': Intent.Primary,
};
export const STATES_FILTER = [
{ value: 'all', text: t('All') },
{ value: 'Active', text: t('Active') },
{ value: 'Cancelled', text: t('Cancelled') },
{ value: 'Closed', text: t('Closed') },
{ value: 'Pending', text: t('Pending') },
{ value: 'Proposed', text: t('Proposed') },
{ value: 'Rejected', text: t('Rejected') },
{ value: 'Settled', text: t('Settled') },
{ value: 'Suspended', text: t('Suspended') },
{ value: 'TradingTerminated', text: t('TradingTerminated') },
];

View File

@ -33,6 +33,7 @@ export const MARKETS_QUERY = gql`
tags
}
product {
__typename
... on Future {
settlementAsset {
symbol
@ -66,6 +67,25 @@ export const CANDLE_SUB = gql`
}
`;
export const FILTERS_QUERY = gql`
query MarketFilters {
markets {
tradableInstrument {
instrument {
product {
__typename
... on Future {
settlementAsset {
symbol
}
}
}
}
}
}
}
`;
const update = (
draft: SimpleMarkets_markets[],
delta: SimpleMarketDataSub_marketData

View File

@ -0,0 +1,225 @@
{
"markets": [
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "XYZalpha",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tUSDC",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tDAI",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tBTC",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tEURO",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tDAI",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tEURO",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tDAI",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tBTC",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Future"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tUSDC",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tDAI",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tDAI",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
},
{
"tradableInstrument": {
"instrument": {
"product": {
"__typename": "Future",
"settlementAsset": {
"symbol": "tDAI",
"__typename": "Asset"
},
"__typename": "Future"
},
"__typename": "Instrument"
},
"__typename": "TradableInstrument"
},
"__typename": "Market"
}
]
}

View File

@ -1,18 +1,24 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { render, screen, waitFor } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import type { MockedResponse } from '@apollo/client/testing';
import { BrowserRouter } from 'react-router-dom';
import { MarketState } from '@vegaprotocol/types';
import SimpleMarketList from './simple-market-list';
import { MARKETS_QUERY } from './data-provider';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
import type { SimpleMarkets } from './__generated__/SimpleMarkets';
import { FILTERS_QUERY, MARKETS_QUERY } from './data-provider';
import type {
SimpleMarkets_markets,
SimpleMarkets,
} from './__generated__/SimpleMarkets';
import type { MarketFilters } from './__generated__/MarketFilters';
const mockedNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockedNavigate,
useParams: () => ({}),
}));
jest.mock('date-fns', () => ({
@ -20,6 +26,15 @@ jest.mock('date-fns', () => ({
}));
describe('SimpleMarketList', () => {
const filterMock: MockedResponse<MarketFilters> = {
request: {
query: FILTERS_QUERY,
},
result: {
data: { markets: [] },
},
};
afterEach(() => {
jest.clearAllMocks();
});
@ -36,17 +51,19 @@ describe('SimpleMarketList', () => {
data: { markets: [] },
},
};
await act(async () => {
render(
<MockedProvider mocks={[mocks]}>
<MockedProvider mocks={[mocks, filterMock]}>
<SimpleMarketList />
</MockedProvider>
</MockedProvider>,
{ wrapper: BrowserRouter }
);
await new Promise((resolve) => setTimeout(resolve, 0));
});
await waitFor(() => {
expect(screen.getByText('No data to display')).toBeInTheDocument();
});
});
it('should be properly rendered with some data', async () => {
const data = [
@ -74,7 +91,7 @@ describe('SimpleMarketList', () => {
id: '2',
data: {
market: {
state: MarketState.Proposed,
state: MarketState.Active,
},
},
tradableInstrument: {
@ -103,15 +120,18 @@ describe('SimpleMarketList', () => {
data: { markets: data },
},
};
await act(async () => {
render(
<MockedProvider mocks={[mocks]}>
<MockedProvider mocks={[mocks, filterMock]}>
<SimpleMarketList />
</MockedProvider>
</MockedProvider>,
{ wrapper: BrowserRouter }
);
await new Promise((resolve) => setTimeout(resolve, 0));
expect(screen.getByRole('list')).toBeInTheDocument();
expect(screen.getAllByRole('listitem')).toHaveLength(2);
});
await waitFor(() => {
expect(screen.getByTestId('simple-market-list')).toBeInTheDocument();
});
expect(screen.getByTestId('simple-market-list').children).toHaveLength(2);
});
});

View File

@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { useNavigate, useParams } from 'react-router-dom';
import { subDays } from 'date-fns';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/react-helpers';
@ -10,9 +10,19 @@ import SimpleMarketPercentChange from './simple-market-percent-change';
import SimpleMarketExpires from './simple-market-expires';
import DataProvider from './data-provider';
import { MARKET_STATUS } from './constants';
import SimpleMarketToolbar from './simple-market-toolbar';
import useMarketsFilterData from '../../hooks/use-markets-filter-data';
export type RouterParams = Partial<{
product: string;
asset: string;
state: string;
}>;
const SimpleMarketList = () => {
const navigate = useNavigate();
const params = useParams<RouterParams>();
const statusesRef = useRef<Record<string, MarketState | ''>>({});
const variables = useMemo(
() => ({
@ -21,12 +31,7 @@ const SimpleMarketList = () => {
[]
);
const update = useCallback(
(delta) => {
if (statusesRef.current[delta.market.id] !== delta.market.state) {
return false;
}
return true;
},
(delta) => statusesRef.current[delta.market.id] === delta.market.state,
[statusesRef]
);
@ -35,13 +40,15 @@ const SimpleMarketList = () => {
update,
variables
);
const localData = useMarketsFilterData(data || [], params);
useEffect(() => {
const statuses: Record<string, MarketState | ''> = {};
data?.forEach((market) => {
statuses[market.id] = market.data?.market.state || '';
});
statusesRef.current = statuses;
}, [data]);
}, [data, statusesRef]);
const onClick = useCallback(
(marketId) => {
@ -51,12 +58,17 @@ const SimpleMarketList = () => {
);
return (
<AsyncRenderer loading={loading} error={error} data={data}>
{data && data.length > 0 ? (
<ul className="list-none relative pt-8 pb-8">
{data?.map((market) => (
<>
<SimpleMarketToolbar />
<AsyncRenderer loading={loading} error={error} data={localData}>
{localData && localData.length > 0 ? (
<ul
className="list-none relative pt-8 pb-8"
data-testid="simple-market-list"
>
{localData?.map((market) => (
<li
className="w-full relative flex justify-start items-center no-underline box-border text-left pt-8 pb-8 pl-16 pr-16 mb-10"
className="w-full relative flex justify-start items-center no-underline box-border text-left py-8 mb-10"
key={market.id}
>
<div className="w-full grid sm:grid-cols-2">
@ -66,8 +78,8 @@ const SimpleMarketList = () => {
tags={market.tradableInstrument.instrument.metadata.tags}
/>
<div className="py-2">{`${t('settled in')} ${
market.tradableInstrument.instrument.product.settlementAsset
.symbol
market.tradableInstrument.instrument.product
.settlementAsset.symbol
}`}</div>
</div>
<div className="w-full grid sm:grid-rows-2">
@ -100,6 +112,7 @@ const SimpleMarketList = () => {
<Splash>{t('No data to display')}</Splash>
)}
</AsyncRenderer>
</>
);
};

View File

@ -1,6 +1,6 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { theme } from '@vegaprotocol/tailwindcss-config';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import { MockedProvider } from '@apollo/react-testing';
import SimpleMarketPercentChange from './simple-market-percent-change';
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';

View File

@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { InView } from 'react-intersection-observer';
import { useSubscription } from '@apollo/client';
import { theme } from '@vegaprotocol/tailwindcss-config';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';
import type {
CandleLive,

View File

@ -0,0 +1,122 @@
import React from 'react';
import { useLocation, useRoutes, BrowserRouter } from 'react-router-dom';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { MockedProvider } from '@apollo/react-testing';
import SimpleMarketToolbar from './simple-market-toolbar';
import type { MockedResponse } from '@apollo/client/testing';
import type { MarketFilters } from './__generated__/MarketFilters';
import { FILTERS_QUERY } from './data-provider';
import filterData from './mocks/market-filters.json';
describe('SimpleMarketToolbar', () => {
const filterMock: MockedResponse<MarketFilters> = {
request: {
query: FILTERS_QUERY,
},
result: {
data: filterData as unknown as MarketFilters,
},
};
const WrappedCompForTest = () => {
const routes = useRoutes([
{
path: '/',
element: <SimpleMarketToolbar />,
},
{
path: 'markets',
children: [
{
path: `:state`,
element: <SimpleMarketToolbar />,
children: [
{
path: `:product`,
element: <SimpleMarketToolbar />,
children: [
{ path: `:asset`, element: <SimpleMarketToolbar /> },
],
},
],
},
],
element: <SimpleMarketToolbar />,
},
]);
const location = useLocation();
return (
<>
{routes}
<div data-testid="location-display">{location.pathname}</div>
</>
);
};
afterEach(() => {
jest.resetAllMocks();
});
it('should be properly rendered', async () => {
render(
<MockedProvider mocks={[filterMock]} addTypename={false}>
<WrappedCompForTest />
</MockedProvider>,
{ wrapper: BrowserRouter }
);
await waitFor(() => {
expect(screen.getByText('Future')).toBeInTheDocument();
});
fireEvent.click(screen.getByText('Future'));
await waitFor(() => {
expect(screen.getByTestId('market-products-menu').children).toHaveLength(
3
);
expect(screen.getByTestId('market-assets-menu').children).toHaveLength(6);
});
fireEvent.click(screen.getByTestId('state-trigger'));
waitFor(() => {
expect(screen.getByRole('menu')).toBeInTheDocument();
expect(screen.getByRole('menu').children).toHaveLength(10);
});
});
it('navigation should work well', async () => {
render(
<MockedProvider mocks={[filterMock]} addTypename={false}>
<WrappedCompForTest />
</MockedProvider>,
{ wrapper: BrowserRouter }
);
await waitFor(() => {
expect(screen.getByText('Future')).toBeInTheDocument();
});
fireEvent.click(screen.getByText('Future'));
await waitFor(() => {
expect(screen.getByTestId('location-display')).toHaveTextContent(
'/markets/Active/Future'
);
});
fireEvent.click(
screen
.getByTestId('market-assets-menu')
.children[5].querySelector('a') as HTMLAnchorElement
);
await waitFor(() => {
expect(screen.getByTestId('location-display')).toHaveTextContent(
'/markets/Active/Future/tEURO'
);
});
fireEvent.click(screen.getByTestId('state-trigger'));
waitFor(() => {
expect(screen.getByRole('menu')).toBeInTheDocument();
fireEvent.click(screen.getByText('Pending'));
expect(screen.getByTestId('location-display')).toHaveTextContent(
'/markets/Pending/Future/tEURO'
);
});
});
});

View File

@ -0,0 +1,205 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import classNames from 'classnames';
import { useNavigate, useParams, Link } from 'react-router-dom';
import {
DropdownMenu,
DropdownMenuTrigger,
} from '@radix-ui/react-dropdown-menu';
import { IconNames } from '@blueprintjs/icons';
import { t } from '@vegaprotocol/react-helpers';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import {
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuItemIndicator,
Icon,
} from '@vegaprotocol/ui-toolkit';
import useMarketFiltersData from '../../hooks/use-markets-filter';
import { STATES_FILTER } from './constants';
const SimpleMarketToolbar = () => {
const navigate = useNavigate();
const params = useParams();
const { products, assetsPerProduct } = useMarketFiltersData();
const [isOpen, setOpen] = useState(false);
const [activeNumber, setActiveNumber] = useState(
products?.length ? products.indexOf(params.product || '') + 1 : -1
);
const [sliderStyles, setSliderStyles] = useState<Record<string, string>>({});
const slideContRef = useRef<HTMLUListElement | null>(null);
useEffect(() => {
if (products.length) {
setActiveNumber(products.indexOf(params.product || '') + 1);
} else {
setActiveNumber(-1);
}
}, [params, products, setActiveNumber]);
useEffect(() => {
const contStyles = (
slideContRef.current as HTMLUListElement
).getBoundingClientRect();
const selectedStyles = (slideContRef.current as HTMLUListElement).children[
activeNumber
]?.getBoundingClientRect();
const styles: Record<string, string> = selectedStyles
? {
backgroundColor: activeNumber ? '' : theme.colors.pink,
width: `${selectedStyles.width}px`,
left: `${selectedStyles.left - contStyles.left}px`,
}
: {};
setSliderStyles(styles);
}, [activeNumber, slideContRef]);
const onStateChange = useCallback(
(activeState: string) => {
const asset =
params.asset && params.asset !== 'all' ? `/${params.asset}` : '';
const product = params.product ? `/${params.product}` : '';
const state =
activeState !== 'Active' || product ? `/${activeState}` : '';
navigate(`/markets${state}${product}${asset}`);
},
[params, navigate]
);
return (
<div className="w-max mb-16 font-alpha">
<ul
ref={slideContRef}
className="grid grid-flow-col auto-cols-min gap-8 relative pb-4 mb-16"
data-testid="market-products-menu"
aria-label={t('Product type')}
>
<li key="all" className="md:mr-16 whitespace-nowrap">
<Link
to={`/markets${
params.state && params.state !== 'Active'
? '/' + params.state
: ''
}`}
aria-label={t('All markets')}
className={classNames('text-h5 pl-0 text-pink hover:opacity-75', {
active: !activeNumber,
})}
>
{t('All Markets')}
</Link>
</li>
{products.map((product, i) => (
<li key={product} className="mx-16 whitespace-nowrap">
<Link
to={`/markets/${params.state || 'Active'}/${product}`}
className={classNames(
'text-h5 hover:opacity-75 text-black dark:text-white',
{
active: activeNumber - 1 === i,
}
)}
aria-label={product}
>
{product}
</Link>
</li>
))}
<li
className="absolute bottom-0 h-2 transition-left duration-300 dark:bg-white bg-black"
key="slider"
style={sliderStyles}
/>
</ul>
<div className="grid gap-8 pb-4 mt-8 md:grid-cols-[min-content,min-content,1fr]">
<div className="pb-8">
<DropdownMenu onOpenChange={(open) => setOpen(open)}>
<DropdownMenuTrigger
className="mr-16 w-auto text-capMenu text-black dark:text-white"
data-testid="state-trigger"
>
<div className="w-full justify-between uppercase inline-flex items-center justify-center box-border">
{STATES_FILTER.find(
(state) =>
state.value === params.state ||
(!params.state && state.value === 'Active')
)?.text || params.state}
<Icon
name={IconNames.ARROW_DOWN}
className={classNames(
'fill-current ml-8 transition-transform',
{
'rotate-180': isOpen,
}
)}
size={16}
/>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent>
{STATES_FILTER.map(({ value, text }) => (
<DropdownMenuCheckboxItem
className="uppercase text-ui dark:text-white"
key={value}
inset
checked={
value === params.state ||
(!params.state && value === 'Active')
}
onCheckedChange={() => onStateChange(value)}
>
<DropdownMenuItemIndicator>
<Icon name="tick" />
</DropdownMenuItemIndicator>
{text}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="hidden md:block text-deemphasise dark:text-midGrey">
|
</div>
{activeNumber > 0 && (
<ul
className="grid grid-flow-col auto-cols-min md:gap-16 sm:gap-12 pb-4 md:ml-16"
data-testid="market-assets-menu"
aria-label={t('Asset on the market')}
>
<li key="all">
<Link
to={`/markets/${params.state}/${params.product}`}
className={classNames('uppercase pl-0 md:pl-4 text-capMenu', {
'text-deemphasise dark:text-midGrey':
params.asset && params.asset !== 'all',
'active text-black dark:text-white':
!params.asset || params.asset === 'all',
})}
aria-label={t('All assets')}
>
{t('All')}
</Link>
</li>
{assetsPerProduct[products[activeNumber - 1]]?.map((asset) => (
<li key={asset}>
<Link
to={`/markets/${params.state}/${params.product}/${asset}`}
className={classNames('uppercase text-capMenu', {
'text-deemphasise dark:text-midGrey':
params.asset !== asset,
'active text-black dark:text-white': params.asset === asset,
})}
aria-label={asset}
>
{asset}
</Link>
</li>
))}
</ul>
)}
</div>
</div>
);
};
export default SimpleMarketToolbar;

View File

@ -0,0 +1,32 @@
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
import type { RouterParams } from '../components/simple-market-list/simple-market-list';
const useMarketsFilterData = (
data: SimpleMarkets_markets[] = [],
params: RouterParams
) => {
return data.filter((item) => {
if (
params.product &&
params.product !== item.tradableInstrument.instrument.product.__typename
) {
return false;
}
if (
params.asset &&
params.asset !== 'all' &&
params.asset !==
item.tradableInstrument.instrument.product.settlementAsset.symbol
) {
return false;
}
const state =
params.state === 'all' ? '' : params.state ? params.state : 'Active';
if (state && state !== item.data?.market.state) {
return false;
}
return true;
});
};
export default useMarketsFilterData;

View File

@ -0,0 +1,41 @@
import { useEffect, useState } from 'react';
import { useQuery } from '@apollo/client';
import { FILTERS_QUERY } from '../components/simple-market-list/data-provider';
import type { MarketFilters } from '../components/simple-market-list/__generated__/MarketFilters';
const useMarketFilters = () => {
const [products, setProducts] = useState<string[]>([]);
const [assetsPerProduct, setAssetsPerProduct] = useState<
Record<string, string[]>
>({});
const { data } = useQuery<MarketFilters>(FILTERS_QUERY, {
pollInterval: 5000,
});
useEffect(() => {
const localProducts = new Set<string>();
const localAssetPerProduct: Record<string, Set<string>> = {};
data?.markets?.forEach((item) => {
const product = item.tradableInstrument.instrument.product.__typename;
const asset =
item.tradableInstrument.instrument.product.settlementAsset.symbol;
if (!(product in localAssetPerProduct)) {
localAssetPerProduct[product] = new Set<string>();
}
localAssetPerProduct[product].add(asset);
localProducts.add(product);
});
setProducts([...localProducts]);
setAssetsPerProduct(
Object.entries(localAssetPerProduct).reduce(
(agg: Record<string, string[]>, entry) => {
agg[entry[0]] = [...entry[1]];
return agg;
},
{}
)
);
}, [data]);
return { products, assetsPerProduct };
};
export default useMarketFilters;

View File

@ -20,6 +20,19 @@ export const routerConfig = [
},
{
path: ROUTES.MARKETS,
children: [
{
path: `:state`,
element: <SimpleMarketList />,
children: [
{
path: `:product`,
element: <SimpleMarketList />,
children: [{ path: `:asset`, element: <SimpleMarketList /> }],
},
],
},
],
name: 'Markets',
text: t('Markets'),
element: <SimpleMarketList />,

View File

@ -1,6 +1,6 @@
const { join } = require('path');
const { createGlobPatternsForDependencies } = require('@nrwl/next/tailwind');
const theme = require('../../libs/tailwindcss-config/src/theme');
const theme = require('../../libs/tailwindcss-config/src/theme-lite');
const vegaCustomClasses = require('../../libs/tailwindcss-config/src/vega-custom-classes');
module.exports = {

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@
"tranche_end": "2022-11-26T13:48:10.000Z",
"total_added": "100",
"total_removed": "0",
"locked_amount": "45.544174911212587",
"locked_amount": "43.3757895738204",
"deposits": [
{
"amount": "100",
@ -240,18 +240,62 @@
"tranche_id": 3,
"tranche_start": "2021-10-12T00:53:20.000Z",
"tranche_end": "2022-10-12T00:53:20.000Z",
"total_added": "100",
"total_removed": "0",
"locked_amount": "33.06798896499239",
"total_added": "1100",
"total_removed": "673.04388635",
"locked_amount": "339.895639903602233",
"deposits": [
{
"amount": "1000",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tx": "0xfee1971d3403ecfbee9b88a14aee2654a5a397d9fb5e4a1787b0a8d4a60dd42c"
},
{
"amount": "100",
"user": "0xFc00fa2A8B7f0D85a39e101B985a74e83f5c8980",
"tx": "0xf3a97d073a229b78b0dfacb6b24d6eb2fc89d79dc003bff114c1d205705f880b"
}
],
"withdrawals": [],
"withdrawals": [
{
"amount": "673.00240994",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tx": "0xdaf6124a50ae4cfed3e72d42e5bb43dcc707538d3db1355f215aac162c3f35a4"
},
{
"amount": "0.04147641",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tx": "0x8c9b4e7bb2ef3f06f47c614ac42f466de3b6994c36a5061e7d384607bdbdfb01"
}
],
"users": [
{
"address": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"deposits": [
{
"amount": "1000",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tranche_id": 3,
"tx": "0xfee1971d3403ecfbee9b88a14aee2654a5a397d9fb5e4a1787b0a8d4a60dd42c"
}
],
"withdrawals": [
{
"amount": "673.00240994",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tranche_id": 3,
"tx": "0xdaf6124a50ae4cfed3e72d42e5bb43dcc707538d3db1355f215aac162c3f35a4"
},
{
"amount": "0.04147641",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tranche_id": 3,
"tx": "0x8c9b4e7bb2ef3f06f47c614ac42f466de3b6994c36a5061e7d384607bdbdfb01"
}
],
"total_tokens": "1000",
"withdrawn_tokens": "673.04388635",
"remaining_tokens": "326.95611365"
},
{
"address": "0xFc00fa2A8B7f0D85a39e101B985a74e83f5c8980",
"deposits": [

View File

@ -68,8 +68,8 @@
"tranche_start": "2021-10-12T00:53:20.000Z",
"tranche_end": "2022-10-12T00:53:20.000Z",
"total_added": "1010.000000000000000001",
"total_removed": "668.3761174488",
"locked_amount": "333.9866885464231390003306798896499239",
"total_removed": "668.4622323651",
"locked_amount": "312.08602866565198040030899606798579404",
"deposits": [
{
"amount": "1000",
@ -107,6 +107,11 @@
"amount": "0.0000190259",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tx": "0xcbc22a50267244f1cbb61c1018270f7e9d0052815141c7c1158393036e93be5b"
},
{
"amount": "0.0861149163",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tx": "0xaef5a50d71958240471b88830f19e3ebd0095bbf52e815cfc4aec41fc77e1b40"
}
],
"users": [
@ -166,11 +171,17 @@
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tranche_id": 2,
"tx": "0xcbc22a50267244f1cbb61c1018270f7e9d0052815141c7c1158393036e93be5b"
},
{
"amount": "0.0861149163",
"user": "0x970Bf6C66E55f90a7D455354954Af5CaBA11318C",
"tranche_id": 2,
"tx": "0xaef5a50d71958240471b88830f19e3ebd0095bbf52e815cfc4aec41fc77e1b40"
}
],
"total_tokens": "10.000000000000000001",
"withdrawn_tokens": "6.6176192288",
"remaining_tokens": "3.382380771200000001"
"withdrawn_tokens": "6.7037341451",
"remaining_tokens": "3.296265854900000001"
}
]
},

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_ENV = 'TESTNET'
CYPRESS_VEGA_ENV = 'TESTNET'
NX_VEGA_REST = 'https://lb.testnet.vega.xyz/datanode/rest'
NX_VEGA_ENV=TESTNET
CYPRESS_VEGA_ENV=TESTNET
NX_VEGA_REST=https://lb.testnet.vega.xyz/datanode/rest

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_ENV = 'DEVNET'
CYPRESS_VEGA_ENV = 'DEVNET'
NX_VEGA_REST = 'https://n04.d.vega.xyz/datanode/rest'
NX_VEGA_ENV=DEVNET
CYPRESS_VEGA_ENV=DEVNET
NX_VEGA_REST=https://n04.d.vega.xyz/datanode/rest

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_ENV = 'MAINNET'
CYPRESS_VEGA_ENV = 'MAINNET'
NX_VEGA_REST = 'https://api.token.vega.xyz/'
NX_VEGA_ENV=MAINNET
CYPRESS_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_ENV = 'STAGNET 1'
CYPRESS_VEGA_ENV = 'STAGNET 1'
NX_VEGA_REST = 'https://n03.s.vega.xyz/datanode/rest'
NX_VEGA_ENV=STAGNET 1
CYPRESS_VEGA_ENV=STAGNET 1
NX_VEGA_REST=https://n03.s.vega.xyz/datanode/rest

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_ENV = 'STAGNET 2'
CYPRESS_VEGA_ENV = 'STAGNET 2'
NX_VEGA_REST = 'https://n01.stagnet2.vega.xyz/datanode/rest'
NX_VEGA_ENV=STAGNET 2
CYPRESS_VEGA_ENV=STAGNET 2
NX_VEGA_REST=https://n01.stagnet2.vega.xyz/datanode/rest

View File

@ -1,4 +1,4 @@
# App configuration variables
NX_VEGA_ENV = 'TESTNET'
CYPRESS_VEGA_ENV = 'TESTNET'
NX_VEGA_REST = 'https://lb.testnet.vega.xyz/datanode/rest'
NX_VEGA_ENV=TESTNET
CYPRESS_VEGA_ENV=TESTNET
NX_VEGA_REST=https://lb.testnet.vega.xyz/datanode/rest

View File

@ -1,3 +1,3 @@
# App configuration variables
NX_VEGA_ENV = 'MAINNET'
NX_VEGA_REST = 'https://api.token.vega.xyz/'
NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/

View File

@ -1,3 +1,3 @@
# App configuration variables
NX_VEGA_ENV = 'DEVNET'
NX_VEGA_REST = 'https://n04.d.vega.xyz/datanode/rest'
NX_VEGA_ENV=DEVNET
NX_VEGA_REST=https://n04.d.vega.xyz/datanode/rest

View File

@ -1,3 +1,3 @@
# App configuration variables. No overrides for default urls
NX_VEGA_ENV = 'MAINNET'
NX_VEGA_REST = 'https://api.token.vega.xyz/'
NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/

View File

@ -1,3 +1,3 @@
# App configuration variables
NX_VEGA_ENV = 'STAGNET1'
NX_VEGA_REST = 'https://n03.s.vega.xyz/datanode/rest'
NX_VEGA_ENV=STAGNET1;
NX_VEGA_REST=https://n03.s.vega.xyz/datanode/rest;

View File

@ -1,3 +1,3 @@
# App configuration variables
NX_VEGA_ENV = 'STAGNET2'
NX_VEGA_REST = 'https://n03.stagnet2.vega.xyz/datanode/rest'
NX_VEGA_REST=https://n01.stagnet2.vega.xyz/datanode/rest;
NX_VEGA_ENV=STAGNET2;

View File

@ -1,3 +1,3 @@
# App configuration variables
NX_VEGA_ENV = 'TESTNET'
NX_VEGA_REST = 'https://lb.testnet.vega.xyz/datanode/rest'
NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://lb.testnet.vega.xyz/datanode/rest

View File

@ -19,11 +19,11 @@ REACT_APP_DEPLOY_URL=$DEPLOY_URL
REACT_APP_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
# App configuration variables
NX_VEGA_ENV = "TESTNET"
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
NX_FAIRGROUND=false
#Test configuration variables

View File

@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV = "DEVNET"
NX_VEGA_URL = "https://n04.d.vega.xyz/query"
NX_VEGA_ENV=DEVNET
NX_VEGA_URL=https://n04.d.vega.xyz/query
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io

View File

@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV = "MAINNET"
NX_VEGA_URL = "https://api.token.vega.xyz/query"
NX_VEGA_ENV=MAINNET
NX_VEGA_URL=https://api.token.vega.xyz/query
NX_ETHEREUM_CHAIN_ID=1
NX_ETHEREUM_PROVIDER_URL = "https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://etherscan.io

View File

@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV = "STAGNET"
NX_VEGA_URL = "https://n03.s.vega.xyz/query"
NX_VEGA_ENV=STAGNET
NX_VEGA_URL=https://n03.s.vega.xyz/query
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io

View File

@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV = "STAGNET2"
NX_VEGA_URL = "https://n03.stagnet2.vega.xyz/query"
NX_VEGA_ENV=STAGNET2
NX_VEGA_URL=https://n03.stagnet2.vega.xyz/query
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io

View File

@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV = "TESTNET"
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io

View File

@ -19,11 +19,11 @@ REACT_APP_DEPLOY_URL=$DEPLOY_URL
REACT_APP_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
# App configuration variables
NX_VEGA_ENV = "TESTNET"
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
NX_FAIRGROUND=false
NX_IS_NEW_BRIDGE_CONTRACT=true
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET":"https://dev.token.vega.xyz","STAGNET2":"staging2.token.vega.xyz","TESTNET":"token.fairground.wtf","MAINNET":"token.vega.xyz"}'

View File

@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV = "DEVNET"
NX_VEGA_URL = "https://n04.d.vega.xyz/query"
NX_VEGA_ENV=DEVNET
NX_VEGA_URL=https://n04.d.vega.xyz/query
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET":"https://dev.token.vega.xyz","STAGNET2":"staging2.token.vega.xyz","TESTNET":"token.fairground.wtf","MAINNET":"token.vega.xyz"}'
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io

View File

@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV = "MAINNET"
NX_VEGA_URL = "https://api.token.vega.xyz/query"
NX_VEGA_ENV=MAINNET
NX_VEGA_URL=https://api.token.vega.xyz/query
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET":"https://dev.token.vega.xyz","STAGNET2":"staging2.token.vega.xyz","TESTNET":"token.fairground.wtf","MAINNET":"token.vega.xyz"}'
NX_ETHEREUM_CHAIN_ID=1
NX_ETHEREUM_PROVIDER_URL = "https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://etherscan.io

View File

@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV = "STAGNET"
NX_VEGA_URL = "https://n03.s.vega.xyz/query"
NX_VEGA_ENV=STAGNET
NX_VEGA_URL=https://n03.s.vega.xyz/query
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET":"https://dev.token.vega.xyz","STAGNET2":"staging2.token.vega.xyz","TESTNET":"token.fairground.wtf","MAINNET":"token.vega.xyz"}'
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io

View File

@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV = "STAGNET2"
NX_VEGA_URL = "https://n03.stagnet2.vega.xyz/query"
NX_VEGA_ENV=STAGNET2
NX_VEGA_URL=https://n03.stagnet2.vega.xyz/query
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET":"https://dev.token.vega.xyz","STAGNET2":"staging2.token.vega.xyz","TESTNET":"token.fairground.wtf","MAINNET":"token.vega.xyz"}'
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io

View File

@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV = "TESTNET"
NX_VEGA_URL = "https://lb.testnet.vega.xyz/query"
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://lb.testnet.vega.xyz/query
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET":"https://dev.token.vega.xyz","STAGNET2":"staging2.token.vega.xyz","TESTNET":"token.fairground.wtf","MAINNET":"token.vega.xyz"}'
NX_ETHEREUM_CHAIN_ID=3
NX_ETHEREUM_PROVIDER_URL = "https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8"
NX_ETHERSCAN_URL = "https://ropsten.etherscan.io"
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io

5
apps/token/index.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference types="react-scripts" />
interface Window {
_env_?: Record<string, string>;
}

View File

@ -1,6 +1,6 @@
import './i18n';
import React from 'react';
import { ApolloProvider } from '@apollo/client';
import React, { useMemo } from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { AppLoader } from './app-loader';
import { AppBanner } from './components/app-banner';
@ -15,18 +15,28 @@ import { AppStateProvider } from './contexts/app-state/app-state-provider';
import { ContractsProvider } from './contexts/contracts/contracts-provider';
import { AppRouter } from './routes';
import { Web3Provider } from '@vegaprotocol/web3';
import { Connectors } from './lib/web3-connectors';
import { VegaWalletDialogs } from './components/vega-wallet-dialogs';
import { VegaWalletProvider } from '@vegaprotocol/wallet';
import { EnvironmentProvider } from '@vegaprotocol/network-switcher';
import { client } from './lib/apollo-client';
import { createConnectors } from './lib/web3-connectors';
import { ApolloProvider } from '@apollo/client';
import { createClient } from './lib/apollo-client';
import {
EnvironmentProvider,
useEnvironment,
} from '@vegaprotocol/network-switcher';
function App() {
const AppContainer = () => {
const sideBar = React.useMemo(() => [<EthWallet />, <VegaWallet />], []);
const { ETHEREUM_PROVIDER_URL, ETHEREUM_CHAIN_ID, VEGA_URL } =
useEnvironment();
const Connectors = useMemo(
() => createConnectors(ETHEREUM_PROVIDER_URL, ETHEREUM_CHAIN_ID),
[ETHEREUM_CHAIN_ID, ETHEREUM_PROVIDER_URL]
);
const client = useMemo(() => createClient(VEGA_URL), [VEGA_URL]);
return (
<ApolloProvider client={client}>
<Router>
<EnvironmentProvider>
<AppStateProvider>
<Web3Provider connectors={Connectors}>
<Web3Connector>
@ -52,10 +62,17 @@ function App() {
</Web3Connector>
</Web3Provider>
</AppStateProvider>
</EnvironmentProvider>
</Router>
</ApolloProvider>
);
};
function App() {
return (
<EnvironmentProvider>
<AppContainer />
</EnvironmentProvider>
);
}
export default App;

View File

@ -0,0 +1 @@
window._env_ = {};

View File

@ -2,13 +2,12 @@ import { Link } from '@vegaprotocol/ui-toolkit';
import { Trans } from 'react-i18next';
import { Links } from '../../config';
import { ENV } from '../../config/env';
export const AppFooter = () => {
return (
<footer className="p-12 text-ui">
<p className="mb-8">
Version: {process.env['NX_COMMIT_REF'] || 'development'}
</p>
<p className="mb-8">Version: {ENV.commit || 'development'}</p>
<p>
<Trans
i18nKey="footerLinksText"

View File

@ -17,7 +17,7 @@ import type {
DelegationsVariables,
} from './__generated__/Delegations';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useEnvironment } from '@vegaprotocol/network-switcher';
import { useContracts } from '../../contexts/contracts/contracts-context';
const DELEGATIONS_QUERY = gql`
query Delegations($partyId: ID!) {
@ -60,7 +60,7 @@ const DELEGATIONS_QUERY = gql`
`;
export const usePollForDelegations = () => {
const { ADDRESSES } = useEnvironment();
const { token: vegaToken } = useContracts();
const { t } = useTranslation();
const { keypair } = useVegaWallet();
const client = useApolloClient();
@ -118,8 +118,7 @@ export const usePollForDelegations = () => {
.map((a) => {
const isVega =
a.asset.source.__typename === 'ERC20' &&
a.asset.source.contractAddress ===
ADDRESSES.vegaTokenAddress;
a.asset.source.contractAddress === vegaToken.address;
return {
isVega,
@ -228,7 +227,7 @@ export const usePollForDelegations = () => {
clearInterval(interval);
mounted = false;
};
}, [client, keypair?.pub, t, ADDRESSES.vegaTokenAddress]);
}, [client, keypair?.pub, t, vegaToken.address]);
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
};

View File

@ -1,13 +1,14 @@
import { useEnvironment } from '@vegaprotocol/network-switcher';
import { Button, Splash } from '@vegaprotocol/ui-toolkit';
import { Web3ConnectDialog } from '@vegaprotocol/web3';
import { useWeb3React } from '@web3-react/core';
import type { ReactElement } from 'react';
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useMemo } from 'react';
import {
AppStateActionType,
useAppState,
} from '../../contexts/app-state/app-state-context';
import { Connectors } from '../../lib/web3-connectors';
import { createConnectors } from '../../lib/web3-connectors';
interface Web3ConnectorProps {
children: ReactElement;
@ -15,13 +16,18 @@ interface Web3ConnectorProps {
export function Web3Connector({ children }: Web3ConnectorProps) {
const { appState, appDispatch } = useAppState();
const { ETHEREUM_PROVIDER_URL, ETHEREUM_CHAIN_ID } = useEnvironment();
const Connectors = useMemo(
() => createConnectors(ETHEREUM_PROVIDER_URL, ETHEREUM_CHAIN_ID),
[ETHEREUM_CHAIN_ID, ETHEREUM_PROVIDER_URL]
);
const setDialogOpen = useCallback(
(isOpen: boolean) => {
appDispatch({ type: AppStateActionType.SET_ETH_WALLET_OVERLAY, isOpen });
},
[appDispatch]
);
const appChainId = Number(process.env['NX_ETHEREUM_CHAIN_ID']);
const appChainId = Number(ETHEREUM_CHAIN_ID);
return (
<>
<Web3Content appChainId={appChainId} setDialogOpen={setDialogOpen}>

View File

@ -0,0 +1,29 @@
const windowOrDefault = (key: string) => {
if (window._env_ && window._env_[key]) {
return window._env_[key];
}
return process.env[key] || '';
};
const TRUTHY = ['1', 'true'];
export const ENV = {
// Environment
dsn: windowOrDefault('NX_SENTRY_DSN'),
envName: windowOrDefault('NX_VEGA_ENV'),
commit: windowOrDefault('NX_COMMIT_REF'),
branch: windowOrDefault('NX_BRANCH'),
vegaUrl: windowOrDefault('NX_VEGA_URL'),
flags: {
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
HOSTED_WALLET_ENABLED: TRUTHY.includes(
windowOrDefault('NX_HOSTED_WALLET_ENABLED')
),
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
FAIRGROUND: TRUTHY.includes(windowOrDefault('NX_FAIRGROUND')),
NETWORK_LIMITS: TRUTHY.includes(windowOrDefault('NX_NETWORK_LIMITS')),
USE_NEW_BRIDGE_CONTRACT: TRUTHY.includes(
process.env['NX_IS_NEW_BRIDGE_CONTRACT'] as string
),
},
};

View File

@ -1,14 +1,5 @@
const TRUTHY = ['1', 'true'];
import { ENV } from './env';
export const Flags = {
NETWORK_DOWN: TRUTHY.includes(process.env['NX_NETWORK_DOWN'] as string),
HOSTED_WALLET_ENABLED: TRUTHY.includes(
process.env['NX_HOSTED_WALLET_ENABLED'] as string
),
MOCK: TRUTHY.includes(process.env['NX_MOCKED'] as string),
FAIRGROUND: TRUTHY.includes(process.env['NX_FAIRGROUND'] as string),
NETWORK_LIMITS: TRUTHY.includes(process.env['NX_NETWORK_LIMITS'] as string),
USE_NEW_BRIDGE_CONTRACT: TRUTHY.includes(
process.env['NX_IS_NEW_BRIDGE_CONTRACT'] as string
),
...ENV.flags,
};

View File

@ -17,31 +17,6 @@ export type NetworkConfig = {
[N in Networks]: string[];
};
const splitFilter = (a: string) => a.split(',').filter((a) => a.length > 0);
const getCustomNodesFromOptionalEnvironmentVariables = () => {
const validatorUrls = process.env['CUSTOM_URLS'] || '';
const validatorUrlsWithGraphQL =
process.env['CUSTOM_URLS_WITH_GRAPHQL'] || '';
const validatorUrlsList: string[] = splitFilter(validatorUrls);
const validatorUrlsWithGraphQLList: string[] = splitFilter(
validatorUrlsWithGraphQL
);
const customNodes: VegaNode[] = validatorUrlsList
.map((a) => ({ url: a, api: { GraphQL: false } }))
.concat(
validatorUrlsWithGraphQLList.map((a) => ({
url: a,
api: { GraphQL: true },
}))
);
return customNodes;
};
const customNodes = getCustomNodesFromOptionalEnvironmentVariables();
export const VegaNetworks: VegaNets = {
[Networks.DEVNET]: {
nodes: [
@ -179,9 +154,6 @@ export const VegaNetworks: VegaNets = {
},
],
},
[Networks.CUSTOM]: {
nodes: customNodes,
},
[Networks.MAINNET]: {
nodes: [],
},

View File

@ -6,12 +6,12 @@ import {
} from '@vegaprotocol/smart-contracts';
import { Splash } from '@vegaprotocol/ui-toolkit';
import { useWeb3React } from '@web3-react/core';
import React from 'react';
import React, { useMemo } from 'react';
import { SplashLoader } from '../../components/splash-loader';
import type { ContractsContextShape } from './contracts-context';
import { ContractsContext } from './contracts-context';
import { defaultProvider } from '../../lib/web3-connectors';
import { createDefaultProvider } from '../../lib/web3-connectors';
import { useEthereumConfig } from '@vegaprotocol/web3';
import { useEnvironment } from '@vegaprotocol/network-switcher';
@ -21,14 +21,20 @@ import { useEnvironment } from '@vegaprotocol/network-switcher';
export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
const { provider: activeProvider, account } = useWeb3React();
const { config } = useEthereumConfig();
const { VEGA_ENV, ADDRESSES } = useEnvironment();
const { VEGA_ENV, ADDRESSES, ETHEREUM_PROVIDER_URL, ETHEREUM_CHAIN_ID } =
useEnvironment();
const [contracts, setContracts] =
React.useState<ContractsContextShape | null>(null);
const defaultProvider = useMemo(
() => createDefaultProvider(ETHEREUM_PROVIDER_URL, ETHEREUM_CHAIN_ID),
[ETHEREUM_PROVIDER_URL, ETHEREUM_CHAIN_ID]
);
// Create instances of contract classes. If we have an account use a signer for the
// contracts so that we can sign transactions, otherwise use the provider for just
// reading data
React.useEffect(() => {
const run = async () => {
let signer = null;
const provider = activeProvider ? activeProvider : defaultProvider;
@ -42,8 +48,14 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
}
if (provider && config) {
const staking = new StakingBridge(
config.staking_bridge_contract.address,
signer || provider
);
const vegaAddress = await staking.stakingToken();
setContracts({
token: new Token(ADDRESSES.vegaTokenAddress, signer || provider),
token: new Token(vegaAddress, signer || provider),
staking: new StakingBridge(
config.staking_bridge_contract.address,
signer || provider
@ -55,7 +67,9 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
claim: new Claim(ADDRESSES.claimAddress, signer || provider),
});
}
}, [activeProvider, account, config, ADDRESSES, VEGA_ENV]);
};
run();
}, [activeProvider, account, config, ADDRESSES, VEGA_ENV, defaultProvider]);
if (!contracts) {
return (

View File

@ -12,7 +12,6 @@ const TRANCHES_URLS: { [N in Networks]: string } = {
STAGNET: 'https://static.vega.xyz/assets/stagnet1-tranches.json',
STAGNET2: 'https://static.vega.xyz/assets/stagnet2-tranches.json',
DEVNET: 'https://static.vega.xyz/assets/devnet-tranches.json',
CUSTOM: '',
};
export function useTranches() {

View File

@ -25,6 +25,7 @@
crossorigin="anonymous"
/>
<title>Vega Token dApp</title>
<script src="./assets/env-config.js"></script>
</head>
<body class="h-full">
<noscript>You need to enable JavaScript to run this app.</noscript>

View File

@ -8,7 +8,6 @@ import uniqBy from 'lodash/uniqBy';
import { BigNumber } from './bignumber';
import { addDecimal } from './decimals';
import { deterministicShuffle } from './deterministic-shuffle';
import { getDataNodeUrl } from './get-data-node-url';
// Create seed in memory. Validator list order will remain the same
// until the page is refreshed.
@ -16,9 +15,10 @@ const VALIDATOR_RANDOMISER_SEED = (
Math.floor(Math.random() * 1000) + 1
).toString();
export function createClient() {
const { graphql } = getDataNodeUrl();
export function createClient(base?: string) {
if (!base) {
throw new Error('Base must be passed into createClient!');
}
const formatUintToNumber = (amount: string, decimals = 18) =>
addDecimal(new BigNumber(amount), decimals).toString();
@ -155,7 +155,7 @@ export function createClient() {
});
const httpLink = new HttpLink({
uri: graphql,
uri: base,
credentials: 'same-origin',
});
@ -172,5 +172,3 @@ export function createClient() {
cache,
});
}
export const client = createClient();

View File

@ -1,5 +1,7 @@
import { ENV } from '../config/env';
export function getDataNodeUrl() {
const base = process.env['NX_VEGA_URL'];
const base = ENV.vegaUrl;
if (!base) {
throw new Error('Environment variable NX_VEGA_URL must be set');
}

View File

@ -4,34 +4,30 @@ import { initializeConnector } from '@web3-react/core';
import { MetaMask } from '@web3-react/metamask';
import { WalletConnect } from '@web3-react/walletconnect';
export const [metamask, metamaskHooks] = initializeConnector<MetaMask>(
const [metamask, metamaskHooks] = initializeConnector<MetaMask>(
(actions) => new MetaMask(actions)
);
const CHAIN_ID = Number(process.env['NX_ETHEREUM_CHAIN_ID']);
const PROVIDER_URL = process.env['NX_ETHEREUM_PROVIDER_URL'] as string;
export const createDefaultProvider = (providerUrl: string, chainId: number) => {
return new ethers.providers.JsonRpcProvider(providerUrl, chainId);
};
if (isNaN(CHAIN_ID)) {
export const createConnectors = (providerUrl: string, chainId: number) => {
if (isNaN(chainId)) {
throw new Error('Invalid Ethereum chain ID for environment');
}
export const [walletconnect, walletconnectHooks] =
const [walletconnect, walletconnectHooks] =
initializeConnector<WalletConnect>(
(actions) =>
new WalletConnect(actions, {
rpc: {
[CHAIN_ID]: PROVIDER_URL,
[chainId]: providerUrl,
},
}),
[CHAIN_ID]
[chainId]
);
export const defaultProvider = new ethers.providers.JsonRpcProvider(
PROVIDER_URL,
CHAIN_ID
);
export const Connectors: [MetaMask | WalletConnect, Web3ReactHooks][] = [
return [
[metamask, metamaskHooks],
[walletconnect, walletconnectHooks],
];
] as [MetaMask | WalletConnect, Web3ReactHooks][];
};

View File

@ -7,11 +7,12 @@ import ReactDOM from 'react-dom';
import App from './app';
import reportWebVitals from './report-web-vitals';
import { ENV } from './config/env';
const dsn = process.env['NX_SENTRY_DSN'] || false;
const environment = process.env['NX_VEGA_ENV'] || 'local';
const commit = process.env['NX_COMMIT_REF'] || 'local';
const branch = process.env['NX_BRANCH'] || 'unknown';
const dsn = ENV.dsn || false;
const environment = ENV.envName || 'local';
const commit = ENV.commit || 'local';
const branch = ENV.branch || 'unknown';
/* istanbul ignore next */
if (dsn) {

View File

@ -145,7 +145,6 @@ export const VoteButtons = ({
{proposalState === ProposalState.Open ? (
<Button
variant="inline-link"
className="text-yellow"
onClick={() => {
setChangeVote(true);
}}

View File

@ -9,6 +9,7 @@ import { formatNumber } from '../../../lib/format-number';
import { TokenDetailsCirculating } from './token-details-circulating';
import { SplashLoader } from '../../../components/splash-loader';
import { useEthereumConfig } from '@vegaprotocol/web3';
import { useContracts } from '../../../contexts/contracts/contracts-context';
export const TokenDetails = ({
totalSupply,
@ -17,11 +18,12 @@ export const TokenDetails = ({
totalSupply: BigNumber;
totalStaked: BigNumber;
}) => {
const { ADDRESSES, ETHERSCAN_URL } = useEnvironment();
const { ETHERSCAN_URL } = useEnvironment();
const { t } = useTranslation();
const { tranches, loading, error } = useTranches();
const { config } = useEthereumConfig();
const { token } = useContracts();
if (error) {
return (
@ -47,10 +49,9 @@ export const TokenDetails = ({
data-testid="token-address"
title={t('View on Etherscan (opens in a new tab)')}
className="font-mono"
href={`${ETHERSCAN_URL}/address/${ADDRESSES.vegaTokenAddress}`}
target="_blank"
href={`${ETHERSCAN_URL}/address/${token.address}`}
>
{ADDRESSES.vegaTokenAddress}
{token.address}
</Link>
</KeyValueTableRow>
<KeyValueTableRow>

View File

@ -3,7 +3,6 @@ import { Trans, useTranslation } from 'react-i18next';
import { Link, useParams, useOutletContext } from 'react-router-dom';
import { TransactionCallout } from '../../../components/transaction-callout';
import { useEnvironment } from '@vegaprotocol/network-switcher';
import { useAppState } from '../../../contexts/app-state/app-state-context';
import { useContracts } from '../../../contexts/contracts/contracts-context';
import {
@ -25,7 +24,6 @@ export const RedeemFromTranche = () => {
address: string;
}>();
const { vesting } = useContracts();
const { ADDRESSES } = useEnvironment();
const { t } = useTranslation();
const {
appState: { lien, totalVestedBalance, trancheBalances, totalLockedBalance },
@ -44,6 +42,8 @@ export const RedeemFromTranche = () => {
perform,
dispatch: txDispatch,
} = useTransaction(() => vesting.withdrawFromTranche(numberId));
const { token } = useContracts();
const redeemedAmount = React.useMemo(() => {
return (
trancheBalances.find(({ id: bId }) => bId.toString() === id?.toString())
@ -111,7 +111,7 @@ export const RedeemFromTranche = () => {
{t(
'The VEGA token address is {{address}}, make sure you add this to your wallet to see your tokens',
{
address: ADDRESSES.vegaTokenAddress,
address: token.address,
}
)}
</p>

Some files were not shown because too many files have changed in this diff Show More