Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
829d3112e1 | ||
|
|
73cda26e17 | ||
|
|
f34ddaa7b9 | ||
|
|
20371f56f7 | ||
|
|
6db09974d6 | ||
|
|
261ec8c5e4 | ||
|
|
d577080a86 | ||
|
|
c5deddb6d8 | ||
|
|
4acf2a7f8c | ||
|
|
fdfae74524 | ||
|
|
7f9c1178c4 | ||
|
|
b633dbc049 | ||
|
|
b69c58f59d | ||
|
|
57cc5ce217 | ||
|
|
92315181e1 | ||
|
|
7e461d3e0e | ||
|
|
58799bb231 | ||
|
|
836c232a1c | ||
|
|
de04a5b527 | ||
|
|
6af2186669 | ||
|
|
9b7c26386b | ||
|
|
0d32ef61ed | ||
|
|
05349282a1 | ||
|
|
98b1f88008 | ||
|
|
59b36c9b37 | ||
|
|
b9aef78447 | ||
|
|
db050c6560 | ||
|
|
c36630e681 | ||
|
|
c8796e9ba7 | ||
|
|
5cb547c4e3 | ||
|
|
312db3ea0f | ||
|
|
2fbecc461b | ||
|
|
4d9bcde560 | ||
|
|
e5fc3d1bc4 | ||
|
|
799cb04cae | ||
|
|
e03ba3256f | ||
|
|
68105c05ca | ||
|
|
0c6212e82b | ||
|
|
71ae12007b | ||
|
|
ccc4d39aec | ||
|
|
5be0a1a85d | ||
|
|
5eefd0c1a5 | ||
|
|
fba905a811 | ||
|
|
db06f0bc99 | ||
|
|
3b04963cf4 | ||
|
|
c470740a41 | ||
|
|
a585c39dcf | ||
|
|
806b8605e9 | ||
|
|
a50c28713a | ||
|
|
d843c61570 | ||
|
|
46bdf17f1a | ||
|
|
a1515e980c | ||
|
|
acef1a8e24 | ||
|
|
5d4ce7e2f2 | ||
|
|
457caf4e8c | ||
|
|
18c857a0ce | ||
|
|
3f77986885 | ||
|
|
ba7d0ec6c9 | ||
|
|
d644988aaf | ||
|
|
3b4bf832c8 | ||
|
|
8c7a0e24a3 | ||
|
|
50693d2df9 | ||
|
|
282f714d5b | ||
|
|
87338c4f2f | ||
|
|
8e6c066b99 | ||
|
|
c0a744ff78 | ||
|
|
059a4298f4 | ||
|
|
23fef06263 | ||
|
|
19980e5fb1 | ||
|
|
bd18759e5e | ||
|
|
913703e2d8 | ||
|
|
288a5d6268 | ||
|
|
8e25108701 | ||
|
|
d88bf734f5 | ||
|
|
2094a29d35 | ||
|
|
8e276d9933 | ||
|
|
0473412487 | ||
|
|
cc51007e6a | ||
|
|
eba3b6a5b9 | ||
|
|
54bad195b8 | ||
|
|
46803ce619 | ||
|
|
6f9f94229e |
@@ -2,9 +2,21 @@
|
||||
"root": true,
|
||||
"ignorePatterns": ["**/*"],
|
||||
"plugins": ["@nrwl/nx", "eslint-plugin-unicorn", "jsx-a11y", "jest"],
|
||||
"settings": {
|
||||
"jsx-a11y": {
|
||||
"components": {
|
||||
"Button": "button",
|
||||
"Input": "input",
|
||||
"Select": "select",
|
||||
"Radio": "radio",
|
||||
"TextArea": "textarea"
|
||||
}
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"extends": ["plugin:jsx-a11y/strict"],
|
||||
"rules": {
|
||||
"@nrwl/nx/enforce-module-boundaries": [
|
||||
"error",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
/tmp
|
||||
/out-tsc
|
||||
/tools/executors/**/*.js
|
||||
/tools/utils/*.js
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
@@ -16,7 +16,7 @@ The trading interface built based on a component toolkit. It will provide a way
|
||||
|
||||
### [Token](./apps/token)
|
||||
|
||||
The utlity dApp for interacting with the Vega token and using its' utility. This includes; delegation, nomination, governance and redemption of tokens.
|
||||
The utility dApp for interacting with the Vega token and using its' utility. This includes; delegation, nomination, governance and redemption of tokens.
|
||||
|
||||
### [Explorer](./apps/explorer)
|
||||
|
||||
@@ -51,7 +51,7 @@ A utility library for connecting to the Ethereum network and interacting with Ve
|
||||
|
||||
### [React Helpers](./libs/react-helpers)
|
||||
|
||||
Generic react helpers that can be used across multilpe applications, along with other utilities.
|
||||
Generic react helpers that can be used across multiple applications, along with other utilities.
|
||||
|
||||
# 💻 Develop
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ NX_EXPLORER_ASSETS=1
|
||||
NX_EXPLORER_GENESIS=1
|
||||
NX_EXPLORER_GOVERNANCE=1
|
||||
NX_EXPLORER_MARKETS=1
|
||||
NX_EXPLORER_TXS_LIST=0
|
||||
NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
|
||||
@@ -11,6 +11,7 @@ NX_EXPLORER_ASSETS=1
|
||||
NX_EXPLORER_GENESIS=1
|
||||
NX_EXPLORER_GOVERNANCE=1
|
||||
NX_EXPLORER_MARKETS=1
|
||||
NX_EXPLORER_TXS_LIST=1
|
||||
NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
|
||||
@@ -11,6 +11,7 @@ NX_EXPLORER_ASSETS=1
|
||||
NX_EXPLORER_GENESIS=1
|
||||
NX_EXPLORER_GOVERNANCE=1
|
||||
NX_EXPLORER_MARKETS=1
|
||||
NX_EXPLORER_TXS_LIST=1
|
||||
NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
|
||||
@@ -11,6 +11,7 @@ NX_EXPLORER_ASSETS=1
|
||||
NX_EXPLORER_GENESIS=1
|
||||
NX_EXPLORER_GOVERNANCE=1
|
||||
NX_EXPLORER_MARKETS=1
|
||||
NX_EXPLORER_TXS_LIST=1
|
||||
NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
|
||||
@@ -11,6 +11,7 @@ NX_EXPLORER_ASSETS=1
|
||||
NX_EXPLORER_GENESIS=1
|
||||
NX_EXPLORER_GOVERNANCE=1
|
||||
NX_EXPLORER_MARKETS=1
|
||||
NX_EXPLORER_TXS_LIST=1
|
||||
NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
const setupNodeEvents = require('./src/plugins/index.js');
|
||||
|
||||
module.exports = defineConfig({
|
||||
projectId: 'et4snf',
|
||||
|
||||
e2e: {
|
||||
setupNodeEvents,
|
||||
baseUrl: 'http://localhost:3000',
|
||||
fileServerFolder: '.',
|
||||
fixturesFolder: false,
|
||||
specPattern: '**/*.feature',
|
||||
excludeSpecPattern: '**/*.js',
|
||||
modifyObstructiveCode: false,
|
||||
supportFile: './src/support/index.ts',
|
||||
video: true,
|
||||
videosFolder: '../../dist/cypress/apps/explorer-e2e/videos',
|
||||
screenshotsFolder: '../../dist/cypress/apps/explorer-e2e/screenshots',
|
||||
chromeWebSecurity: false,
|
||||
},
|
||||
env: {
|
||||
environment: 'CUSTOM',
|
||||
tsConfig: 'tsconfig.json',
|
||||
TAGS: 'not @todo and not @ignore and not @manual',
|
||||
},
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3000",
|
||||
"projectId": "et4snf",
|
||||
"fileServerFolder": ".",
|
||||
"fixturesFolder": false,
|
||||
"pluginsFile": "./src/plugins/index.js",
|
||||
"testFiles": "*.{ts,feature,features}",
|
||||
"ignoreTestFiles": "**/*.js",
|
||||
"integrationFolder": "./src/integration",
|
||||
"modifyObstructiveCode": false,
|
||||
"supportFile": "./src/support/index.ts",
|
||||
"video": true,
|
||||
"videosFolder": "../../dist/cypress/apps/explorer-e2e/videos",
|
||||
"screenshotsFolder": "../../dist/cypress/apps/explorer-e2e/screenshots",
|
||||
"chromeWebSecurity": false,
|
||||
"env": {
|
||||
"environment": "CUSTOM",
|
||||
"tsConfig": "tsconfig.json",
|
||||
"TAGS": "not @todo and not @ignore and not @manual"
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
"e2e": {
|
||||
"executor": "@nrwl/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/explorer-e2e/cypress.json",
|
||||
"cypressConfig": "apps/explorer-e2e/cypress.config.js",
|
||||
"devServerTarget": "explorer:serve"
|
||||
},
|
||||
"configurations": {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@ignore
|
||||
# tendermint times out getting txs on testnet atm
|
||||
Feature: Transactions Page
|
||||
|
||||
Scenario: Navigate to transactions page
|
||||
@@ -5,14 +7,12 @@ Feature: Transactions Page
|
||||
When I navigate to the transactions page
|
||||
Then transactions page is correctly displayed
|
||||
|
||||
@ignore
|
||||
Scenario: Navigate to transaction details page
|
||||
Given I am on the homepage
|
||||
When I navigate to the transactions page
|
||||
And I click on the top transaction
|
||||
Then transaction details are displayed
|
||||
|
||||
@ignore
|
||||
Scenario: Navigate to transactions page using mobile
|
||||
Given I am on mobile and open the toggle menu
|
||||
When I navigate to the transactions page
|
||||
|
||||
@@ -15,11 +15,9 @@ export default class TransactionsPage extends BasePage {
|
||||
txType = 'tx-type';
|
||||
|
||||
validateTransactionsPagedisplayed() {
|
||||
cy.getByTestId(this.transactionsList).should('have.length.above', 1);
|
||||
cy.getByTestId(this.blockHeight).first().should('not.be.empty');
|
||||
cy.getByTestId(this.numberOfTransactions).first().should('not.be.empty');
|
||||
cy.getByTestId(this.validatorLink).first().should('not.be.empty');
|
||||
cy.getByTestId(this.blockTime).first().should('not.be.empty');
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(5000); // Wait for transactions to load if there are any
|
||||
cy.getByTestId(this.transactionRow).should('have.length.above', 1);
|
||||
}
|
||||
|
||||
validateRefreshBtn() {
|
||||
|
||||
@@ -13,6 +13,7 @@ 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
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
@@ -22,3 +23,4 @@ NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
NX_EXPLORER_MARKETS=1
|
||||
NX_EXPLORER_TXS_LIST=1
|
||||
|
||||
@@ -6,12 +6,14 @@ NX_VEGA_URL=http://localhost:3028/query
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
||||
NX_VEGA_ENV=CUSTOM
|
||||
NX_VEGA_REST=http://localhost:3029
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
NX_EXPLORER_GENESIS=1
|
||||
NX_EXPLORER_GOVERNANCE=1
|
||||
NX_EXPLORER_MARKETS=1
|
||||
NX_EXPLORER_TXS_LIST=1
|
||||
NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
|
||||
@@ -7,3 +7,4 @@ 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_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -7,3 +7,4 @@ 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_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -7,3 +7,4 @@ 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_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -7,3 +7,4 @@ 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_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -7,3 +7,4 @@ 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_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -5,3 +5,4 @@ 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
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -58,6 +58,7 @@ There are a few different configuration options offered for this app:
|
||||
| `NX_EXPLORER_GENESIS` | Enable the genesis page for the explorer |
|
||||
| `NX_EXPLORER_GOVERNANCE` | Enable the governance page for the explorer |
|
||||
| `NX_EXPLORER_MARKETS` | Enable the markets page for the explorer |
|
||||
| `NX_EXPLORER_TXS_LIST` | Enable the transactions list page for the explorer |
|
||||
| `NX_EXPLORER_NETWORK_PARAMETERS` | Enable the network parameters page for the explorer |
|
||||
| `NX_EXPLORER_PARTIES` | Enable the parties page for the explorer |
|
||||
| `NX_EXPLORER_VALIDATORS` | Enable the validators page for the explorer |
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/web:webpack",
|
||||
"executor": "./tools/executors/webpack:build",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "./tools/executors/serve:serve",
|
||||
"executor": "./tools/executors/webpack:serve",
|
||||
"options": {
|
||||
"port": 3000,
|
||||
"buildTarget": "explorer:build",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
|
||||
import { NetworkInfo } from '@vegaprotocol/network-info';
|
||||
import { createClient } from './lib/apollo-client';
|
||||
import { Nav } from './components/nav';
|
||||
import { Header } from './components/header';
|
||||
@@ -36,6 +37,9 @@ function App() {
|
||||
/>
|
||||
<Nav menuOpen={menuOpen} />
|
||||
<Main />
|
||||
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] md:flex md:col-span-2 p-16 gap-12 border-t-1">
|
||||
<NetworkInfo />
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</NetworkLoader>
|
||||
|
||||
@@ -28,9 +28,10 @@ export const Nav = ({ menuOpen }: NavProps) => {
|
||||
className={({ isActive }) =>
|
||||
classnames(
|
||||
'block mb-8 px-8',
|
||||
'text-h5 hover:bg-vega-yellow hover:text-black',
|
||||
'text-h5 hover:bg-vega-pink dark:hover:bg-vega-yellow hover:text-white dark:hover:text-black',
|
||||
{
|
||||
'bg-vega-yellow text-black': isActive,
|
||||
'bg-vega-pink text-white dark:bg-vega-yellow dark:text-black':
|
||||
isActive,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -55,14 +55,18 @@ export const Search = () => {
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
className="flex-1 flex self-center md:ml-16 md:mr-12 md:justify-end"
|
||||
>
|
||||
<FormGroup className="relative w-full md:w-2/3 mb-0">
|
||||
<FormGroup
|
||||
label={t('Search by block number or transaction hash')}
|
||||
className="relative w-full md:w-2/3 mb-0"
|
||||
labelClassName="sr-only"
|
||||
labelFor="search"
|
||||
>
|
||||
<Input
|
||||
{...register('search')}
|
||||
id="search"
|
||||
data-testid="search"
|
||||
hasError={Boolean(error?.message)}
|
||||
type="text"
|
||||
autoFocus={true}
|
||||
placeholder={t('Enter block number or transaction hash')}
|
||||
/>
|
||||
{error?.message && (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export { TxList } from './tx-list';
|
||||
export { BlockTxsData } from './block-txs-data';
|
||||
export { TxOrderType } from './tx-order-type';
|
||||
export { TxsInfiniteList } from './txs-infinite-list';
|
||||
export { TxsInfiniteListItem } from './txs-infinite-list-item';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Lozenge } from '@vegaprotocol/ui-toolkit';
|
||||
import { Lozenge, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
interface TxOrderTypeProps {
|
||||
orderType: string;
|
||||
@@ -36,7 +36,7 @@ const displayString: StringMap = {
|
||||
|
||||
export const TxOrderType = ({ orderType, className }: TxOrderTypeProps) => {
|
||||
return (
|
||||
<Lozenge data-testid="tx-type" className={className}>
|
||||
<Lozenge data-testid="tx-type" variant={Intent.None} className={className}>
|
||||
{displayString[orderType] || orderType}
|
||||
</Lozenge>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import { TxsInfiniteListItem } from './txs-infinite-list-item';
|
||||
import { render, screen, fireEvent, act } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
describe('Txs infinite list item', () => {
|
||||
it('should display "missing vital data" if "Type" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
// @ts-ignore testing deliberate failure
|
||||
Type={undefined}
|
||||
Command={'test'}
|
||||
Sig={'test'}
|
||||
PubKey={'test'}
|
||||
Nonce={1}
|
||||
TxHash={'test'}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display "missing vital data" if "Command" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
Type={'test'}
|
||||
// @ts-ignore testing deliberate failure
|
||||
Command={undefined}
|
||||
Sig={'test'}
|
||||
PubKey={'test'}
|
||||
Nonce={1}
|
||||
TxHash={'test'}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display "missing vital data" if "Pubkey" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
Type={'test'}
|
||||
Command={'test'}
|
||||
Sig={'test'}
|
||||
// @ts-ignore testing deliberate failure
|
||||
PubKey={undefined}
|
||||
Nonce={1}
|
||||
TxHash={'test'}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display "missing vital data" if "TxHash" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
Type={'test'}
|
||||
Command={'test'}
|
||||
Sig={'test'}
|
||||
PubKey={'test'}
|
||||
Nonce={1}
|
||||
// @ts-ignore testing deliberate failure
|
||||
TxHash={undefined}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders data correctly', () => {
|
||||
const testCommandData = JSON.stringify({
|
||||
test: 'test of command data',
|
||||
});
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<TxsInfiniteListItem
|
||||
Type={'testType'}
|
||||
Command={testCommandData}
|
||||
Sig={'testSig'}
|
||||
PubKey={'testPubKey'}
|
||||
Nonce={1}
|
||||
TxHash={'testTxHash'}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
);
|
||||
expect(screen.getByTestId('tx-hash')).toHaveTextContent('testTxHash');
|
||||
expect(screen.getByTestId('pub-key')).toHaveTextContent('testPubKey');
|
||||
expect(screen.getByTestId('type')).toHaveTextContent('testType');
|
||||
const button = screen.getByTestId('command-details');
|
||||
act(() => {
|
||||
fireEvent.click(button);
|
||||
});
|
||||
expect(screen.getByText('"test of command data"')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
Icon,
|
||||
Intent,
|
||||
SyntaxHighlighter,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { TruncatedLink } from '../truncate/truncated-link';
|
||||
import { Routes } from '../../routes/route-names';
|
||||
import { TxOrderType } from './tx-order-type';
|
||||
import type { ChainExplorerTxResponse } from '../../routes/types/chain-explorer-response';
|
||||
|
||||
const TRUNCATE_LENGTH = 14;
|
||||
|
||||
export const TxsInfiniteListItem = ({
|
||||
TxHash,
|
||||
PubKey,
|
||||
Type,
|
||||
Command,
|
||||
}: ChainExplorerTxResponse) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
if (!TxHash || !PubKey || !Type || !Command) {
|
||||
return <div>Missing vital data</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
data-testid="transaction-row"
|
||||
className="grid grid-cols-[repeat(2,_1fr)_240px] gap-12 w-full border-t border-black-60 dark:border-white-25 py-8 txs-infinite-list-item"
|
||||
>
|
||||
<div className="whitespace-nowrap overflow-scroll" data-testid="tx-hash">
|
||||
<TruncatedLink
|
||||
to={`/${Routes.TX}/${TxHash}`}
|
||||
text={TxHash}
|
||||
startChars={TRUNCATE_LENGTH}
|
||||
endChars={TRUNCATE_LENGTH}
|
||||
/>
|
||||
</div>
|
||||
<div className="whitespace-nowrap overflow-scroll" data-testid="pub-key">
|
||||
<TruncatedLink
|
||||
to={`/${Routes.PARTIES}/${PubKey}`}
|
||||
text={PubKey}
|
||||
startChars={TRUNCATE_LENGTH}
|
||||
endChars={TRUNCATE_LENGTH}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="flex justify-between whitespace-nowrap overflow-scroll"
|
||||
data-testid="type"
|
||||
>
|
||||
<TxOrderType orderType={Type} />
|
||||
<button
|
||||
title="More details"
|
||||
onClick={() => setOpen(true)}
|
||||
data-testid="command-details"
|
||||
>
|
||||
<Icon name="search-template" />
|
||||
</button>
|
||||
<Dialog
|
||||
open={open}
|
||||
onChange={(isOpen) => setOpen(false)}
|
||||
intent={Intent.None}
|
||||
>
|
||||
<SyntaxHighlighter data={JSON.parse(Command)} />
|
||||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
import { TxsInfiniteList } from './txs-infinite-list';
|
||||
import { render, screen, fireEvent, act } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
const generateTxs = (number: number) => {
|
||||
return Array.from(Array(number)).map((_) => ({
|
||||
Type: 'ChainEvent',
|
||||
Command:
|
||||
'{"txId":"0xc8941ac4ea989988cb8f72e8fdab2e2009376fd17619491439d36b519d27bc93","nonce":"1494","stakingEvent":{"index":"263","block":"14805346","stakeDeposited":{"ethereumAddress":"0x2e5fe63e5d49c26998cf4bfa9b64de1cf9ae7ef2","vegaPublicKey":"657c2a8a5867c43c831e24820b7544e2fdcc1cf610cfe0ece940fe78137400fd","amount":"38471116086510047870875","blockTime":"1652968806"}}}',
|
||||
Sig: 'fe7624ab742c492cf1e667e79de4777992aca8e093c8707e1f22685c3125c6082cd21b85cd966a61ad4ca0cca2f8bed3082565caa5915bc3b2f78c1ae35cac0b',
|
||||
PubKey:
|
||||
'0x7d69327393cdfaaae50e5e215feca65273eafabfb38f32b8124e66298af346d5',
|
||||
Nonce: 18296387398179254000,
|
||||
TxHash:
|
||||
'0x9C753FA6325F7A40D9C4FA5C25E24476C54613E12B1FA2DD841E3BB00D088B77',
|
||||
}));
|
||||
};
|
||||
|
||||
describe('Txs infinite list', () => {
|
||||
it('should display a "no items" message when no items provided', () => {
|
||||
render(
|
||||
<TxsInfiniteList
|
||||
txs={undefined}
|
||||
areTxsLoading={false}
|
||||
hasMoreTxs={false}
|
||||
loadMoreTxs={() => null}
|
||||
error={undefined}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('No items')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('error is displayed at item level', () => {
|
||||
const txs = generateTxs(1);
|
||||
render(
|
||||
<TxsInfiniteList
|
||||
txs={txs}
|
||||
areTxsLoading={false}
|
||||
hasMoreTxs={false}
|
||||
loadMoreTxs={() => null}
|
||||
error={Error('test error!')}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Error: test error!')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('item renders data of n length into list of n length', () => {
|
||||
// Provided the number of items doesn't exceed the 30 it initially
|
||||
// desires, all txs will initially render
|
||||
const txs = generateTxs(10);
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<TxsInfiniteList
|
||||
txs={txs}
|
||||
areTxsLoading={false}
|
||||
hasMoreTxs={false}
|
||||
loadMoreTxs={() => null}
|
||||
error={undefined}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByTestId('infinite-scroll-wrapper')
|
||||
.querySelectorAll('.txs-infinite-list-item')
|
||||
).toHaveLength(10);
|
||||
});
|
||||
|
||||
it('tries to load more items when required to initially fill the list', () => {
|
||||
// For example, if initially rendering 15, the bottom of the list is
|
||||
// in view of the viewport, and the callback should be executed
|
||||
const txs = generateTxs(15);
|
||||
const callback = jest.fn();
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<TxsInfiniteList
|
||||
txs={txs}
|
||||
areTxsLoading={false}
|
||||
hasMoreTxs={true}
|
||||
loadMoreTxs={callback}
|
||||
error={undefined}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(callback.mock.calls.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('does not try to load more items if there are no more', () => {
|
||||
const txs = generateTxs(3);
|
||||
const callback = jest.fn();
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<TxsInfiniteList
|
||||
txs={txs}
|
||||
areTxsLoading={false}
|
||||
hasMoreTxs={false}
|
||||
loadMoreTxs={callback}
|
||||
error={undefined}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(callback.mock.calls.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('loads more items is called when scrolled', () => {
|
||||
const txs = generateTxs(20);
|
||||
const callback = jest.fn();
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<TxsInfiniteList
|
||||
txs={txs}
|
||||
areTxsLoading={false}
|
||||
hasMoreTxs={true}
|
||||
loadMoreTxs={callback}
|
||||
error={undefined}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
act(() => {
|
||||
fireEvent.scroll(screen.getByTestId('infinite-scroll-wrapper'), {
|
||||
target: { scrollY: 600 },
|
||||
});
|
||||
});
|
||||
|
||||
expect(callback.mock.calls.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,109 @@
|
||||
import React from 'react';
|
||||
import { FixedSizeList as List } from 'react-window';
|
||||
import InfiniteLoader from 'react-window-infinite-loader';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TxsInfiniteListItem } from './txs-infinite-list-item';
|
||||
import type { ChainExplorerTxResponse } from '../../routes/types/chain-explorer-response';
|
||||
|
||||
interface TxsInfiniteListProps {
|
||||
hasMoreTxs: boolean;
|
||||
areTxsLoading: boolean | undefined;
|
||||
txs: ChainExplorerTxResponse[] | undefined;
|
||||
loadMoreTxs: () => void;
|
||||
error: Error | undefined;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface ItemProps {
|
||||
index: ChainExplorerTxResponse;
|
||||
style: React.CSSProperties;
|
||||
isLoading: boolean;
|
||||
error: Error | undefined;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const NOOP = () => {};
|
||||
|
||||
const Item = ({ index, style, isLoading, error }: ItemProps) => {
|
||||
let content;
|
||||
if (error) {
|
||||
content = t(`${error}`);
|
||||
} else if (isLoading) {
|
||||
content = t('Loading...');
|
||||
} else {
|
||||
const { TxHash, PubKey, Type, Command, Sig, Nonce } = index;
|
||||
content = (
|
||||
<TxsInfiniteListItem
|
||||
Type={Type}
|
||||
Command={Command}
|
||||
Sig={Sig}
|
||||
PubKey={PubKey}
|
||||
Nonce={Nonce}
|
||||
TxHash={TxHash}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <div style={style}>{content}</div>;
|
||||
};
|
||||
|
||||
export const TxsInfiniteList = ({
|
||||
hasMoreTxs,
|
||||
areTxsLoading,
|
||||
txs,
|
||||
loadMoreTxs,
|
||||
error,
|
||||
className,
|
||||
}: TxsInfiniteListProps) => {
|
||||
if (!txs) {
|
||||
return <div>No items</div>;
|
||||
}
|
||||
|
||||
// If there are more items to be loaded then add an extra row to hold a loading indicator.
|
||||
const itemCount = hasMoreTxs ? txs.length + 1 : txs.length;
|
||||
|
||||
// Pass an empty callback to InfiniteLoader in case it asks us to load more than once.
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const loadMoreItems = areTxsLoading ? NOOP : loadMoreTxs;
|
||||
|
||||
// Every row is loaded except for our loading indicator row.
|
||||
const isItemLoaded = (index: number) => !hasMoreTxs || index < txs.length;
|
||||
|
||||
return (
|
||||
<div className={className} data-testid="transactions-list">
|
||||
<div className="grid grid-cols-[repeat(2,_1fr)_240px] gap-12 w-full mb-8">
|
||||
<div className="text-h5 font-bold">Txn hash</div>
|
||||
<div className="text-h5 font-bold">Party</div>
|
||||
<div className="text-h5 font-bold pl-2">Type</div>
|
||||
</div>
|
||||
<div data-testid="infinite-scroll-wrapper">
|
||||
<InfiniteLoader
|
||||
isItemLoaded={isItemLoaded}
|
||||
itemCount={itemCount}
|
||||
loadMoreItems={loadMoreItems}
|
||||
>
|
||||
{({ onItemsRendered, ref }) => (
|
||||
<List
|
||||
className="List"
|
||||
height={595}
|
||||
itemCount={itemCount}
|
||||
itemSize={41}
|
||||
onItemsRendered={onItemsRendered}
|
||||
ref={ref}
|
||||
width={'100%'}
|
||||
>
|
||||
{({ index, style }) => (
|
||||
<Item
|
||||
index={txs[index]}
|
||||
style={style}
|
||||
isLoading={!isItemLoaded(index)}
|
||||
error={error}
|
||||
/>
|
||||
)}
|
||||
</List>
|
||||
)}
|
||||
</InfiniteLoader>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -24,6 +24,7 @@ export const ENV = {
|
||||
genesis: truthy.includes(windowOrDefault('NX_EXPLORER_GENESIS')),
|
||||
governance: truthy.includes(windowOrDefault('NX_EXPLORER_GOVERNANCE')),
|
||||
markets: truthy.includes(windowOrDefault('NX_EXPLORER_MARKETS')),
|
||||
txsList: truthy.includes(windowOrDefault('NX_EXPLORER_TXS_LIST')),
|
||||
networkParameters: truthy.includes(
|
||||
windowOrDefault('NX_EXPLORER_NETWORK_PARAMETERS')
|
||||
),
|
||||
|
||||
@@ -12,7 +12,7 @@ import Genesis from './genesis';
|
||||
import { Block } from './blocks/id';
|
||||
import { Blocks } from './blocks/home';
|
||||
import { Tx } from './txs/id';
|
||||
import { Txs as TxHome } from './txs/home';
|
||||
import { TxsHome, TxsHomeFallback } from './txs/home';
|
||||
import { PendingTxs } from './pending';
|
||||
import flags from '../config/flags';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
@@ -129,7 +129,7 @@ const routerConfig = [
|
||||
},
|
||||
{
|
||||
index: true,
|
||||
element: <TxHome />,
|
||||
element: flags.txsList ? <TxsHome /> : <TxsHomeFallback />,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,32 +1,130 @@
|
||||
import type { TendermintBlockchainResponse } from '../../blocks/tendermint-blockchain-response';
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import { useCallback, useState, useMemo } from 'react';
|
||||
import { t, useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { RouteTitle } from '../../../components/route-title';
|
||||
import { BlocksRefetch } from '../../../components/blocks';
|
||||
import { RenderFetched } from '../../../components/render-fetched';
|
||||
import { BlockTxsData } from '../../../components/txs';
|
||||
import { JumpToBlock } from '../../../components/jump-to-block';
|
||||
import { t, useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { TxsInfiniteList } from '../../../components/txs';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ChainExplorerTxResponse } from '../../types/chain-explorer-response';
|
||||
import type { TendermintBlockchainResponse } from '../../blocks/tendermint-blockchain-response';
|
||||
|
||||
const Txs = () => {
|
||||
const {
|
||||
state: { data, error, loading },
|
||||
refetch,
|
||||
} = useFetch<TendermintBlockchainResponse>(
|
||||
`${DATA_SOURCES.tendermintUrl}/blockchain`
|
||||
interface TxsProps {
|
||||
latestBlockHeight: string;
|
||||
}
|
||||
|
||||
interface TxsStateProps {
|
||||
txsData: ChainExplorerTxResponse[];
|
||||
hasMoreTxs: boolean;
|
||||
nextPage: number;
|
||||
}
|
||||
|
||||
const Txs = ({ latestBlockHeight }: TxsProps) => {
|
||||
const [{ txsData, hasMoreTxs, nextPage }, setTxsState] =
|
||||
useState<TxsStateProps>({
|
||||
txsData: [],
|
||||
hasMoreTxs: true,
|
||||
nextPage: 1,
|
||||
});
|
||||
|
||||
const reusedBodyParams = useMemo(
|
||||
() => ({
|
||||
node_url: DATA_SOURCES.tendermintUrl,
|
||||
transaction_height: parseInt(latestBlockHeight),
|
||||
page_size: 30,
|
||||
}),
|
||||
[latestBlockHeight]
|
||||
);
|
||||
|
||||
const {
|
||||
state: { error, loading },
|
||||
refetch,
|
||||
} = useFetch(
|
||||
DATA_SOURCES.chainExplorerUrl,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(reusedBodyParams),
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
const loadTxs = useCallback(async () => {
|
||||
const data = await refetch(
|
||||
undefined,
|
||||
JSON.stringify({
|
||||
...reusedBodyParams,
|
||||
page_number: nextPage,
|
||||
})
|
||||
);
|
||||
|
||||
if (data) {
|
||||
setTxsState((prev) => ({
|
||||
...prev,
|
||||
nextPage: prev.nextPage + 1,
|
||||
hasMoreTxs: true,
|
||||
txsData: [...prev.txsData, ...(data as ChainExplorerTxResponse[])],
|
||||
}));
|
||||
}
|
||||
}, [nextPage, refetch, reusedBodyParams]);
|
||||
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle>{t('Transactions')}</RouteTitle>
|
||||
<RenderFetched error={error} loading={loading}>
|
||||
<>
|
||||
<BlocksRefetch refetch={refetch} />
|
||||
<BlockTxsData data={data} />
|
||||
</>
|
||||
</RenderFetched>
|
||||
<BlocksRefetch
|
||||
refetch={() =>
|
||||
refetch(
|
||||
undefined,
|
||||
JSON.stringify({
|
||||
...reusedBodyParams,
|
||||
page_number: 1,
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<TxsInfiniteList
|
||||
hasMoreTxs={hasMoreTxs}
|
||||
areTxsLoading={loading}
|
||||
txs={txsData}
|
||||
loadMoreTxs={loadTxs}
|
||||
error={error}
|
||||
className="mb-28"
|
||||
/>
|
||||
<JumpToBlock />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export { Txs };
|
||||
export const TxsHome = () => {
|
||||
const {
|
||||
state: { data, error, loading },
|
||||
} = useFetch<TendermintBlockchainResponse>(
|
||||
`${DATA_SOURCES.tendermintUrl}/blockchain`
|
||||
);
|
||||
|
||||
return (
|
||||
<AsyncRenderer
|
||||
loading={!!loading}
|
||||
loadingMessage={t('Getting latest block height...')}
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('Could not get latest block height')}
|
||||
render={(data) => (
|
||||
<Txs
|
||||
latestBlockHeight={
|
||||
data?.result?.block_metas?.[0]?.header?.height || ''
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const TxsHomeFallback = () => (
|
||||
<>
|
||||
<RouteTitle>{t('Transactions')}</RouteTitle>
|
||||
<div>
|
||||
The transactions list is currently disabled. Please use the search bar to
|
||||
discover transaction data
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
const { execSync } = require('child_process');
|
||||
const webpack = require('webpack');
|
||||
const SentryPlugin = require('@sentry/webpack-plugin');
|
||||
|
||||
const gitCommitHash = execSync('git rev-parse HEAD').toString();
|
||||
const gitOriginUrl = execSync('git remote get-url origin')
|
||||
.toString()
|
||||
.replace('ssh://git@github.com', 'https://github.com')
|
||||
.replace('.git', '');
|
||||
|
||||
module.exports = (config, context) => {
|
||||
const additionalPlugins = process.env.SENTRY_AUTH_TOKEN
|
||||
? [
|
||||
@@ -9,8 +17,16 @@ module.exports = (config, context) => {
|
||||
}),
|
||||
]
|
||||
: [];
|
||||
|
||||
return {
|
||||
...config,
|
||||
plugins: [...additionalPlugins, ...config.plugins],
|
||||
plugins: [
|
||||
...additionalPlugins,
|
||||
...config.plugins,
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.GIT_COMMIT_HASH': JSON.stringify(gitCommitHash),
|
||||
'process.env.GIT_ORIGIN_URL': JSON.stringify(gitOriginUrl),
|
||||
}),
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
module.exports = defineConfig({
|
||||
projectId: 'et4snf',
|
||||
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:4200',
|
||||
fileServerFolder: '.',
|
||||
fixturesFolder: false,
|
||||
specPattern: './src/integration/*.ts',
|
||||
excludeSpecPattern: '**/*.js',
|
||||
modifyObstructiveCode: false,
|
||||
supportFile: './src/support/index.ts',
|
||||
video: true,
|
||||
videosFolder: '../../dist/cypress/apps/explorer-e2e/videos',
|
||||
screenshotsFolder: '../../dist/cypress/apps/explorer-e2e/screenshots',
|
||||
chromeWebSecurity: false,
|
||||
},
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:4200",
|
||||
"fileServerFolder": ".",
|
||||
"testFiles": "*.{ts,feature,features}",
|
||||
"ignoreTestFiles": "**/*.js",
|
||||
"fixturesFolder": "./src/fixtures",
|
||||
"integrationFolder": "./src/integration",
|
||||
"modifyObstructiveCode": false,
|
||||
"supportFile": "./src/support/index.ts",
|
||||
"pluginsFile": false,
|
||||
"video": true,
|
||||
"videosFolder": "../../dist/cypress/apps/simple-trading-app-e2e/videos",
|
||||
"screenshotsFolder": "../../dist/cypress/apps/simple-trading-app-e2e/screenshots",
|
||||
"chromeWebSecurity": false,
|
||||
"projectId": "et4snf"
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
"e2e": {
|
||||
"executor": "@nrwl/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/simple-trading-app-e2e/cypress.json",
|
||||
"cypressConfig": "apps/simple-trading-app-e2e/cypress.config.js",
|
||||
"devServerTarget": "simple-trading-app:serve"
|
||||
},
|
||||
"configurations": {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
describe('console lite header', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.setItem('theme', 'dark');
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
it('logo should linked home', () => {
|
||||
cy.get('span').contains('Markets').click();
|
||||
cy.location('pathname').should('eq', '/markets');
|
||||
cy.getByTestId('header').find('a').click();
|
||||
cy.location('pathname').should('eq', '/');
|
||||
});
|
||||
|
||||
it('theme switcher should switch theme', () => {
|
||||
cy.get('#root').children().eq(0).as('Container');
|
||||
cy.get('@Container').should('have.css', 'background-color', 'rgb(8, 8, 8)');
|
||||
cy.getByTestId('theme-switcher').click();
|
||||
cy.get('@Container').should(
|
||||
'have.css',
|
||||
'background-color',
|
||||
'rgb(255, 255, 255)'
|
||||
);
|
||||
});
|
||||
|
||||
it('wallet connector should open a dialog', () => {
|
||||
cy.get('[role="dialog"]').should('not.exist');
|
||||
cy.getByTestId('connect-vega-wallet').click();
|
||||
cy.get('[role="dialog"]').should('be.visible');
|
||||
});
|
||||
});
|
||||
@@ -60,7 +60,7 @@ describe('market list', () => {
|
||||
cy.intercept('POST', '/query').as('Filters');
|
||||
cy.visit('/markets');
|
||||
cy.wait('@Filters').then((filters) => {
|
||||
if (filters?.response?.body.data.markets.length) {
|
||||
if (filters?.response?.body?.data?.markets?.length) {
|
||||
const asset =
|
||||
filters.response.body.data.markets[0].tradableInstrument.instrument
|
||||
.product.settlementAsset.symbol;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
@@ -4,7 +4,7 @@
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/web:webpack",
|
||||
"executor": "./tools/executors/webpack:build",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
@@ -41,7 +41,7 @@
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "./tools/executors/serve:serve",
|
||||
"executor": "./tools/executors/webpack:serve",
|
||||
"options": {
|
||||
"buildTarget": "simple-trading-app:build",
|
||||
"hmr": true,
|
||||
@@ -68,6 +68,15 @@
|
||||
"jestConfig": "apps/simple-trading-app/jest.config.js",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
},
|
||||
"build-netlify": {
|
||||
"builder": "@nrwl/workspace:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"cp apps/simple-trading-app/netlify.toml netlify.toml",
|
||||
"nx build simple-trading-app"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
|
||||
@@ -8,13 +8,11 @@ import {
|
||||
VegaManageDialog,
|
||||
VegaWalletProvider,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { VegaWalletConnectButton } from './components/vega-wallet-connect-button';
|
||||
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
|
||||
import { Connectors } from './lib/vega-connectors';
|
||||
import '../styles.scss';
|
||||
import { AppLoader } from './components/app-loader';
|
||||
import Header from './components/header';
|
||||
import { Main } from './components/main';
|
||||
import { DrawerToggle, DRAWER_TOGGLE_VARIANTS } from './components/drawer';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
function App() {
|
||||
@@ -39,32 +37,12 @@ function App() {
|
||||
<NetworkLoader createClient={createClient}>
|
||||
<VegaWalletProvider>
|
||||
<AppLoader>
|
||||
<div className="max-h-full min-h-full dark:bg-black dark:text-white-60 bg-white text-black-60 grid grid-rows-[min-content,1fr]">
|
||||
<div className="flex items-stretch p-16 bg-black text-white-60">
|
||||
<div className="flex items-center gap-4 ml-auto mr-8">
|
||||
<VegaWalletConnectButton
|
||||
setConnectDialog={(open) =>
|
||||
setVegaWallet((x) => ({ ...x, connect: open }))
|
||||
}
|
||||
setManageDialog={(open) =>
|
||||
setVegaWallet((x) => ({ ...x, manage: open }))
|
||||
}
|
||||
/>
|
||||
<ThemeSwitcher
|
||||
onToggle={toggleTheme}
|
||||
className="-my-4"
|
||||
sunClassName="text-white"
|
||||
/>
|
||||
</div>
|
||||
<DrawerToggle
|
||||
onToggle={onToggle}
|
||||
variant={DRAWER_TOGGLE_VARIANTS.OPEN}
|
||||
className="xs:py-32 xs:px-16 xs:text-white xs:hover:text-blue"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-white-60 bg-white text-black-60 grid grid-rows-[min-content,1fr]">
|
||||
<Header
|
||||
setVegaWallet={setVegaWallet}
|
||||
toggleTheme={toggleTheme}
|
||||
/>
|
||||
<Main isMenuOpen={menuOpen} onToggle={onToggle} />
|
||||
|
||||
<VegaConnectDialog
|
||||
connectors={Connectors}
|
||||
dialogOpen={vegaWallet.connect}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import Video from '../header/video';
|
||||
import Comet from '../header/comet';
|
||||
import Star from '../icons/star';
|
||||
|
||||
const Baubles = () => {
|
||||
return (
|
||||
<div className="relative right-0 top-0 h-[700px] hidden md:block md:w-1/2 overflow-hidden">
|
||||
<div className="absolute top-[100px] w-[393px] left-[19%] h-[517px]">
|
||||
<div className="absolute top-[82px] right-[34px] w-[100px] h-[100px] clip-path-rounded">
|
||||
<Video />
|
||||
</div>
|
||||
<div className="absolute bottom-[100px] left-[59px] w-[200px] h-[200px] clip-path-rounded">
|
||||
<Video />
|
||||
</div>
|
||||
<div className="absolute w-[118px] h-[85px] right-0 bottom-[178px]">
|
||||
<Comet />
|
||||
</div>
|
||||
<div className="absolute w-[118px] h-[82px] left-0 bottom-[120px]">
|
||||
<Comet />
|
||||
</div>
|
||||
<div className="absolute w-[20px] h-[20px] top-0 left-[49px]">
|
||||
<Star />
|
||||
</div>
|
||||
<div className="absolute w-[20px] h-[20px] top-[89px] left-[184px]">
|
||||
<Star />
|
||||
</div>
|
||||
<div className="absolute w-[10px] h-[10px] bottom-0 right-[137px]">
|
||||
<Star />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Baubles;
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import {
|
||||
DealTicketManager,
|
||||
@@ -8,6 +9,7 @@ import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { DealTicketBalance } from './deal-ticket-balance';
|
||||
import type { PartyBalanceQuery } from './__generated__/PartyBalanceQuery';
|
||||
import Baubles from './baubles-decor';
|
||||
|
||||
const tempEmptyText = <p>Please select a market from the markets page</p>;
|
||||
|
||||
@@ -39,27 +41,34 @@ export const DealTicketContainer = () => {
|
||||
}
|
||||
);
|
||||
|
||||
return marketId ? (
|
||||
<Container marketId={marketId}>
|
||||
{(data) => (
|
||||
<DealTicketManager market={data.market}>
|
||||
{loading ? (
|
||||
'Loading...'
|
||||
) : (
|
||||
<DealTicketBalance
|
||||
settlementAsset={
|
||||
data.market.tradableInstrument.instrument.product
|
||||
?.settlementAsset
|
||||
}
|
||||
accounts={partyData?.party?.accounts || []}
|
||||
isWalletConnected={!!keypair?.pub}
|
||||
/>
|
||||
)}
|
||||
<DealTicketSteps market={data.market} />
|
||||
</DealTicketManager>
|
||||
)}
|
||||
</Container>
|
||||
) : (
|
||||
tempEmptyText
|
||||
return (
|
||||
<div className="flex">
|
||||
<div className="md:w-1/2 md:min-w-[500px]">
|
||||
{marketId ? (
|
||||
<Container marketId={marketId}>
|
||||
{(data) => (
|
||||
<DealTicketManager market={data.market}>
|
||||
{loading ? (
|
||||
'Loading...'
|
||||
) : (
|
||||
<DealTicketBalance
|
||||
settlementAsset={
|
||||
data.market.tradableInstrument.instrument.product
|
||||
?.settlementAsset
|
||||
}
|
||||
accounts={partyData?.party?.accounts || []}
|
||||
isWalletConnected={!!keypair?.pub}
|
||||
/>
|
||||
)}
|
||||
<DealTicketSteps market={data.market} />
|
||||
</DealTicketManager>
|
||||
)}
|
||||
</Container>
|
||||
) : (
|
||||
tempEmptyText
|
||||
)}
|
||||
</div>
|
||||
<Baubles />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,6 +8,6 @@ interface Props {
|
||||
}
|
||||
|
||||
export const DrawerWrapper = ({ children, className = '' }: Props) => {
|
||||
const classes = classNames('flex dark:bg-black md:flex-row', className);
|
||||
const classes = classNames('flex dark:bg-lite-black md:flex-row', className);
|
||||
return <div className={classes}>{children}</div>;
|
||||
};
|
||||
|
||||
@@ -34,11 +34,14 @@ export const NavigationDrawer = ({
|
||||
|
||||
const translateClose = rtl ? 'translate-x-full' : '-translate-x-full';
|
||||
|
||||
const innerStyles = classNames('w-3/4 md:w-full bg-white dark:bg-black', {
|
||||
'translate-x-0 transition-transform md:transform-none': isMenuOpen,
|
||||
[`${translateClose} md:transform-none`]: !isMenuOpen,
|
||||
[innerClasses]: innerClasses,
|
||||
});
|
||||
const innerStyles = classNames(
|
||||
'w-3/4 md:w-full bg-white dark:bg-lite-black',
|
||||
{
|
||||
'translate-x-0 transition-transform md:transform-none': isMenuOpen,
|
||||
[`${translateClose} md:transform-none`]: !isMenuOpen,
|
||||
[innerClasses]: innerClasses,
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<aside aria-label="Sidebar Navigation Menu" className={outerStyles}>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
|
||||
const Comet = () => {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 118 82"
|
||||
fill="currentColor"
|
||||
className="max-w-[7.5rem] mx-auto"
|
||||
>
|
||||
<g className="fill-black dark:fill-white">
|
||||
<path d="M44.3791 67.5864H41.5859V70.3796H44.3791V67.5864Z"></path>
|
||||
<path d="M47.173 64.7932V62H44.3799V64.7932V67.5863H47.173V64.7932Z"></path>
|
||||
<path d="M41.5863 70.3794H36V73.1726H41.5863V70.3794Z"></path>
|
||||
<path d="M44.3791 73.1719H41.5859V75.965H44.3791V73.1719Z"></path>
|
||||
<path d="M47.173 75.9658H44.3799V81.5521H47.173V75.9658Z"></path>
|
||||
<path d="M49.966 73.1719H47.1729V75.965H49.966V73.1719Z"></path>
|
||||
<path d="M55.5521 70.3794H49.9658V73.1726H55.5521V70.3794Z"></path>
|
||||
<path d="M49.966 67.5864H47.1729V70.3796H49.966V67.5864Z"></path>
|
||||
<path d="M57.1876 60.564H54V63.7515H57.1876V60.564Z"></path>
|
||||
<path d="M60.3751 57.3765H57.1875V60.564H60.3751V57.3765Z"></path>
|
||||
<path d="M63.5626 54.1885H60.375V57.3761H63.5626V54.1885Z"></path>
|
||||
<path d="M66.7501 51.001H63.5625V54.1886H66.7501V51.001Z"></path>
|
||||
<path d="M69.9376 47.8135H66.75V51.0011H69.9376V47.8135Z"></path>
|
||||
<path d="M73.1251 44.626H69.9375V47.8136H73.1251V44.626Z"></path>
|
||||
<path d="M76.3126 41.4385H73.125V44.6261H76.3126V41.4385Z"></path>
|
||||
<path d="M79.5001 38.251H76.3125V41.4386H79.5001V38.251Z"></path>
|
||||
<path d="M82.6886 35.0635H79.501V38.2511H82.6886V35.0635Z"></path>
|
||||
<path d="M85.8761 31.876H82.6885V35.0636H85.8761V31.876Z"></path>
|
||||
<path d="M89.0636 28.688H85.876V31.8756H89.0636V28.688Z"></path>
|
||||
<path d="M92.2511 25.5005H89.0635V28.6881H92.2511V25.5005Z"></path>
|
||||
<path d="M95.4386 22.313H92.251V25.5006H95.4386V22.313Z"></path>
|
||||
<path d="M98.6261 19.1255H95.4385V22.3131H98.6261V19.1255Z"></path>
|
||||
<path d="M101.814 15.938H98.626V19.1256H101.814V15.938Z"></path>
|
||||
<path d="M105.001 12.7505H101.813V15.9381H105.001V12.7505Z"></path>
|
||||
<path d="M108.189 9.5625H105.001V12.7501H108.189V9.5625Z"></path>
|
||||
<path d="M111.376 6.375H108.188V9.56258H111.376V6.375Z"></path>
|
||||
<path d="M114.565 3.1875H111.377V6.37508H114.565V3.1875Z"></path>
|
||||
<path d="M117.752 0H114.564V3.18758H117.752V0Z"></path>
|
||||
<path d="M2.79316 20.793H0V23.5861H2.79316V20.793Z"></path>
|
||||
<path d="M5.58612 18H2.79297V20.7932H5.58612V18Z"></path>
|
||||
<path d="M5.58612 23.5859H2.79297V26.3791H5.58612V23.5859Z"></path>
|
||||
<path d="M8.37909 20.793H5.58594V23.5861H8.37909V20.793Z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default Comet;
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
|
||||
import Logo from './logo';
|
||||
import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
|
||||
|
||||
type WalletParams = {
|
||||
connect: boolean;
|
||||
manage: boolean;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
setVegaWallet: (func: (wParams: WalletParams) => WalletParams) => void;
|
||||
toggleTheme: () => void;
|
||||
}
|
||||
const Header = ({ setVegaWallet, toggleTheme }: Props) => {
|
||||
return (
|
||||
<div
|
||||
className="flex items-stretch pr-16 py-16 bg-black text-white-60"
|
||||
data-testid="header"
|
||||
>
|
||||
<Logo />
|
||||
<div className="flex items-center gap-4 ml-auto mr-8 relative z-10">
|
||||
<VegaWalletConnectButton
|
||||
setConnectDialog={(open) =>
|
||||
setVegaWallet((x) => ({ ...x, connect: open }))
|
||||
}
|
||||
setManageDialog={(open) =>
|
||||
setVegaWallet((x) => ({ ...x, manage: open }))
|
||||
}
|
||||
/>
|
||||
<ThemeSwitcher
|
||||
onToggle={toggleTheme}
|
||||
className="-my-4"
|
||||
sunClassName="text-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './header';
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { VLogo } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
const Logo = () => {
|
||||
return (
|
||||
<NavLink
|
||||
className="mx-20 text-white"
|
||||
aria-label={t('Go to home page')}
|
||||
to="/"
|
||||
>
|
||||
<VLogo />
|
||||
</NavLink>
|
||||
);
|
||||
};
|
||||
|
||||
export default Logo;
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface Props {
|
||||
width: number;
|
||||
height: number;
|
||||
className: string;
|
||||
}
|
||||
|
||||
const Video = ({ width = 60, height = 60, className = '' }: Partial<Props>) => {
|
||||
return (
|
||||
<video
|
||||
width={width}
|
||||
height={height}
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
className={classNames(
|
||||
'absolute left-0 top-0 w-full h-full object-cover',
|
||||
className
|
||||
)}
|
||||
poster="https://vega.xyz/static/poster-image.jpg"
|
||||
>
|
||||
<source
|
||||
src="https://d33wubrfki0l68.cloudfront.net/2500bc5ef1b96927e0220eeb2bef0b22b87bcda1/3e0d3/static/moshed-aa65f0933af9abe9afb5e5663c9b3f68.mp4"
|
||||
type="video/mp4"
|
||||
/>
|
||||
</video>
|
||||
);
|
||||
};
|
||||
|
||||
export default Video;
|
||||
@@ -1,8 +1,8 @@
|
||||
export const LiquidityIconPath = () => (
|
||||
<>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M12.5268 1.46612L12 1.99999L11.4732 1.46612L12 0.946381L12.5268 1.46612ZM12 3.07542C11.8274 3.25709 11.6185 3.48044 11.3826 3.73943C10.6899 4.49987 9.76793 5.56335 8.84782 6.77789C7.92587 7.99485 7.01715 9.34862 6.34179 10.6903C5.66046 12.0439 5.25 13.3205 5.25 14.4C5.25 19.0485 8.47431 22.15 12 22.15C15.5257 22.15 18.75 19.0485 18.75 14.4C18.75 13.3205 18.3395 12.0439 17.6582 10.6903C16.9829 9.34862 16.0741 7.99485 15.1522 6.77789C14.2321 5.56335 13.3101 4.49987 12.6174 3.73943C12.3815 3.48044 12.1726 3.25709 12 3.07542ZM11.4732 1.46612C11.4734 1.46597 11.4732 1.46612 12 1.99999C12.5268 1.46612 12.5266 1.46597 12.5268 1.46612L12.5336 1.47291L12.5512 1.49036C12.5663 1.5055 12.5884 1.52759 12.6169 1.55634C12.6739 1.61384 12.7566 1.698 12.8615 1.80641C13.071 2.02319 13.3692 2.33722 13.7263 2.72931C14.4399 3.51261 15.3929 4.61164 16.3478 5.8721C17.3009 7.13013 18.2671 8.56386 18.998 10.0159C19.723 11.4561 20.25 12.9795 20.25 14.4C20.25 19.7514 16.4743 23.65 12 23.65C7.52569 23.65 3.75 19.7514 3.75 14.4C3.75 12.9795 4.27704 11.4561 5.00196 10.0159C5.73285 8.56386 6.69913 7.13013 7.65218 5.8721C8.60707 4.61164 9.56014 3.51261 10.2737 2.72931C10.6308 2.33722 10.929 2.02319 11.1385 1.80641C11.2434 1.698 11.3261 1.61384 11.3831 1.55634C11.4116 1.52759 11.4337 1.5055 11.4488 1.49036L11.4664 1.47291L11.4712 1.46817L11.4732 1.46612Z"
|
||||
/>
|
||||
<rect x="11.5" y="17.4" width="1" height="1" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export const MarketIconPath = () => (
|
||||
<>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M3.5 2H2V20.5V22H3.5H22V20.5H3.5V2Z"
|
||||
/>
|
||||
<rect x="5" y="15" width="2" height="2" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export const PortfolioIconPath = () => (
|
||||
<>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M8.5 3.5H15.5V6H8.5V3.5ZM7 6V3.5C7 2.67157 7.67157 2 8.5 2H15.5C16.3284 2 17 2.67157 17 3.5V6H20.5C21.3284 6 22 6.67157 22 7.5V20.5C22 21.3284 21.3284 22 20.5 22H3.5C2.67157 22 2 21.3284 2 20.5V7.5C2 6.67157 2.67157 6 3.5 6H7ZM15.5 7.5H8.5H3.5L3.5 20.5H20.5V7.5H15.5Z"
|
||||
/>
|
||||
<rect x="4" y="8" width="2" height="2" />
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
const Star = () => {
|
||||
return (
|
||||
<svg width="100%" height="100%" viewBox="0 0 21 21" fill="currentColor">
|
||||
<g className="fill-black dark:fill-white">
|
||||
<path d="M8.99996 5.99976H6V8.99972H8.99996V5.99976Z" />
|
||||
<path d="M12.0009 2.99996V0H9.00098V2.99996V5.99993H12.0009V2.99996Z" />
|
||||
<path d="M5.99993 9H0V12H5.99993V9Z" />
|
||||
<path d="M8.99996 11.9998H6V14.9997H8.99996V11.9998Z" />
|
||||
<path d="M12.0009 15H9.00098V20.9999H12.0009V15Z" />
|
||||
<path d="M15 11.9998H12V14.9997H15V11.9998Z" />
|
||||
<path d="M20.9999 9H15V12H20.9999V9Z" />
|
||||
<path d="M15 5.99976H12V8.99972H15V5.99976Z" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default Star;
|
||||
@@ -1,13 +1,13 @@
|
||||
export const TradeIconPath = () => (
|
||||
<>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M19.3254 7.28784L14.8547 2.93099L15.7621 1.99999L21.4056 7.49983L21.8833 7.96534L21.4056 8.43085L15.7621 13.9307L14.8547 12.9997L19.3819 8.58784L1.99999 8.58784L1.99999 7.28784L19.3254 7.28784Z"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M4.55785 16.6429L9.02855 20.9997L8.12124 21.9307L2.47767 16.4309L2 15.9654L2.47767 15.4999L8.12124 10L9.02855 10.931L4.50141 15.3429L21.8833 15.3429V16.6429L4.55785 16.6429Z"
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -73,6 +73,7 @@ export const agGridLightVariables = `
|
||||
|
||||
export const agGridDarkVariables = `
|
||||
.ag-theme-balham-dark {
|
||||
--ag-background-color: ${theme.colors.lite.black};
|
||||
--ag-row-border-color: ${theme.colors.transparent};
|
||||
--ag-row-hover-color: ${theme.colors.transparent};
|
||||
--ag-font-size: 15px;
|
||||
|
||||
@@ -91,14 +91,15 @@ export const FILTERS_QUERY = gql`
|
||||
const update = (
|
||||
data: SimpleMarkets_markets[],
|
||||
delta: SimpleMarketDataSub_marketData
|
||||
) =>
|
||||
produce(data, (draft) => {
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
const index = draft.findIndex((m) => m.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index].data = delta;
|
||||
}
|
||||
// @TODO - else push new market to draft
|
||||
});
|
||||
};
|
||||
|
||||
const getData = (responseData: SimpleMarkets) => responseData.markets;
|
||||
const getDelta = (
|
||||
|
||||
+8
-7
@@ -16,11 +16,11 @@ import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import type { MarketState } from '@vegaprotocol/types';
|
||||
import useMarketsFilterData from '../../hooks/use-markets-filter-data';
|
||||
import useColumnDefinitions from '../../hooks/use-column-definitions';
|
||||
import DataProvider from './data-provider';
|
||||
import dataProvider from './data-provider';
|
||||
import * as constants from './constants';
|
||||
import SimpleMarketToolbar from './simple-market-toolbar';
|
||||
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
|
||||
|
||||
import type { SimpleMarketDataSub_marketData } from './__generated__/SimpleMarketDataSub';
|
||||
export type SimpleMarketsType = SimpleMarkets_markets & {
|
||||
percentChange?: number | '-';
|
||||
};
|
||||
@@ -44,15 +44,16 @@ const SimpleMarketList = () => {
|
||||
[]
|
||||
);
|
||||
const update = useCallback(
|
||||
(delta) => statusesRef.current[delta.market.id] === delta.market.state,
|
||||
({ delta }: { delta: SimpleMarketDataSub_marketData }) =>
|
||||
statusesRef.current[delta.market.id] === delta.market.state,
|
||||
[statusesRef]
|
||||
);
|
||||
|
||||
const { data, error, loading } = useDataProvider(
|
||||
DataProvider,
|
||||
const { data, error, loading } = useDataProvider({
|
||||
dataProvider,
|
||||
update,
|
||||
variables
|
||||
);
|
||||
variables,
|
||||
});
|
||||
const localData: Array<SimpleMarketsType> = useMarketsFilterData(
|
||||
data || [],
|
||||
params
|
||||
|
||||
+3
-6
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
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';
|
||||
@@ -50,8 +49,8 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByText('100.000%')).toBeInTheDocument();
|
||||
expect(screen.getByText('100.000%')).toHaveStyle(
|
||||
`color: ${theme.colors.vega.green}`
|
||||
expect(screen.getByText('100.000%')).toHaveClass(
|
||||
'text-darkerGreen dark:text-lightGreen'
|
||||
);
|
||||
});
|
||||
it('a depreciated one', () => {
|
||||
@@ -70,8 +69,6 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByText('-50.000%')).toBeInTheDocument();
|
||||
expect(screen.getByText('-50.000%')).toHaveStyle(
|
||||
`color: ${theme.colors.vega.pink}`
|
||||
);
|
||||
expect(screen.getByText('-50.000%')).toHaveClass('text-vega-pink');
|
||||
});
|
||||
});
|
||||
|
||||
+7
-9
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { InView } from 'react-intersection-observer';
|
||||
import { useSubscription } from '@apollo/client';
|
||||
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';
|
||||
import type {
|
||||
CandleLive,
|
||||
@@ -37,14 +37,14 @@ const getChange = (
|
||||
return ' - ';
|
||||
};
|
||||
|
||||
const getColor = (change: number | string) => {
|
||||
const getClassColor = (change: number | string) => {
|
||||
if (parseFloat(change as string) > 0) {
|
||||
return theme.colors.vega.green;
|
||||
return 'text-darkerGreen dark:text-lightGreen';
|
||||
}
|
||||
if (parseFloat(change as string) < 0) {
|
||||
return theme.colors.vega.pink;
|
||||
return 'text-vega-pink';
|
||||
}
|
||||
return theme.colors.black[10];
|
||||
return 'text-black-10';
|
||||
};
|
||||
|
||||
const SimpleMarketPercentChangeWrapper = (props: Props) => {
|
||||
@@ -67,16 +67,14 @@ const SimpleMarketPercentChange = ({ candles, marketId, setValue }: Props) => {
|
||||
variables: { marketId },
|
||||
});
|
||||
const change = getChange(candles, close);
|
||||
const color = getColor(change);
|
||||
const colorClasses = getClassColor(change);
|
||||
useEffect(() => {
|
||||
const value = parseFloat(change);
|
||||
setValue(isNaN(value) ? '-' : value);
|
||||
}, [setValue, change]);
|
||||
|
||||
return (
|
||||
<div className="flex text-center" style={{ color }}>
|
||||
{change}
|
||||
</div>
|
||||
<div className={classNames('flex text-center', colorClasses)}>{change}</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/web:webpack",
|
||||
"executor": "./tools/executors/webpack:build",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
@@ -36,7 +36,7 @@
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "./tools/executors/serve:serve",
|
||||
"executor": "./tools/executors/webpack:serve",
|
||||
"options": {
|
||||
"buildTarget": "static:build"
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@
|
||||
"tranche_end": "2022-11-26T13:48:10.000Z",
|
||||
"total_added": "100",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "41.38951674277017",
|
||||
"locked_amount": "38.99234208523592",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "100",
|
||||
@@ -242,7 +242,7 @@
|
||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||
"total_added": "1100",
|
||||
"total_removed": "673.04388635",
|
||||
"locked_amount": "318.046638762049714",
|
||||
"locked_amount": "291.677717529172953",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1000",
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||
"total_added": "1010.000000000000000001",
|
||||
"total_removed": "668.4622323651",
|
||||
"locked_amount": "292.02467307204467760028913333967529176",
|
||||
"locked_amount": "267.81317700405880230026516156139015723",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1000",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
module.exports = defineConfig({
|
||||
projectId: 'et4snf',
|
||||
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:3010',
|
||||
fileServerFolder: '.',
|
||||
fixturesFolder: false,
|
||||
specPattern: './src/integration/*.ts',
|
||||
excludeSpecPattern: '**/*.js',
|
||||
modifyObstructiveCode: false,
|
||||
supportFile: './src/support/index.ts',
|
||||
video: true,
|
||||
videosFolder: '../../dist/cypress/apps/explorer-e2e/videos',
|
||||
screenshotsFolder: '../../dist/cypress/apps/explorer-e2e/screenshots',
|
||||
chromeWebSecurity: false,
|
||||
},
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3010",
|
||||
"projectId": "et4snf",
|
||||
"fileServerFolder": ".",
|
||||
"fixturesFolder": "./src/fixtures",
|
||||
"integrationFolder": "./src/integration",
|
||||
"modifyObstructiveCode": false,
|
||||
"supportFile": "./src/support/index.ts",
|
||||
"pluginsFile": false,
|
||||
"video": true,
|
||||
"videosFolder": "../../dist/cypress/apps/stats-e2e/videos",
|
||||
"screenshotsFolder": "../../dist/cypress/apps/stats-e2e/screenshots",
|
||||
"chromeWebSecurity": false
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
"e2e": {
|
||||
"executor": "@nrwl/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/stats-e2e/cypress.json",
|
||||
"cypressConfig": "apps/stats-e2e/cypress.config.js",
|
||||
"devServerTarget": "stats:serve"
|
||||
},
|
||||
"configurations": {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/web:webpack",
|
||||
"executor": "./tools/executors/webpack:build",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
@@ -37,7 +37,7 @@
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "./tools/executors/serve:serve",
|
||||
"executor": "./tools/executors/webpack:serve",
|
||||
"options": {
|
||||
"port": 3010,
|
||||
"buildTarget": "stats:build",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
module.exports = defineConfig({
|
||||
projectId: 'et4snf',
|
||||
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:4210',
|
||||
fileServerFolder: '.',
|
||||
fixturesFolder: false,
|
||||
specPattern: '**/*.cy.{js,jsx,ts,tsx}',
|
||||
modifyObstructiveCode: false,
|
||||
supportFile: './src/support/index.ts',
|
||||
video: true,
|
||||
videosFolder: '../../dist/cypress/apps/explorer-e2e/videos',
|
||||
screenshotsFolder: '../../dist/cypress/apps/explorer-e2e/screenshots',
|
||||
chromeWebSecurity: false,
|
||||
},
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:4210",
|
||||
"projectId": "et4snf",
|
||||
"fileServerFolder": ".",
|
||||
"fixturesFolder": "./src/fixtures",
|
||||
"integrationFolder": "./src/integration",
|
||||
"modifyObstructiveCode": false,
|
||||
"supportFile": "./src/support/index.ts",
|
||||
"pluginsFile": false,
|
||||
"video": true,
|
||||
"videosFolder": "../../dist/cypress/apps/token-e2e/videos",
|
||||
"screenshotsFolder": "../../dist/cypress/apps/token-e2e/screenshots",
|
||||
"chromeWebSecurity": false
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
"e2e": {
|
||||
"executor": "@nrwl/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/token-e2e/cypress.json",
|
||||
"cypressConfig": "apps/token-e2e/cypress.config.js",
|
||||
"devServerTarget": "token:serve"
|
||||
},
|
||||
"configurations": {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import governance from '../locators/governance.locators';
|
||||
|
||||
context('Governance Page - verify elements on page', function () {
|
||||
before('navigate to governance page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.governance).click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with no network change proposals', function () {
|
||||
it('should have governance tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.governance).should('have.attr', 'aria-current');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have GOVERNANCE header visible', function () {
|
||||
cy.get(governance.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Governance');
|
||||
});
|
||||
|
||||
it('should have information box visible', function () {
|
||||
cy.get(governance.noProposals)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'There are no active network change proposals');
|
||||
});
|
||||
});
|
||||
});
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import navigation from '../../locators/navigation.locators';
|
||||
import home from '../../locators/home.locators';
|
||||
import vegaToken from '../../data/vegaToken.json';
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import home from '../locators/home.locators';
|
||||
import vegaToken from '../data/vegaToken.json';
|
||||
|
||||
context('Home Page - verify elements on page', function () {
|
||||
before('visit token home page', function () {
|
||||
@@ -0,0 +1,41 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import rewards from '../locators/rewards.locators';
|
||||
|
||||
context('Rewards Page - verify elements on page', function () {
|
||||
before('navigate to rewards page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.rewards).click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
it('should have REWARDS tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.rewards).should('have.attr', 'aria-current');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have rewards header visible', function () {
|
||||
cy.get(rewards.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Rewards');
|
||||
});
|
||||
|
||||
it('should have epoch warning', function () {
|
||||
cy.get(rewards.warning)
|
||||
.should('be.visible')
|
||||
.and(
|
||||
'have.text',
|
||||
'Rewards are credited 5 minutes after the epoch ends.This delay is set by a network parameter'
|
||||
);
|
||||
});
|
||||
|
||||
it('should have connect Vega wallet button', function () {
|
||||
cy.get(rewards.connectToVegaBtn)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Vega wallet');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,108 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import staking from '../locators/staking.locators';
|
||||
|
||||
context('Staking Page - verify elements on page', function () {
|
||||
before('navigate to staking page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.staking).click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
describe('description section', function () {
|
||||
it('should have staking tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.staking).should('have.attr', 'aria-current');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have STAKING ON VEGA header visible', function () {
|
||||
cy.get(staking.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Staking on Vega');
|
||||
});
|
||||
|
||||
it('should have Staking Guide link visible', function () {
|
||||
cy.get(staking.guideLink)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Read more about staking on Vega')
|
||||
.and(
|
||||
'have.attr',
|
||||
'href',
|
||||
'https://docs.vega.xyz/docs/mainnet/concepts/vega-chain/#staking-on-vega'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('step 1 section', function () {
|
||||
it('should have header visible', function () {
|
||||
cy.get(staking.step1).within(() => {
|
||||
cy.get(staking.sectionHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Step 1. Connect to a Vega Wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have text visible', function () {
|
||||
cy.get(staking.step1).within(() => {
|
||||
cy.get(staking.link)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Vega Wallet')
|
||||
.and('have.attr', 'href', 'https://vega.xyz/wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have connect to eth button visible', function () {
|
||||
cy.get(staking.step1).within(() => {
|
||||
cy.get(staking.connectToEthBtn)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Ethereum wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have connect to vega button visible', function () {
|
||||
cy.get(staking.step1).within(() => {
|
||||
cy.get(staking.connectToVegaBtn)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Vega wallet');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('step 2 section', function () {
|
||||
it('should have header visible', function () {
|
||||
cy.get(staking.step2).within(() => {
|
||||
cy.get(staking.sectionHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Step 2. Associate tokens with a Vega Wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have warning visible', function () {
|
||||
cy.get(staking.step2).within(() => {
|
||||
cy.get(staking.warning)
|
||||
.should('be.visible')
|
||||
.and(
|
||||
'have.text',
|
||||
'You need to connect to an Ethereum wallet first'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('step 3 section', function () {
|
||||
it('should have header visible', function () {
|
||||
cy.get(staking.step3).within(() => {
|
||||
cy.get(staking.sectionHeader)
|
||||
.should('be.visible')
|
||||
.and(
|
||||
'have.text',
|
||||
"Step 3. Select the validator you'd like to nominate"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import vesting from '../locators/vesting.locators';
|
||||
|
||||
context('Vesting Page - verify elements on page', function () {
|
||||
before('navigate to vesting page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.vesting).click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
it('should have vesting tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.vesting).should('have.attr', 'aria-current');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have VESTING header visible', function () {
|
||||
cy.get(vesting.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Vesting');
|
||||
});
|
||||
|
||||
it('should have connect Eth wallet info', function () {
|
||||
cy.get(vesting.connectPrompt).should('be.visible');
|
||||
});
|
||||
|
||||
it('should have connect Eth wallet button', function () {
|
||||
cy.get(vesting.connectButton)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Ethereum wallet');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import withdraw from '../locators/withdraw.locators';
|
||||
|
||||
context('Withdraw Page - verify elements on page', function () {
|
||||
before('navigate to withdraw page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.withdraw).click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
it('should have withdraw tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.withdraw).should('have.attr', 'aria-current');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have WITHDRAW header visible', function () {
|
||||
cy.get(withdraw.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Withdraw');
|
||||
});
|
||||
|
||||
it('should have connect Vega wallet button', function () {
|
||||
cy.get(withdraw.connectToVegaBtn)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Vega wallet');
|
||||
});
|
||||
|
||||
it('should have withdraw information box', function () {
|
||||
cy.get(withdraw.warning).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
export default {
|
||||
pageHeader: 'header h1',
|
||||
sectionHeader: 'h2',
|
||||
link: '[data-testid="link"]',
|
||||
warning: '[data-testid="callout"]',
|
||||
connectToVegaBtn: '[data-testid="connect-to-vega-wallet-btn"]',
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
noProposals: '[data-testid="no-proposals"]',
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
guideLink: '[data-testid="staking-guide-link"]',
|
||||
step1: '[data-testid="staking-step-1"]',
|
||||
step2: '[data-testid="staking-step-2"]',
|
||||
step3: '[data-testid="staking-step-3"]',
|
||||
connectToEthBtn: '[data-testid="connect-to-eth-btn"]',
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
connectPrompt: '[data-testid="eth-connect-prompt"]',
|
||||
connectButton: '[data-testid="connect-to-eth-btn"]',
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
};
|
||||
@@ -7,6 +7,9 @@ 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"}'
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
#Test configuration variables
|
||||
CYPRESS_FAIRGROUND=false
|
||||
|
||||
NX_GIT_ORIGIN_URL=git@github.com:vegaprotocol/frontend-monorepo.git
|
||||
|
||||
@@ -5,6 +5,7 @@ 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"}'
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
NX_VEGA_URL=http://localhost:3028/query
|
||||
NX_VEGA_REST=http://localhost:3029
|
||||
|
||||
@@ -5,3 +5,6 @@ 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_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
NX_GIT_ORIGIN_URL=git@github.com:vegaprotocol/frontend-monorepo.git
|
||||
@@ -5,3 +5,4 @@ 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_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -5,3 +5,4 @@ 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_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -5,3 +5,4 @@ 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_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -5,3 +5,4 @@ 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_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/web:webpack",
|
||||
"executor": "./tools/executors/webpack:build",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "./tools/executors/serve:serve",
|
||||
"executor": "./tools/executors/webpack:serve",
|
||||
"options": {
|
||||
"port": 4210,
|
||||
"buildTarget": "token:build",
|
||||
|
||||
@@ -4,7 +4,7 @@ import React, { useMemo } from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { AppLoader } from './app-loader';
|
||||
import { AppBanner } from './components/app-banner';
|
||||
import { AppFooter } from './components/app-footer';
|
||||
import { NetworkInfo } from '@vegaprotocol/network-info';
|
||||
import { BalanceManager } from './components/balance-manager';
|
||||
import { EthWallet } from './components/eth-wallet';
|
||||
import { TemplateSidebar } from './components/page-templates/template-sidebar';
|
||||
@@ -54,7 +54,9 @@ const AppContainer = () => {
|
||||
<TemplateSidebar sidebar={sideBar}>
|
||||
<AppRouter />
|
||||
</TemplateSidebar>
|
||||
<AppFooter />
|
||||
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] md:flex md:col-span-2 p-16 gap-12 border-t-1">
|
||||
<NetworkInfo />
|
||||
</footer>
|
||||
</div>
|
||||
<VegaWalletDialogs />
|
||||
<TransactionModal />
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
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>Version: {ENV.commit || 'development'}</p>
|
||||
<p>
|
||||
<Trans
|
||||
i18nKey="footerLinksText"
|
||||
components={{
|
||||
/* eslint-disable */
|
||||
feedbackLink: (
|
||||
<Link className="text-white underline" href={Links.FEEDBACK} />
|
||||
),
|
||||
githubLink: (
|
||||
<Link className="text-white underline" href={Links.GITHUB} />
|
||||
),
|
||||
/* eslint-enable */
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './app-footer';
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
FormGroup,
|
||||
Lozenge,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -49,7 +50,10 @@ export const AmountInput = ({
|
||||
min={0}
|
||||
step="any"
|
||||
appendElement={
|
||||
<Lozenge className="text-[10px] relative top-[-2px]">
|
||||
<Lozenge
|
||||
variant={Intent.None}
|
||||
className="text-[10px] relative top-[-2px]"
|
||||
>
|
||||
{currency}
|
||||
</Lozenge>
|
||||
}
|
||||
@@ -171,7 +175,11 @@ export const TokenInput = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGroup label="" labelFor={inputName}>
|
||||
<FormGroup
|
||||
labelClassName="sr-only"
|
||||
label={t('Input Amount')}
|
||||
labelFor={inputName}
|
||||
>
|
||||
<AmountInput
|
||||
amount={amount}
|
||||
setAmount={setAmount}
|
||||
|
||||
@@ -22,6 +22,7 @@ export const VegaWalletContainer = ({ children }: VegaWalletContainerProps) => {
|
||||
return (
|
||||
<p>
|
||||
<Button
|
||||
data-testid="connect-to-vega-wallet-btn"
|
||||
onClick={() =>
|
||||
appDispatch({
|
||||
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user