Compare commits

..
1167 changed files with 8822 additions and 16698 deletions
+2 -4
View File
@@ -18,11 +18,9 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Use Node.js 16 - uses: actions/setup-node@v3
id: Node
uses: actions/setup-node@v2
with: with:
node-version: 16.15.1 node-version: 16
- name: Run Cypress tests - name: Run Cypress tests
uses: cypress-io/github-action@v4 uses: cypress-io/github-action@v4
+1 -1
View File
@@ -11,7 +11,7 @@ on:
type: choice type: choice
options: options:
- explorer-e2e - explorer-e2e
- governance-e2e - token-e2e
- trading-e2e - trading-e2e
tags: tags:
description: 'Test tags to run' description: 'Test tags to run'
+1 -1
View File
@@ -10,5 +10,5 @@ jobs:
uses: ./.github/workflows/cypress-run.yml uses: ./.github/workflows/cypress-run.yml
secrets: inherit secrets: inherit
with: with:
projects: '["explorer-e2e","governance-e2e","trading-e2e"]' projects: '["explorer-e2e","token-e2e","trading-e2e"]'
tags: '@smoke @regression @slow' tags: '@smoke @regression @slow'
+2 -2
View File
@@ -42,10 +42,10 @@ jobs:
affected=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects) affected=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)
echo -n "Affected projects: $affected" echo -n "Affected projects: $affected"
projects="" projects=""
if [[ $affected == *"governance"* ]]; then projects+='"governance-e2e" '; fi if [[ $affected == *"token"* ]]; then projects+='"token-e2e" '; fi
if [[ $affected == *"trading"* ]]; then projects+='"trading-e2e" '; fi if [[ $affected == *"trading"* ]]; then projects+='"trading-e2e" '; fi
if [[ $affected == *"explorer"* ]]; then projects+='"explorer-e2e" '; fi if [[ $affected == *"explorer"* ]]; then projects+='"explorer-e2e" '; fi
if [[ -z "$projects" ]]; then projects+='"governance-e2e" "trading-e2e" "explorer-e2e" '; fi if [[ -z "$projects" ]]; then projects+='"token-e2e" "trading-e2e" "explorer-e2e" '; fi
projects=${projects%?} projects=${projects%?}
projects=[${projects// /,}] projects=[${projects// /,}]
echo PROJECTS=$projects >> $GITHUB_ENV echo PROJECTS=$projects >> $GITHUB_ENV
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
id: Node id: Node
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: 16.15.1 node-version: 16.14.0
- name: Install root dependencies - name: Install root dependencies
run: yarn install run: yarn install
- name: Generate queries - name: Generate queries
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
id: Node id: Node
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: 16.15.1 node-version: 16.14.0
- name: Install root dependencies - name: Install root dependencies
run: yarn install run: yarn install
- name: Check PR title - name: Check PR title
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
id: Node id: Node
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: 16.15.1 node-version: 16.14.0
- name: Install root dependencies - name: Install root dependencies
run: yarn install run: yarn install
- name: Generate queries - name: Generate queries
-49
View File
@@ -1,49 +0,0 @@
name: Publish libs to npm
on:
workflow_dispatch:
inputs:
project:
description: 'Monorepo project to publish'
required: true
type: choice
options:
- ui-toolkit
- react-helpers
- tailwindcss-config
- types
- utils
- i18n
jobs:
publish:
name: Build & Publish - Tag
runs-on: ubuntu-latest
permissions:
contents: 'read'
actions: 'read'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: User Node.js 16
id: Node
uses: actions/setup-node@v3
with:
node-version: 16.15.1
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }}
- name: Install root dependencies
run: yarn install --frozen-lockfile
- name: Build project
run: yarn nx build ${{inputs.project}}
- name: Publish project to @vegaprotocol
uses: JS-DevTools/npm-publish@v1
with:
token: ${{ secrets.NPM_TOKEN }}
package: dist/libs/${{inputs.project}}/package.json
access: public
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
id: Node id: Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16.15.1 node-version: 16.14.0
- name: Restore node_modules from cache - name: Restore node_modules from cache
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
+1 -1
View File
@@ -1 +1 @@
16.15.1 16.14.0
+1 -1
View File
@@ -161,7 +161,7 @@ In order to setup and run vegawallet for e2e capsule tests, in a separate termin
bash setup-vegawallet.sh bash setup-vegawallet.sh
``` ```
3. copy generated `api-token` and paste the token into `CYPRESS_VEGA_WALLET_API_TOKEN` environment variable in either `apps/governance-e2e/.env` or `apps/explorer-e2e/.env` depending on which project needs testing. 3. copy generated `api-token` and paste the token into `CYPRESS_VEGA_WALLET_API_TOKEN` environment variable in either `apps/token-e2e/.env` or `apps/explorer-e2e/.env` depending on which project needs testing.
Note: The script is only needed if capsule was built for first time or fresh. To run existing wallet service for capsule: Note: The script is only needed if capsule was built for first time or fresh. To run existing wallet service for capsule:
@@ -8,7 +8,7 @@ context('Asset page', { tags: '@regression' }, () => {
it('should be able to see full assets list', () => { it('should be able to see full assets list', () => {
cy.getAssets().then((assets) => { cy.getAssets().then((assets) => {
assets.forEach((asset) => { Object.values(assets).forEach((asset) => {
cy.get(`[row-id="${asset.id}"]`).should('be.visible'); cy.get(`[row-id="${asset.id}"]`).should('be.visible');
}); });
}); });
@@ -25,7 +25,7 @@ context('Asset page', { tags: '@regression' }, () => {
}); });
cy.getAssets().then((assets) => { cy.getAssets().then((assets) => {
assets.forEach((asset) => { Object.values(assets).forEach((asset) => {
cy.get(`[row-id="${asset.id}"]`).should('be.visible'); cy.get(`[row-id="${asset.id}"]`).should('be.visible');
}); });
}); });
@@ -33,7 +33,7 @@ context('Asset page', { tags: '@regression' }, () => {
it('should open details page when clicked on "View details"', () => { it('should open details page when clicked on "View details"', () => {
cy.getAssets().then((assets) => { cy.getAssets().then((assets) => {
assets.forEach((asset) => { Object.values(assets).forEach((asset) => {
cy.get(`[row-id="${asset.id}"] [col-id="actions"] button`) cy.get(`[row-id="${asset.id}"] [col-id="actions"] button`)
.eq(0) .eq(0)
.should('contain.text', 'View details'); .should('contain.text', 'View details');
@@ -1,15 +1,303 @@
context('Validator page', { tags: '@smoke' }, function () { context('Validator page', { tags: '@smoke' }, function () {
const validatorMenuHeading = 'a[href="/validators"]';
const tendermintDataHeader = '[data-testid="tendermint-header"]';
const vegaDataHeader = '[data-testid="vega-header"]';
const jsonSection = '.language-json';
before('Visit validators page and obtain data', function () { before('Visit validators page and obtain data', function () {
cy.visit('/validators'); cy.visit('/');
cy.get(validatorMenuHeading).click();
cy.get_validators().as('validators');
cy.get_nodes().as('nodes');
}); });
describe('Verify elements on page', function () { describe('Verify elements on page', function () {
it('should be able to see validator tiles', function () { before('Ensure at least two validators are present', function () {
cy.getNodes().then((nodes) => { assert.isAtLeast(
nodes.forEach((node) => { this.validators.length,
cy.get(`[validator-id="${node.id}"]`).should('be.visible'); 2,
'Ensuring at least two validators exist'
);
});
it('should be able to see validator page sections', function () {
cy.get(vegaDataHeader)
.contains('Vega data')
.and('is.visible')
.next()
.within(() => {
cy.get(jsonSection).should('not.be.empty');
});
cy.get(tendermintDataHeader)
.contains('Tendermint data')
.and('is.visible')
.next()
.within(() => {
cy.get(jsonSection).should('not.be.empty');
});
});
it('should be able to see relevant validator information in tendermint section', function () {
cy.get(tendermintDataHeader)
.contains('Tendermint data')
.next()
.within(() => {
cy.get(jsonSection)
.invoke('text')
.convert_string_json_to_js_object()
.then((validatorsInJson) => {
this.validators.forEach((validator, index) => {
const validatorInJson =
validatorsInJson.result.validators[index];
assert.equal(
validatorInJson.address,
validator.address,
`Checking that validator address shown in json matches system data`
);
cy.contains(validator.address).should('be.visible');
assert.equal(
validatorInJson.pub_key.type,
validator.pub_key.type,
`Checking that validator public key type shown in json matches system data`
);
cy.contains(validator.pub_key.type).should('be.visible');
assert.equal(
validatorInJson.pub_key.value,
validator.pub_key.value,
`Checking that validator public key value shown in json matches system data`
);
cy.contains(validator.pub_key.value).should('be.visible');
assert.equal(
validatorInJson.voting_power,
validator.voting_power,
`Checking that validator voting power in json matches system data`
);
cy.contains(validator.voting_power).should('be.visible');
// Proposer priority can change frequently mid test
// Therefore only checking the field name is present.
cy.contains('proposer_priority').should('be.visible');
});
});
});
});
// Test disabled 2022/11/15 during the 0.62.1 upgrade. The JSON structure changed, and
// this test failed. Rather than fix it, it will be replaced when the validator view displays
// something useful rather than just dumping out the JSON.
xit('should be able to see relevant node information in vega data section', function () {
cy.get(vegaDataHeader)
.contains('Vega data')
.next()
.within(() => {
cy.get(jsonSection)
.invoke('text')
.convert_string_json_to_js_object()
.then((nodesInJson) => {
this.nodes.forEach((node, index) => {
const nodeInJson = nodesInJson.edges[index].node;
// Vegacapsule shows no info or null for following fields:
// name, infoURL, avatarUrl, location, epoch data
// Therefore, these values remain unchecked.
assert.equal(
nodeInJson.__typename,
node.__typename,
`Checking that node __typename shown in json matches system data`
);
cy.contains(node.__typename).should('be.visible');
assert.equal(
nodeInJson.id,
node.id,
`Checking that node id shown in json matches system data`
);
cy.contains(node.id).should('be.visible');
assert.equal(
nodeInJson.pubkey,
node.pubkey,
`Checking that node pubkey shown in json matches system data`
);
cy.contains(node.pubkey).should('be.visible');
assert.equal(
nodeInJson.tmPubkey,
node.tmPubkey,
`Checking that node tmPubkey shown in json matches system data`
);
cy.contains(node.tmPubkey).should('be.visible');
assert.equal(
nodeInJson.ethereumAddress,
node.ethereumAddress,
`Checking that node ethereumAddress shown in json matches system data`
);
cy.contains(node.ethereumAddress).should('be.visible');
assert.equal(
nodeInJson.stakedByOperator,
node.stakedByOperator,
`Checking that node stakedByOperator value shown in json matches system data`
);
cy.contains(node.stakedByOperator).should('be.visible');
assert.equal(
nodeInJson.stakedByDelegates,
node.stakedByDelegates,
`Checking that node stakedByDelegates value shown in json matches system data`
);
cy.contains(node.stakedByDelegates).should('be.visible');
assert.equal(
nodeInJson.stakedTotal,
node.stakedTotal,
`Checking that node stakedTotal shown in json matches system data`
);
cy.contains(node.stakedTotal).should('be.visible');
assert.equal(
nodeInJson.pendingStake,
node.pendingStake,
`Checking that node pendingStake shown in json matches system data`
);
cy.contains(node.pendingStake).should('be.visible');
assert.equal(
nodeInJson.status,
node.status,
`Checking that node status shown in json matches system data`
);
cy.contains(node.status).should('be.visible');
});
});
});
});
it('should be able to see validator page displayed on mobile', function () {
cy.common_switch_to_mobile_and_click_toggle();
cy.get(validatorMenuHeading).click();
cy.get(vegaDataHeader)
.contains('Vega data')
.and('is.visible')
.next()
.within(() => {
cy.get(jsonSection).should('not.be.empty');
});
cy.get(tendermintDataHeader)
.contains('Tendermint data')
.and('is.visible')
.next()
.within(() => {
cy.get(jsonSection).should('not.be.empty');
});
cy.get(tendermintDataHeader)
.contains('Tendermint data')
.next()
.within(() => {
this.validators.forEach((validator) => {
cy.contains(validator.address).should('be.visible');
cy.contains(validator.pub_key.type).should('be.visible');
cy.contains(validator.pub_key.value).should('be.visible');
cy.contains(validator.voting_power).should('be.visible');
// Proposer priority can change frequently mid test
// Therefore only checking the field name is present.
cy.contains('proposer_priority').should('be.visible');
});
});
});
it('should be able to switch validator page between light and dark mode', function () {
const whiteThemeSelectedMenuOptionColor = 'rgb(255, 7, 127)';
const whiteThemeJsonFieldBackColor = 'rgb(255, 255, 255)';
const whiteThemeSideMenuBackgroundColor = 'rgb(255, 255, 255)';
const darkThemeSelectedMenuOptionColor = 'rgb(215, 251, 80)';
const darkThemeJsonFieldBackColor = 'rgb(38, 38, 38)';
const darkThemeSideMenuBackgroundColor = 'rgb(0, 0, 0)';
const themeSwitcher = '[data-testid="theme-switcher"]';
const jsonFields = '.hljs';
const sideMenuBackground = '.absolute';
// Engage dark mode if not allready set
cy.get(sideMenuBackground)
.should('have.css', 'background-color')
.then((background_color) => {
if (background_color.includes(whiteThemeSideMenuBackgroundColor))
cy.get(themeSwitcher).click();
});
// Engage white mode
cy.get(themeSwitcher).click();
// White Mode
cy.get(validatorMenuHeading)
.should('have.css', 'background-color')
.and('include', whiteThemeSelectedMenuOptionColor);
cy.get(jsonFields)
.should('have.css', 'background-color')
.and('include', whiteThemeJsonFieldBackColor);
cy.get(sideMenuBackground)
.should('have.css', 'background-color')
.and('include', whiteThemeSideMenuBackgroundColor);
// Dark Mode
cy.get(themeSwitcher).click();
cy.get(validatorMenuHeading)
.should('have.css', 'background-color')
.and('include', darkThemeSelectedMenuOptionColor);
cy.get(jsonFields)
.should('have.css', 'background-color')
.and('include', darkThemeJsonFieldBackColor);
cy.get(sideMenuBackground)
.should('have.css', 'background-color')
.and('include', darkThemeSideMenuBackgroundColor);
});
Cypress.Commands.add('get_validators', () => {
cy.request({
method: 'GET',
url: `http://localhost:26617/validators`,
headers: { 'content-type': 'application/json' },
})
.its(`body.result.validators`)
.then(function (response) {
let validators = [];
response.forEach((account, index) => {
validators[index] = account;
});
return validators;
});
});
Cypress.Commands.add('get_nodes', () => {
const mutation =
'{nodesConnection { edges { node { id name infoUrl avatarUrl pubkey tmPubkey ethereumAddress \
location stakedByOperator stakedByDelegates stakedTotal pendingStake \
epochData { total offline online __typename } status name __typename}}}}';
cy.request({
method: 'POST',
url: `http://localhost:3028/query`,
body: {
query: mutation,
},
headers: { 'content-type': 'application/json' },
})
.its(`body.data.nodesConnection.edges`)
.then(function (response) {
let nodes = [];
response.forEach((node) => {
nodes.push(node);
});
return nodes;
}); });
});
}); });
}); });
}); });
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables # App configuration variables
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/tm NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.devnet1.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"} NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=DEVNET NX_VEGA_ENV=DEVNET
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables # App configuration variables
NX_TENDERMINT_URL=https://be.explorer.vega.xyz NX_TENDERMINT_URL=https://be.explorer.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.explorer.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://be.explorer.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"} NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=MAINNET NX_VEGA_ENV=MAINNET
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables # App configuration variables
NX_TENDERMINT_URL=https://tm.be.mainnet-mirror.vega.xyz NX_TENDERMINT_URL=https://tm.be.mainnet-mirror.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=https://tm.be.mainnet-mirror.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mirror-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mirror-network.json
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_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_VEGA_ENV=MIRROR NX_VEGA_ENV=MIRROR
+1 -1
View File
@@ -7,6 +7,6 @@ NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"} NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_TENDERMINT_URL=https://tm.sandbox.vega.xyz NX_TENDERMINT_URL=https://tm.sandbox.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.sandbox.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://tm.sandbox.vega.xyz/websocket
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz
+1 -1
View File
@@ -1,5 +1,5 @@
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.stagnet3.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"} NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=STAGNET3 NX_VEGA_ENV=STAGNET3
+1 -1
View File
@@ -1,7 +1,7 @@
# App configuration variables # App configuration variables
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.testnet.vega.xyz/websocket/
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"} NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=TESTNET NX_VEGA_ENV=TESTNET
-14
View File
@@ -1,14 +0,0 @@
# 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/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
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.xyz
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.xyz/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
-5
View File
@@ -1,5 +0,0 @@
function ReactMarkdown({ children }) {
return <div>{children}</div>;
}
export default ReactMarkdown;
+2 -2
View File
@@ -40,9 +40,9 @@ function App() {
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}> <NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
<AnnouncementBanner> <AnnouncementBanner>
<div className="font-alpha calt uppercase text-center text-lg text-white"> <div className="font-alpha calt uppercase text-center text-lg text-white">
<span className="pr-4">Mainnet sim 2 is live!</span> <span className="pr-4">Mainnet sim 2 coming in March!</span>
<ExternalLink href="https://fairground.wtf/"> <ExternalLink href="https://fairground.wtf/">
Come help stress test the network Learn more
</ExternalLink> </ExternalLink>
</div> </div>
</AnnouncementBanner> </AnnouncementBanner>
@@ -1,5 +1,5 @@
import { useAssetDataProvider } from '@vegaprotocol/assets'; import { useAssetDataProvider } from '@vegaprotocol/assets';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; import { addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
import { AssetLink } from '../links'; import { AssetLink } from '../links';
export type AssetBalanceProps = { export type AssetBalanceProps = {
@@ -1,4 +1,4 @@
import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; import { addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
import { useExplorerGovernanceAssetQuery } from './__generated__/Governance-asset'; import { useExplorerGovernanceAssetQuery } from './__generated__/Governance-asset';
import AssetBalance from './asset-balance'; import AssetBalance from './asset-balance';
@@ -1,11 +1,11 @@
import type { AssetFieldsFragment } from '@vegaprotocol/assets'; import type { AssetFieldsFragment } from '@vegaprotocol/assets';
import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets'; import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { VegaICellRendererParams } from '@vegaprotocol/ui-toolkit';
import { ButtonLink } from '@vegaprotocol/ui-toolkit'; import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react'; import { AgGridColumn } from 'ag-grid-react';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid'; import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
import { useRef, useLayoutEffect } from 'react'; import { useRef, useLayoutEffect } from 'react';
import { BREAKPOINT_MD } from '../../config/breakpoints'; import { BREAKPOINT_MD } from '../../config/breakpoints';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@@ -2,11 +2,11 @@ import React from 'react';
import type { BlockMeta } from '../../routes/blocks/tendermint-blockchain-response'; import type { BlockMeta } from '../../routes/blocks/tendermint-blockchain-response';
import { Routes } from '../../routes/route-names'; import { Routes } from '../../routes/route-names';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { getDateTimeFormat } from '@vegaprotocol/utils'; import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
import { Tooltip } from '@vegaprotocol/ui-toolkit'; import { Tooltip } from '@vegaprotocol/ui-toolkit';
import { TimeAgo } from '../time-ago'; import { TimeAgo } from '../time-ago';
import { TableWithTbody, TableRow, TableCell } from '../table'; import { TableWithTbody, TableRow, TableCell } from '../table';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
interface BlockProps { interface BlockProps {
block: BlockMeta; block: BlockMeta;
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import React from 'react'; import React from 'react';
import type { TendermintBlockchainResponse } from '../../routes/blocks/tendermint-blockchain-response'; import type { TendermintBlockchainResponse } from '../../routes/blocks/tendermint-blockchain-response';
import { BlockData } from './block-data'; import { BlockData } from './block-data';
@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { FixedSizeList as List } from 'react-window'; import { FixedSizeList as List } from 'react-window';
import InfiniteLoader from 'react-window-infinite-loader'; import InfiniteLoader from 'react-window-infinite-loader';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { BlockMeta } from '../../routes/blocks/tendermint-blockchain-response'; import type { BlockMeta } from '../../routes/blocks/tendermint-blockchain-response';
import { BlockData } from './block-data'; import { BlockData } from './block-data';
import EmptyList from '../empty-list/empty-list'; import EmptyList from '../empty-list/empty-list';
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { useTendermintWebsocket } from '../../hooks/use-tendermint-websocket'; import { useTendermintWebsocket } from '../../hooks/use-tendermint-websocket';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { ButtonLink } from '@vegaprotocol/ui-toolkit'; import { ButtonLink } from '@vegaprotocol/ui-toolkit';
interface BlocksRefetchProps { interface BlocksRefetchProps {
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { import {
Button, Button,
Dialog, Dialog,
@@ -19,12 +19,12 @@ const EmptyList = ({ heading, label }: EmptyListProps) => {
<div className="mt-4"> <div className="mt-4">
{heading ? ( {heading ? (
<h1 className="font-alpha calt text-xl uppercase text-center leading-relaxed"> <h1 className="font-alpha text-xl uppercase text-center leading-relaxed">
{heading} {heading}
</h1> </h1>
) : null} ) : null}
{label ? ( {label ? (
<p className="font-alpha calt text-gray-500 text-center">{label}</p> <p className="font-alpha text-gray-500 text-center">{label}</p>
) : null} ) : null}
</div> </div>
</div> </div>
@@ -1,24 +0,0 @@
query ExplorerEpoch($id: ID!) {
epoch(id: $id) {
id
timestamps {
start
end
firstBlock
lastBlock
}
}
}
query ExplorerFutureEpoch {
networkParameter(key: "validators.epoch.length") {
value
}
epoch {
id
timestamps {
start
}
}
}
@@ -1,99 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ExplorerEpochQueryVariables = Types.Exact<{
id: Types.Scalars['ID'];
}>;
export type ExplorerEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, firstBlock: string, lastBlock?: string | null } } };
export type ExplorerFutureEpochQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ExplorerFutureEpochQuery = { __typename?: 'Query', networkParameter?: { __typename?: 'NetworkParameter', value: string } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null } } };
export const ExplorerEpochDocument = gql`
query ExplorerEpoch($id: ID!) {
epoch(id: $id) {
id
timestamps {
start
end
firstBlock
lastBlock
}
}
}
`;
/**
* __useExplorerEpochQuery__
*
* To run a query within a React component, call `useExplorerEpochQuery` and pass it any options that fit your needs.
* When your component renders, `useExplorerEpochQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useExplorerEpochQuery({
* variables: {
* id: // value for 'id'
* },
* });
*/
export function useExplorerEpochQuery(baseOptions: Apollo.QueryHookOptions<ExplorerEpochQuery, ExplorerEpochQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ExplorerEpochQuery, ExplorerEpochQueryVariables>(ExplorerEpochDocument, options);
}
export function useExplorerEpochLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerEpochQuery, ExplorerEpochQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ExplorerEpochQuery, ExplorerEpochQueryVariables>(ExplorerEpochDocument, options);
}
export type ExplorerEpochQueryHookResult = ReturnType<typeof useExplorerEpochQuery>;
export type ExplorerEpochLazyQueryHookResult = ReturnType<typeof useExplorerEpochLazyQuery>;
export type ExplorerEpochQueryResult = Apollo.QueryResult<ExplorerEpochQuery, ExplorerEpochQueryVariables>;
export const ExplorerFutureEpochDocument = gql`
query ExplorerFutureEpoch {
networkParameter(key: "validators.epoch.length") {
value
}
epoch {
id
timestamps {
start
}
}
}
`;
/**
* __useExplorerFutureEpochQuery__
*
* To run a query within a React component, call `useExplorerFutureEpochQuery` and pass it any options that fit your needs.
* When your component renders, `useExplorerFutureEpochQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useExplorerFutureEpochQuery({
* variables: {
* },
* });
*/
export function useExplorerFutureEpochQuery(baseOptions?: Apollo.QueryHookOptions<ExplorerFutureEpochQuery, ExplorerFutureEpochQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ExplorerFutureEpochQuery, ExplorerFutureEpochQueryVariables>(ExplorerFutureEpochDocument, options);
}
export function useExplorerFutureEpochLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerFutureEpochQuery, ExplorerFutureEpochQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ExplorerFutureEpochQuery, ExplorerFutureEpochQueryVariables>(ExplorerFutureEpochDocument, options);
}
export type ExplorerFutureEpochQueryHookResult = ReturnType<typeof useExplorerFutureEpochQuery>;
export type ExplorerFutureEpochLazyQueryHookResult = ReturnType<typeof useExplorerFutureEpochLazyQuery>;
export type ExplorerFutureEpochQueryResult = Apollo.QueryResult<ExplorerFutureEpochQuery, ExplorerFutureEpochQueryVariables>;
@@ -1,56 +0,0 @@
import { render } from '@testing-library/react';
import { IconForEpoch } from './epoch';
const THE_PAST = 'Monday, 17 February 2022 11:44:09';
const THE_FUTURE = 'Monday, 17 February 3023 11:44:09';
describe('IconForEpoch', () => {
it('Handles malformed dates', () => {
const start = 'This is n0t a d4te';
const end = '📅';
const screen = render(<IconForEpoch start={start} end={end} />);
expect(screen.getByRole('img')).toHaveAttribute(
'aria-label',
'calendar icon'
);
});
it('defaults to a calendar icon', () => {
const start = null as unknown as string;
const end = null as unknown as string;
const screen = render(<IconForEpoch start={start} end={end} />);
expect(screen.getByRole('img')).toHaveAttribute(
'aria-label',
'calendar icon'
);
});
it('if start and end are both in the future, stick with calendar', () => {
const screen = render(<IconForEpoch start={THE_FUTURE} end={THE_FUTURE} />);
expect(screen.getByRole('img')).toHaveAttribute(
'aria-label',
'calendar icon'
);
});
it('if start is in the past and end is in the future, this is currently active', () => {
const screen = render(<IconForEpoch start={THE_PAST} end={THE_FUTURE} />);
expect(screen.getByRole('img')).toHaveAttribute(
'aria-label',
'circle icon'
);
});
it('if start and end are in the paste, this is done', () => {
const screen = render(<IconForEpoch start={THE_PAST} end={THE_PAST} />);
expect(screen.getByRole('img')).toHaveAttribute(
'aria-label',
'tick-circle icon'
);
});
});
@@ -1,125 +0,0 @@
import { MockedProvider } from '@apollo/client/testing';
import { render } from '@testing-library/react';
import EpochMissingOverview, { calculateEpochData } from './epoch-missing';
import { getSecondsFromInterval } from '@vegaprotocol/utils';
const START_DATE_PAST = 'Monday, 17 February 2022 11:44:09';
describe('getSecondsFromInterval', () => {
it('returns 0 for bad data', () => {
expect(getSecondsFromInterval(null as unknown as string)).toEqual(0);
expect(getSecondsFromInterval('')).toEqual(0);
expect(getSecondsFromInterval('🧙')).toEqual(0);
expect(getSecondsFromInterval(2 as unknown as string)).toEqual(0);
});
it('parses out months from a capital M', () => {
expect(getSecondsFromInterval('2M')).toEqual(5184000);
});
it('parses out days from a capital D', () => {
expect(getSecondsFromInterval('1D')).toEqual(86400);
});
it('parses out hours from a lower case h', () => {
expect(getSecondsFromInterval('11h')).toEqual(39600);
});
it('parses out minutes from a lower case m', () => {
expect(getSecondsFromInterval('10m')).toEqual(600);
});
it('parses out seconds from a lower case s', () => {
expect(getSecondsFromInterval('99s')).toEqual(99);
});
it('parses complex examples', () => {
expect(getSecondsFromInterval('24h')).toEqual(86400);
expect(getSecondsFromInterval('1h30m')).toEqual(5400);
expect(getSecondsFromInterval('1D1h30m1s')).toEqual(91801);
});
});
describe('calculateEpochData', () => {
it('Handles bad data', () => {
const currentEpochId = null as unknown as string;
const missingEpochId = null as unknown as string;
const epochStart = null as unknown as string;
const epochLength = null as unknown as string;
const res = calculateEpochData(
currentEpochId,
missingEpochId,
epochStart,
epochLength
);
expect(res).toHaveProperty('label', 'Missing data');
expect(res).toHaveProperty('isInFuture', false);
});
it('Calculates that a bigger epoch number is in the future from basic data', () => {
const currentEpochId = '10';
const missingEpochId = '20';
const epochStart = '';
const epochLength = '';
const res = calculateEpochData(
currentEpochId,
missingEpochId,
epochStart,
epochLength
);
expect(res).toHaveProperty('isInFuture', true);
});
it('If it has an epoch length and a start time, it provides an estimate', () => {
const currentEpochId = '10';
const missingEpochId = '20';
const epochStart = START_DATE_PAST;
const epochLength = '1s';
const res = calculateEpochData(
currentEpochId,
missingEpochId,
epochStart,
epochLength
);
// 'Estimate: 17/02/2022, 11:44:19 - in less than a minute')
expect(res).toHaveProperty('label');
expect(res.label).toMatch(/^Estimate/);
expect(res.label).toMatch(/in less than a minute$/);
});
it('Provide decent string for past', () => {
const currentEpochId = '20';
const missingEpochId = '10';
const epochStart = START_DATE_PAST;
const epochLength = '1s';
const res = calculateEpochData(
currentEpochId,
missingEpochId,
epochStart,
epochLength
);
// 'Estimate: 17/02/2022, 11:44:19 - in less than a minute')
expect(res).toHaveProperty('label');
expect(res.label).toMatch(/^Estimate/);
expect(res.label).toMatch(/less than a minute ago$/);
});
});
describe('EpochMissingOverview', () => {
function renderComponent(missingEpochId: string) {
return render(
<MockedProvider>
<EpochMissingOverview missingEpochId={missingEpochId} />
</MockedProvider>
);
}
it('renders a - if no id is provided', () => {
const n = null as unknown as string;
const screen = renderComponent(n);
expect(screen.getByTestId('empty')).toBeInTheDocument();
});
});
@@ -1,110 +0,0 @@
import { useExplorerFutureEpochQuery } from './__generated__/Epoch';
import addSeconds from 'date-fns/addSeconds';
import formatDistance from 'date-fns/formatDistance';
import { Icon, Tooltip } from '@vegaprotocol/ui-toolkit';
import isFuture from 'date-fns/isFuture';
import { getSecondsFromInterval, isValidDate } from '@vegaprotocol/utils';
export type EpochMissingOverviewProps = {
missingEpochId?: string;
};
/**
* Renders a set of details for an epoch that has no representation in the
* data node. This is primarily for one of two reasons:
*
* 1. The epoch hasn't happened yet
* 2. The epoch happened before a snapshot, and thus the details don't exist
*
* This component is used when the API has responded with no data for an epoch
* by ID, so we already know that we can't display start time/block etc.
*
* We can detect 1 if the epoch is a higher number than the current epoch
* We can detect 2 if the epoch is in the past, but we still get no response.
*/
const EpochMissingOverview = ({
missingEpochId,
}: EpochMissingOverviewProps) => {
const { data, error, loading } = useExplorerFutureEpochQuery();
// This should not happen, but it's easily handled
if (!missingEpochId) {
return <span data-testid="empty">-</span>;
}
// No data should also not happen - we've requested the current epoch. This
// could happen at chain restart, but shouldn't. If it does, fallback.
if (!data || loading || error) {
return <span data-testid="empty">{missingEpochId}</span>;
}
// If we have enough information to predict a future or past block time, let's do it
if (
!missingEpochId ||
!data.epoch.id ||
!data.epoch.timestamps.start ||
!data?.networkParameter?.value
) {
return <span data-testid="empty">{missingEpochId}</span>;
}
const { label, isInFuture } = calculateEpochData(
data.epoch.id,
missingEpochId,
data.epoch.timestamps.start,
data.networkParameter.value
);
return (
<Tooltip description={<p className="text-xs m-2">{label}</p>}>
<p>
{isInFuture ? (
<Icon name="calendar" className="mr-1" />
) : (
<Icon name="outdated" className="mr-1" />
)}
{missingEpochId}
</p>
</Tooltip>
);
};
export function calculateEpochData(
currentEpochId: string,
missingEpochId: string,
epochStart: string,
epochLength: string
) {
// Blank string will be return 0 seconds from getSecondsFromInterval
const epochLengthInSeconds = getSecondsFromInterval(epochLength);
if (!epochStart || !epochLength) {
// Let's just take a guess
return {
label: 'Missing data',
isInFuture: parseInt(missingEpochId) > parseInt(currentEpochId),
};
}
const startFrom = new Date(epochStart);
const diff = parseInt(missingEpochId) - parseInt(currentEpochId);
const futureDate = addSeconds(startFrom, diff * epochLengthInSeconds);
const label =
isValidDate(futureDate) && isValidDate(startFrom)
? `Estimate: ${futureDate.toLocaleString()} - ${formatDistance(
futureDate,
startFrom,
{ addSuffix: true }
)}`
: 'Missing data';
return {
label,
isInFuture: isFuture(futureDate),
};
}
export default EpochMissingOverview;
@@ -1,127 +0,0 @@
import { useExplorerEpochQuery } from './__generated__/Epoch';
import { t } from '@vegaprotocol/i18n';
import { BlockLink } from '../links';
import { Time } from '../time';
import { TimeAgo } from '../time-ago';
import EpochMissingOverview from './epoch-missing';
import { Icon, Tooltip } from '@vegaprotocol/ui-toolkit';
import type { IconProps } from '@vegaprotocol/ui-toolkit';
import isPast from 'date-fns/isPast';
const borderClass =
'border-solid border-2 border-vega-dark-200 border-collapse';
export type EpochOverviewProps = {
id?: string;
};
/**
* Displays detailed information about an epoch, given an ID. This
* works for past epochs and current epochs - future epochs, and a
* few other situations (see epoch-missing) will not return us
* enough information to render this.
*
* The details are hidden in a tooltip, behind the epoch number
*/
const EpochOverview = ({ id }: EpochOverviewProps) => {
const { data, error, loading } = useExplorerEpochQuery({
variables: { id: id || '' },
});
const ti = data?.epoch.timestamps;
if (
error?.message &&
error.message.includes('no resource corresponding to this id')
) {
return <EpochMissingOverview missingEpochId={id} />;
}
if (!ti || loading || error) {
return <span>{id}</span>;
}
const description = (
<table className="text-xs m-2">
<thead>
<tr>
<th></th>
<th className={`text-center ${borderClass}`}>{t('Block')}</th>
<th className={`text-center ${borderClass}`}>{t('Time')}</th>
</tr>
</thead>
<tbody>
<tr>
<th className={`px-2 ${borderClass}`}>{t('Start')}</th>
<td className={`px-2 ${borderClass}`}>
{ti.firstBlock ? <BlockLink height={ti.firstBlock} /> : '-'}
</td>
<td className={`px-2 ${borderClass}`}>
<Time date={ti.start} />
<br />
<TimeAgo date={ti.start} />
</td>
</tr>
<tr>
<th className={`px-2 ${borderClass}`}>{t('End')}</th>
<td className={`px-2 ${borderClass}`}>
{ti.lastBlock ? (
<BlockLink height={ti.lastBlock} />
) : (
t('In progress')
)}
</td>
<td className={`px-2 ${borderClass}`}>
{ti.end ? (
<>
<Time date={ti.end} />
<br />
<TimeAgo date={ti.end} />
</>
) : (
<span>{t('-')}</span>
)}
</td>
</tr>
</tbody>
</table>
);
return (
<Tooltip description={description}>
<p>
<IconForEpoch start={ti.start} end={ti.end} />
{id}
</p>
</Tooltip>
);
};
export type IconForEpochProps = {
start: string;
end: string;
};
/**
* Chooses an icon to display next to the epoch number, representing
* when the epoch is relative to now (i.e. not yet started, started,
* finished)
*/
export function IconForEpoch({ start, end }: IconForEpochProps) {
const startHasPassed = start ? isPast(new Date(start)) : false;
const endHasPassed = end ? isPast(new Date(end)) : false;
let i: IconProps['name'] = 'calendar';
if (!startHasPassed && !endHasPassed) {
i = 'calendar';
} else if (startHasPassed && !endHasPassed) {
i = 'circle';
} else if (startHasPassed && endHasPassed) {
i = 'tick-circle';
}
return <Icon name={i} className="mr-2" />;
}
export default EpochOverview;
@@ -1,6 +1,5 @@
import { NodeSwitcherDialog, useEnvironment } from '@vegaprotocol/environment'; import { NodeSwitcherDialog, useEnvironment } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n'; import { t, useScreenDimensions } from '@vegaprotocol/react-helpers';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import { ExternalLink, Link } from '@vegaprotocol/ui-toolkit'; import { ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { ENV } from '../../config/env'; import { ENV } from '../../config/env';
@@ -1,7 +1,7 @@
import classnames from 'classnames'; import classnames from 'classnames';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { ThemeSwitcher, Icon } from '@vegaprotocol/ui-toolkit'; import { ThemeSwitcher, Icon } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { Search } from '../search'; import { Search } from '../search';
import { Routes } from '../../routes/route-names'; import { Routes } from '../../routes/route-names';
import { NetworkSwitcher } from '@vegaprotocol/environment'; import { NetworkSwitcher } from '@vegaprotocol/environment';
@@ -11,14 +11,14 @@ export const InfoBlock = ({ title, subtitle, tooltipInfo }: InfoBlockProps) => {
return ( return (
<div className="flex flex-col text-center "> <div className="flex flex-col text-center ">
<h3 className="text-4xl">{title}</h3> <h3 className="text-4xl">{title}</h3>
<p className="text-vega-dark-100 dark:text-vega-light-200"> <p className="text-zinc-800 dark:text-zinc-300">
{subtitle} {subtitle}
{tooltipInfo ? ( {tooltipInfo ? (
<Tooltip description={tooltipInfo} align="center"> <Tooltip description={tooltipInfo} align="center">
<span> <span>
<Icon <Icon
name="info-sign" name="info-sign"
className="ml-2 text-vega-light-300 dark:text-vega-dark-300" className="ml-2 text-zinc-400 dark:text-zinc-600"
/> />
</span> </span>
</Tooltip> </Tooltip>
@@ -44,12 +44,12 @@ export const InfoPanel = ({
text={id} text={id}
startChars={visibleChars} startChars={visibleChars}
endChars={visibleChars} endChars={visibleChars}
className="text-vega-dark-100 dark:text-vega-light-200" className="text-black dark:text-zinc-200"
/> />
) : ( ) : (
<p <p
title={id} title={id}
className="text-vega-dark-100 dark:text-vega-light-200 truncate ..." className="text-black dark:text-zinc-200 truncate ..."
> >
{id} {id}
</p> </p>
@@ -70,7 +70,7 @@ export const InfoPanel = ({
</div> </div>
{copy && ( {copy && (
<CopyWithTooltip text={id}> <CopyWithTooltip text={id}>
<button className="bg-vega-light-100 dark:bg-vega-dark-100 rounded-sm py-2 px-3"> <button className="bg-zinc-100 dark:bg-zinc-900 rounded-sm py-2 px-3">
<Icon name="duplicate" /> <Icon name="duplicate" />
</button> </button>
</CopyWithTooltip> </CopyWithTooltip>
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import React from 'react'; import React from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Routes } from '../../routes/route-names'; import { Routes } from '../../routes/route-names';
@@ -1,6 +1,6 @@
import type { HTMLInputTypeAttribute, SyntheticEvent } from 'react'; import type { HTMLInputTypeAttribute, SyntheticEvent } from 'react';
import { Input, Button } from '@vegaprotocol/ui-toolkit'; import { Input, Button } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
interface JumpToProps { interface JumpToProps {
label: string; label: string;
@@ -11,7 +11,6 @@ import { Routes } from '../../../routes/route-names';
export type AssetLinkProps = Partial<ComponentProps<typeof ButtonLink>> & { export type AssetLinkProps = Partial<ComponentProps<typeof ButtonLink>> & {
assetId: string; assetId: string;
asDialog?: boolean; asDialog?: boolean;
showAssetSymbol?: boolean;
}; };
/** /**
@@ -19,22 +18,12 @@ export type AssetLinkProps = Partial<ComponentProps<typeof ButtonLink>> & {
* with a link to the assets modal. If the name does not come back * with a link to the assets modal. If the name does not come back
* it will use the ID instead. * it will use the ID instead.
*/ */
export const AssetLink = ({ export const AssetLink = ({ assetId, asDialog, ...props }: AssetLinkProps) => {
assetId,
asDialog,
showAssetSymbol = false,
...props
}: AssetLinkProps) => {
const { data: asset } = useAssetDataProvider(assetId); const { data: asset } = useAssetDataProvider(assetId);
const open = useAssetDetailsDialogStore((state) => state.open); const open = useAssetDetailsDialogStore((state) => state.open);
const navigate = useNavigate(); const navigate = useNavigate();
const label = asset const label = asset?.name ? asset.name : assetId;
? showAssetSymbol
? asset?.symbol
: asset?.name
: assetId;
return ( return (
<ButtonLink <ButtonLink
data-testid="asset-link" data-testid="asset-link"
@@ -3,7 +3,7 @@ import { useExplorerMarketQuery } from './__generated__/Market';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import type { ComponentProps } from 'react'; import type { ComponentProps } from 'react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import Hash from '../hash'; import Hash from '../hash';
export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & { export type MarketLinkProps = Partial<ComponentProps<typeof Link>> & {
@@ -48,7 +48,7 @@ const MarketLink = ({
<Link <Link
className="underline" className="underline"
{...props} {...props}
to={`/${Routes.MARKETS}/${id}`} to={`/${Routes.MARKETS}#${id}`}
title={id} title={id}
> >
{label} {label}
@@ -56,7 +56,7 @@ const MarketLink = ({
); );
} else { } else {
return ( return (
<Link className="underline" {...props} to={`/${Routes.MARKETS}/${id}`}> <Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
<Hash text={id} /> <Hash text={id} />
</Link> </Link>
); );
@@ -1,39 +0,0 @@
import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import PartyLink from './party-link';
describe('PartyLink', () => {
it('renders Network for 000.000 party', () => {
const zeroes =
'0000000000000000000000000000000000000000000000000000000000000000';
const screen = render(<PartyLink id={zeroes} />);
expect(screen.getByText('Network')).toBeInTheDocument();
});
it('renders Network for network party', () => {
const screen = render(<PartyLink id="network" />);
expect(screen.getByText('Network')).toBeInTheDocument();
});
it('renders ID with no link for invalid party', () => {
const screen = render(<PartyLink id="this-party-is-not-valid" />);
expect(screen.getByTestId('invalid-party')).toBeInTheDocument();
});
it('links a valid party to the party page', () => {
const aValidParty =
'13464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6e';
const screen = render(
<MemoryRouter>
<PartyLink id={aValidParty} />
</MemoryRouter>
);
const el = screen.getByText(aValidParty);
expect(el).toBeInTheDocument();
// The text should be a link that points to the party's page
expect(el.parentElement?.tagName).toEqual('A');
expect(el.parentElement?.getAttribute('href')).toContain(aValidParty);
});
});
@@ -3,47 +3,19 @@ import { Link } from 'react-router-dom';
import type { ComponentProps } from 'react'; import type { ComponentProps } from 'react';
import Hash from '../hash'; import Hash from '../hash';
import { t } from '@vegaprotocol/i18n';
import { isValidPartyId } from '../../../routes/parties/id/components/party-id-error';
import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
export const SPECIAL_CASE_NETWORK_ID =
'0000000000000000000000000000000000000000000000000000000000000000';
export const SPECIAL_CASE_NETWORK = 'network';
export type PartyLinkProps = Partial<ComponentProps<typeof Link>> & { export type PartyLinkProps = Partial<ComponentProps<typeof Link>> & {
id: string; id: string;
truncate?: boolean;
}; };
const PartyLink = ({ id, truncate = false, ...props }: PartyLinkProps) => { const PartyLink = ({ id, ...props }: PartyLinkProps) => {
// Some transactions will involve the 'network' party, which is alias for '000...000'
// The party page does not handle this nicely, so in this case we render the word 'Network'
if (id === SPECIAL_CASE_NETWORK || id === SPECIAL_CASE_NETWORK_ID) {
return (
<span className="font-mono" data-testid="network">
{t('Network')}
</span>
);
}
// If the party doesn't look correct, there's no point in linking to id. Just render
// the ID as it was given to us
if (!isValidPartyId(id)) {
return (
<span className="font-mono" data-testid="invalid-party">
{id}
</span>
);
}
return ( return (
<Link <Link
className="underline font-mono" className="underline font-mono"
{...props} {...props}
to={`/${Routes.PARTIES}/${id}`} to={`/${Routes.PARTIES}/${id}`}
> >
<Hash text={truncate ? truncateMiddle(id) : id} /> <Hash text={id} />
</Link> </Link>
); );
}; };
@@ -4,14 +4,13 @@ import { ENV } from '../../../config/env';
import Hash from '../hash'; import Hash from '../hash';
export type ProposalLinkProps = { export type ProposalLinkProps = {
id: string; id: string;
text?: string;
}; };
/** /**
* Given a proposal ID, generates an external link over to * Given a proposal ID, generates an external link over to
* the Governance page for more information * the Governance page for more information
*/ */
const ProposalLink = ({ id, text }: ProposalLinkProps) => { const ProposalLink = ({ id }: ProposalLinkProps) => {
const { data } = useExplorerProposalQuery({ const { data } = useExplorerProposalQuery({
variables: { id }, variables: { id },
}); });
@@ -21,7 +20,7 @@ const ProposalLink = ({ id, text }: ProposalLinkProps) => {
return ( return (
<ExternalLink href={`${base}/proposals/${id}`}> <ExternalLink href={`${base}/proposals/${id}`}>
{text ? text : <Hash text={label} />} <Hash text={label} />
</ExternalLink> </ExternalLink>
); );
}; };
@@ -2,8 +2,8 @@ import {
addDecimalsFormatNumber, addDecimalsFormatNumber,
formatNumberPercentage, formatNumberPercentage,
getMarketExpiryDateFormatted, getMarketExpiryDateFormatted,
} from '@vegaprotocol/utils'; t,
import { t } from '@vegaprotocol/i18n'; } from '@vegaprotocol/react-helpers';
import type { MarketInfoNoCandlesQuery } from '@vegaprotocol/market-info'; import type { MarketInfoNoCandlesQuery } from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info'; import { MarketInfoTable } from '@vegaprotocol/market-info';
import pick from 'lodash/pick'; import pick from 'lodash/pick';
@@ -22,7 +22,8 @@ export const MarketDetails = ({
}: { }: {
market: MarketInfoNoCandlesQuery['market']; market: MarketInfoNoCandlesQuery['market'];
}) => { }) => {
const quoteUnit = market?.tradableInstrument.instrument.product.quoteName; const assetSymbol =
market?.tradableInstrument.instrument.product?.settlementAsset.symbol;
const assetId = useMemo( const assetId = useMemo(
() => market?.tradableInstrument.instrument.product?.settlementAsset.id, () => market?.tradableInstrument.instrument.product?.settlementAsset.id,
[market] [market]
@@ -38,10 +39,6 @@ export const MarketDetails = ({
const assetDecimals = const assetDecimals =
market.tradableInstrument.instrument.product.settlementAsset.decimals; market.tradableInstrument.instrument.product.settlementAsset.decimals;
const liquidityPriceRange = formatNumberPercentage(
new BigNumber(market.lpPriceRange).times(100)
);
const panels = [ const panels = [
{ {
title: t('Key details'), title: t('Key details'),
@@ -182,40 +179,32 @@ export const MarketDetails = ({
{ {
title: t('Liquidity price range'), title: t('Liquidity price range'),
content: ( content: (
<> <MarketInfoTable
<p className="text-xs mb-4"> noBorder={false}
{`For liquidity orders to count towards a commitment, they must be data={{
within the liquidity monitoring bounds.`} liquidityPriceRange: formatNumberPercentage(
</p> new BigNumber(market.lpPriceRange).times(100)
<p className="text-xs mb-4"> ),
{`The liquidity price range is a ${liquidityPriceRange} difference from the mid LPVolumeMin:
price.`} market.data?.midPrice &&
</p> `${addDecimalsFormatNumber(
<MarketInfoTable new BigNumber(1)
noBorder={false} .minus(market.lpPriceRange)
data={{ .times(market.data.midPrice)
liquidityPriceRange: `${liquidityPriceRange} of mid price`, .toString(),
lowestPrice: market.decimalPlaces
market.data?.midPrice && )} ${assetSymbol}`,
`${addDecimalsFormatNumber( LPVolumeMax:
new BigNumber(1) market.data?.midPrice &&
.minus(market.lpPriceRange) `${addDecimalsFormatNumber(
.times(market.data.midPrice) new BigNumber(1)
.toString(), .plus(market.lpPriceRange)
market.decimalPlaces .times(market.data.midPrice)
)} ${quoteUnit}`, .toString(),
highestPrice: market.decimalPlaces
market.data?.midPrice && )} ${assetSymbol}`,
`${addDecimalsFormatNumber( }}
new BigNumber(1) ></MarketInfoTable>
.plus(market.lpPriceRange)
.times(market.data.midPrice)
.toString(),
market.decimalPlaces
)} ${quoteUnit}`,
}}
></MarketInfoTable>
</>
), ),
}, },
{ {
@@ -248,7 +237,7 @@ export const MarketDetails = ({
<> <>
{panels.map((p) => ( {panels.map((p) => (
<div className="mb-3"> <div className="mb-3">
<h2 className="font-alpha calt text-xl">{p.title}</h2> <h2 className="font-alpha text-xl">{p.title}</h2>
{p.content} {p.content}
</div> </div>
))} ))}
@@ -1,13 +1,13 @@
import type { MarketFieldsFragment } from '@vegaprotocol/market-list'; import type { MarketFieldsFragment } from '@vegaprotocol/market-list';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type { import type {
VegaICellRendererParams, VegaICellRendererParams,
VegaValueGetterParams, VegaValueGetterParams,
} from '@vegaprotocol/datagrid'; } from '@vegaprotocol/ui-toolkit';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import { useRef, useLayoutEffect } from 'react'; import { useRef, useLayoutEffect } from 'react';
import { BREAKPOINT_MD } from '../../config/breakpoints'; import { BREAKPOINT_MD } from '../../config/breakpoints';
import { MarketStateMapping } from '@vegaprotocol/types'; import { MarketStateMapping } from '@vegaprotocol/types';
@@ -83,7 +83,7 @@ const NestedDataListItem = ({
}); });
const titleClasses = classNames({ const titleClasses = classNames({
'text-xl pl-4 border-l-4 font-alpha calt': hasChildren, 'text-xl pl-4 border-l-4 font-alpha': hasChildren,
'text-base font-medium whitespace-nowrap': !hasChildren, 'text-base font-medium whitespace-nowrap': !hasChildren,
}); });
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { useExplorerDeterministicOrderQuery } from './__generated__/Order'; import { useExplorerDeterministicOrderQuery } from './__generated__/Order';
import { MarketLink } from '../links'; import { MarketLink } from '../links';
import PriceInMarket from '../price-in-market/price-in-market'; import PriceInMarket from '../price-in-market/price-in-market';
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { useExplorerDeterministicOrderQuery } from './__generated__/Order'; import { useExplorerDeterministicOrderQuery } from './__generated__/Order';
import { MarketLink } from '../links'; import { MarketLink } from '../links';
import PriceInMarket from '../price-in-market/price-in-market'; import PriceInMarket from '../price-in-market/price-in-market';
@@ -13,7 +13,7 @@ export interface DeterministicOrderDetailsProps {
} }
export const wrapperClasses = export const wrapperClasses =
'grid lg:grid-cols-1 flex items-center max-w-xl border border-vega-light-200 dark:border-vega-dark-150 rounded-md pv-2 ph-5 mb-5'; 'grid lg:grid-cols-1 flex items-center max-w-xl border border-zinc-200 dark:border-zinc-800 rounded-md pv-2 ph-5 mb-5';
/** /**
* This component renders the *current* details for an order * This component renders the *current* details for an order
@@ -42,7 +42,7 @@ const DeterministicOrderDetails = ({
<h2 className="text-3xl font-bold mb-4 display-5"> <h2 className="text-3xl font-bold mb-4 display-5">
{t('Order not found')} {t('Order not found')}
</h2> </h2>
<p className="text-vega-light-400 mb-12"> <p className="text-gray-500 mb-12">
{t('No order created from this transaction')} {t('No order created from this transaction')}
</p> </p>
</div> </div>
@@ -101,7 +101,7 @@ const DeterministicOrderDetails = ({
{t('Remaining')} {t('Remaining')}
</h2> </h2>
<h5 className="text-lg font-medium text-gray-500 mb-0"> <h5 className="text-lg font-medium text-gray-500 mb-0">
<SizeInMarket size={o.remaining} marketId={o.market.id} /> {o.remaining}
</h5> </h5>
</div> </div>
)} )}
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type * as Schema from '@vegaprotocol/types'; import type * as Schema from '@vegaprotocol/types';
import type { components } from '../../../../types/explorer'; import type { components } from '../../../../types/explorer';
@@ -20,7 +20,7 @@ export const PageHeader = ({
copy = false, copy = false,
className, className,
}: PageHeaderProps) => { }: PageHeaderProps) => {
const titleClasses = 'text-4xl xl:text-5xl uppercase font-alpha calt'; const titleClasses = 'text-4xl xl:text-5xl uppercase font-alpha';
return ( return (
<header className={className}> <header className={className}>
<span className={`${titleClasses} block`}>{prefix}</span> <span className={`${titleClasses} block`}>{prefix}</span>
@@ -38,7 +38,7 @@ export const PageHeader = ({
</h2> </h2>
{copy && ( {copy && (
<CopyWithTooltip data-testid="copy-to-clipboard" text={title}> <CopyWithTooltip data-testid="copy-to-clipboard" text={title}>
<button className="bg-vega-light-100 dark:bg-vega-dark-100 rounded-sm py-2 px-3"> <button className="bg-zinc-100 dark:bg-zinc-900 rounded-sm py-2 px-3">
<Icon name="duplicate" className="" /> <Icon name="duplicate" className="" />
</button> </button>
</CopyWithTooltip> </CopyWithTooltip>
@@ -1 +0,0 @@
export * from './page-actions';
@@ -1,10 +0,0 @@
import type { HTMLAttributes } from 'react';
export const PageActions = ({
children,
...props
}: HTMLAttributes<HTMLDivElement>) => (
<div className="flex flex-row items-start gap-1" {...props}>
{children}
</div>
);
@@ -1,45 +0,0 @@
import classNames from 'classnames';
import type { HTMLAttributes, ReactNode } from 'react';
import { useDocumentTitle } from '../../hooks/use-document-title';
import { RouteTitle } from '../route-title';
import { PageActions } from './page-actions';
type PageTitleProps = {
/**
* The page title
* (also sets the document title unless overwritten by
* `documentTitle` property)
*/
title: string;
/**
* The react node that consists of CTA buttons, links, etc.
*/
actions?: ReactNode;
/**
* Overwrites the document title
*/
documentTitle?: Parameters<typeof useDocumentTitle>[0];
} & Omit<HTMLAttributes<HTMLHeadingElement>, 'children'>;
export const PageTitle = ({
title,
actions,
documentTitle,
className,
...props
}: PageTitleProps) => {
useDocumentTitle(
documentTitle && documentTitle.length > 0 ? documentTitle : [title]
);
return (
<div
className="flex flex-col md:flex-row gap-1 justify-between content-start mb-8"
data-testid="page-title"
>
<RouteTitle className={classNames('mb-1', className)} {...props}>
{title}
</RouteTitle>
{actions && <PageActions>{actions}</PageActions>}
</div>
);
};
@@ -8,7 +8,7 @@ interface PanelProps {
export const Panel = ({ children, className }: PanelProps) => ( export const Panel = ({ children, className }: PanelProps) => (
<div <div
className={classNames( className={classNames(
'border border-vega-light-150 dark:border-vega-dark-150 rounded-md p-5 mb-5', 'border border-zinc-200 dark:border-zinc-800 rounded-md p-5 mb-5',
className className
)} )}
> >
@@ -1,5 +1,4 @@
import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/i18n';
import isUndefined from 'lodash/isUndefined'; import isUndefined from 'lodash/isUndefined';
import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market'; import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market';
import get from 'lodash/get'; import get from 'lodash/get';
@@ -1,18 +1,21 @@
import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals'; import type { ProposalListFieldsFragment } from '@vegaprotocol/governance';
import { VoteProgress } from '@vegaprotocol/proposals'; import { VoteProgress } from '@vegaprotocol/governance';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react'; import { AgGridColumn } from 'ag-grid-react';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type { import type {
VegaICellRendererParams, VegaICellRendererParams,
VegaValueFormatterParams, VegaValueFormatterParams,
} from '@vegaprotocol/datagrid'; } from '@vegaprotocol/ui-toolkit';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import { useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useLayoutEffect, useMemo, useRef, useState } from 'react';
import type { RowClickedEvent } from 'ag-grid-community'; import type { RowClickedEvent } from 'ag-grid-community';
import { getDateTimeFormat } from '@vegaprotocol/utils'; import {
import { t } from '@vegaprotocol/i18n'; getDateTimeFormat,
import { NetworkParams, useNetworkParams } from '@vegaprotocol/react-helpers'; NetworkParams,
t,
useNetworkParams,
} from '@vegaprotocol/react-helpers';
import { ProposalStateMapping } from '@vegaprotocol/types'; import { ProposalStateMapping } from '@vegaprotocol/types';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment'; import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { StatusMessage } from '../status-message'; import { StatusMessage } from '../status-message';
interface RenderFetchedProps { interface RenderFetchedProps {
@@ -13,7 +13,7 @@ export const RouteTitle = ({
...props ...props
}: RouteTitleProps) => { }: RouteTitleProps) => {
const classes = classnames( const classes = classnames(
'font-alpha calt', 'font-alpha',
'text-4xl', 'text-4xl',
'uppercase', 'uppercase',
'mb-8', 'mb-8',
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import React from 'react'; import React from 'react';
interface RouteErrorBoundaryProps { interface RouteErrorBoundaryProps {
@@ -1,5 +1,5 @@
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { Button, Input, InputError } from '@vegaprotocol/ui-toolkit'; import { Button, Input, InputError } from '@vegaprotocol/ui-toolkit';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@@ -1,43 +0,0 @@
import { useAssetDataProvider } from '@vegaprotocol/assets';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { AssetLink } from '../links';
export type DecimalSource = 'ASSET';
export type SizeInAssetProps = {
assetId: string;
size?: string | number;
decimalSource?: DecimalSource;
};
/**
* Given a market ID and an order size it will fetch the market
* order size, and format the size accordingly
*/
const SizeInAsset = ({
assetId,
size,
decimalSource = 'ASSET',
}: SizeInAssetProps) => {
const { data } = useAssetDataProvider(assetId);
if (!size) {
return <span>-</span>;
}
let label = size;
if (data) {
if (decimalSource === 'ASSET' && data.decimals) {
label = addDecimalsFormatNumber(size, data.decimals);
}
}
return (
<p>
<span>{label}</span>&nbsp;
<AssetLink assetId={assetId} showAssetSymbol={true} asDialog={true} />
</p>
);
};
export default SizeInAsset;
@@ -1,9 +1,9 @@
import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; import { addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market'; import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market';
export type DecimalSource = 'MARKET'; export type DecimalSource = 'MARKET';
export type SizeInMarketProps = { export type PriceInMarketProps = {
marketId: string; marketId: string;
size?: string | number; size?: string | number;
decimalSource?: DecimalSource; decimalSource?: DecimalSource;
@@ -17,7 +17,7 @@ const SizeInMarket = ({
marketId, marketId,
size, size,
decimalSource = 'MARKET', decimalSource = 'MARKET',
}: SizeInMarketProps) => { }: PriceInMarketProps) => {
const { data } = useExplorerMarketQuery({ const { data } = useExplorerMarketQuery({
variables: { id: marketId }, variables: { id: marketId },
fetchPolicy: 'cache-first', fetchPolicy: 'cache-first',
@@ -11,7 +11,7 @@ export const StatusMessage = ({
className, className,
...props ...props
}: StatusMessageProps) => { }: StatusMessageProps) => {
const classes = classnames('font-alpha calt text-2xl mb-28', className); const classes = classnames('font-alpha text-2xl mb-28', className);
return ( return (
<h3 className={classes} {...props}> <h3 className={classes} {...props}>
{children} {children}
@@ -12,7 +12,7 @@ export const SubHeading = ({
...props ...props
}: SubHeadingProps) => { }: SubHeadingProps) => {
const classes = classnames( const classes = classnames(
'font-alpha calt', 'font-alpha',
'text-2xl', 'text-2xl',
'uppercase', 'uppercase',
'mt-8 mb-2', 'mt-8 mb-2',
@@ -1,5 +1,5 @@
import { formatDistanceToNowStrict } from 'date-fns'; import { formatDistanceToNowStrict } from 'date-fns';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
interface TimeAgoProps { interface TimeAgoProps {
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
interface TimeProps { interface TimeProps {
date: string | null | undefined; date: string | null | undefined;
@@ -1,4 +1,4 @@
import { truncateByChars } from '@vegaprotocol/utils'; import { truncateByChars } from '@vegaprotocol/react-helpers';
import * as React from 'react'; import * as React from 'react';
interface TruncateInlineProps { interface TruncateInlineProps {
@@ -1,6 +1,6 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { TxDetailsChainEventBuiltinDeposit } from './tx-builtin-deposit'; import { TxDetailsChainEventBuiltinDeposit } from './tx-builtin-deposit';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -10,7 +10,7 @@ import { MemoryRouter } from 'react-router-dom';
type Deposit = components['schemas']['vegaBuiltinAssetDeposit']; type Deposit = components['schemas']['vegaBuiltinAssetDeposit'];
const fullMock: Deposit = { const fullMock: Deposit = {
partyId: '0000000000000000000000000000000000000000000000000000000000000001', partyId: 'party123',
vegaAssetId: 'asset123', vegaAssetId: 'asset123',
amount: 'amount123', amount: 'amount123',
}; };
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { AssetLink, PartyLink } from '../../../links'; import { AssetLink, PartyLink } from '../../../links';
@@ -1,6 +1,6 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { TxDetailsChainEventBuiltinWithdrawal } from './tx-builtin-withdrawal'; import { TxDetailsChainEventBuiltinWithdrawal } from './tx-builtin-withdrawal';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -10,7 +10,7 @@ import { MemoryRouter } from 'react-router-dom';
type Withdrawal = components['schemas']['vegaBuiltinAssetWithdrawal']; type Withdrawal = components['schemas']['vegaBuiltinAssetWithdrawal'];
const fullMock: Withdrawal = { const fullMock: Withdrawal = {
partyId: '0000000000000000000000000000000000000000000000000000000000000001', partyId: 'party123',
vegaAssetId: 'asset123', vegaAssetId: 'asset123',
amount: 'amount123', amount: 'amount123',
}; };
@@ -67,12 +67,11 @@ describe('Chain Event: Builtin asset withdrawal', () => {
expect(screen.getByText(`${fullMock.amount}`)).toBeInTheDocument(); expect(screen.getByText(`${fullMock.amount}`)).toBeInTheDocument();
expect(screen.getByText(t('Recipient'))).toBeInTheDocument(); expect(screen.getByText(t('Recipient'))).toBeInTheDocument();
const partyLink = screen.getByText(`${fullMock.partyId}`); const partyLink = screen.getByText(`${fullMock.partyId}`);
expect(partyLink).toBeInTheDocument();
if (!partyLink.parentElement) { if (!partyLink.parentElement) {
throw new Error('Party link does not exist'); throw new Error('Party link does not exist');
} }
expect(partyLink.parentElement.tagName).toEqual('A'); expect(partyLink.parentElement.tagName).toEqual('A');
expect(partyLink.parentElement.getAttribute('href')).toEqual( expect(partyLink.parentElement.getAttribute('href')).toEqual(
`/parties/${fullMock.partyId}` `/parties/${fullMock.partyId}`
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { AssetLink, PartyLink } from '../../../links'; import { AssetLink, PartyLink } from '../../../links';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links'; import { AssetLink } from '../../../links';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links'; import { AssetLink } from '../../../links';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links'; import { AssetLink } from '../../../links';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TxDetailsChainEventErc20BridgePause } from './tx-erc20-bridge-pause'; import { TxDetailsChainEventErc20BridgePause } from './tx-erc20-bridge-pause';
describe('Chain Event: ERC20 bridge pause', () => { describe('Chain Event: ERC20 bridge pause', () => {
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
export interface TxDetailsChainEventErc20BridgePauseProps { export interface TxDetailsChainEventErc20BridgePauseProps {
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -10,12 +10,10 @@ import { TxDetailsChainEventDeposit } from './tx-erc20-deposit';
type Deposit = components['schemas']['vegaERC20Deposit']; type Deposit = components['schemas']['vegaERC20Deposit'];
const fullMock: Deposit = { const fullMock: Deposit = {
vegaAssetId: vegaAssetId: 'asset123',
'0000000000000000000000000000000000000000000000000000000000000002',
amount: 'amount123', amount: 'amount123',
sourceEthereumAddress: 'eth123', sourceEthereumAddress: 'eth123',
targetPartyId: targetPartyId: 'vega123',
'0000000000000000000000000000000000000000000000000000000000000001',
}; };
describe('Chain Event: ERC20 asset deposit', () => { describe('Chain Event: ERC20 asset deposit', () => {
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { AssetLink, PartyLink } from '../../../links'; import { AssetLink, PartyLink } from '../../../links';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links'; import { AssetLink } from '../../../links';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { getBlockTime } from './lib/get-block-time'; import { getBlockTime } from './lib/get-block-time';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import isNumber from 'lodash/isNumber'; import isNumber from 'lodash/isNumber';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -13,8 +13,7 @@ const fullMock: Deposit = {
amount: 'amount123', amount: 'amount123',
blockTime: 'block123', blockTime: 'block123',
ethereumAddress: 'eth123', ethereumAddress: 'eth123',
vegaPublicKey: vegaPublicKey: 'vega123',
'0000000000000000000000000000000000000000000000000000000000000001',
}; };
describe('Chain Event: Stake deposit', () => { describe('Chain Event: Stake deposit', () => {
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { PartyLink } from '../../../links'; import { PartyLink } from '../../../links';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -13,8 +13,7 @@ const fullMock: Remove = {
amount: 'amount123', amount: 'amount123',
blockTime: 'block123', blockTime: 'block123',
ethereumAddress: 'eth123', ethereumAddress: 'eth123',
vegaPublicKey: vegaPublicKey: 'vega123',
'0000000000000000000000000000000000000000000000000000000000000001',
}; };
describe('Chain Event: Stake remove', () => { describe('Chain Event: Stake remove', () => {
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { PartyLink } from '../../../links'; import { PartyLink } from '../../../links';
@@ -1,5 +1,5 @@
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
@@ -1,5 +1,4 @@
import { formatNumber, toBigNum } from '@vegaprotocol/utils'; import { formatNumber, t, toBigNum } from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/i18n';
import { TableRow, TableCell } from '../../../table'; import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer'; import type { components } from '../../../../../types/explorer';
import { import {
@@ -36,7 +36,7 @@ export const ChainResponseCode = ({
error && error.length > 100 ? error.replace(/,/g, ',\r\n') : error; error && error.length > 100 ? error.replace(/,/g, ',\r\n') : error;
return ( return (
<div title={`Response code: ${code} - ${label}`} className="inline-block"> <div title={`Response code: ${code} - ${label}`}>
<span <span
className="mr-2" className="mr-2"
aria-label={isSuccess ? 'Success' : 'Warning'} aria-label={isSuccess ? 'Success' : 'Warning'}
@@ -1,4 +1,4 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../../../../types/explorer'; import type { components } from '../../../../../../types/explorer';
import { TableRow } from '../../../../table'; import { TableRow } from '../../../../table';

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