Compare commits

..
Author SHA1 Message Date
Madalina Raicu c923bf7837 fix(oracles): update market-info.cy.ts 2023-05-03 10:28:50 +01:00
Madalina Raicu 633717c0e8 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-05-03 09:48:08 +01:00
Matthew Russell eefcc96149 fix(datagrid): prevent unmount of aggrid on theme change (#3588) 2023-05-03 09:45:14 +01:00
Maciek 7a99ded8e9 feat(trading): market view persistent pane sizes (#3537) 2023-05-03 09:44:45 +01:00
Madalina Raicu 4fbea2998b Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-05-03 08:29:27 +01:00
dexturr 4a4cdaa2b8 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-03 06:07:16 +00:00
dexturr cd969549ab chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-03 00:13:45 +00:00
Madalina Raicu 2396c95e35 fix(wallet): set up tests 2023-05-02 23:29:09 +01:00
Madalina Raicu 6d0ca04283 fix(oracles): fix accounts grid dropdown trigger prop remove 2023-05-02 23:24:59 +01:00
Madalina Raicu a39ff3a788 fix(oracles): update index.ts 2023-05-02 23:12:17 +01:00
Madalina Raicu 6c3772a712 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-05-02 23:11:42 +01:00
Matthew Russell 5a73b7e769 feat(trading): add generic welcome message for non mainnet networks (#3584) 2023-05-02 14:01:33 -07:00
dexturr a4f41eabb6 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-02 18:09:46 +00:00
Matthew Russell 351a20abad feat(trading,market-list): closed markets datagrid (#3429) 2023-05-02 10:41:21 -07:00
Sam Keen 8d42481130 feat(governance): eth chain should not inhibit usage (#3568) 2023-05-02 12:31:16 +00:00
dexturr 8a59722f09 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-02 12:08:21 +00:00
Sam Keen de48ffa563 feat(governance): update market proposal only available for enacted markets (#3542) 2023-05-02 10:10:03 +00:00
daro-maj 00c5252aea test(trading): ac for 6501-ASSE-assets - e2e tests (#3570) 2023-05-02 11:30:08 +02:00
Madalina Raicu 54a4b9b694 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-05-02 10:45:34 +03:00
dexturr 9acc083c11 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-02 06:09:38 +00:00
dexturr 77264e80f1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-02 00:15:50 +00:00
dexturr 50378bc8d2 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-01 18:07:37 +00:00
dexturr b88da51c68 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-01 12:08:18 +00:00
dexturr 2ae56bb113 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-01 06:07:17 +00:00
dexturr 752af9a983 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-01 00:17:06 +00:00
dexturr a01df081eb chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-30 18:07:29 +00:00
dexturr c2d14d1abe chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-30 12:10:07 +00:00
dexturr a76ff44ffd chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-30 06:09:37 +00:00
dexturr ac2e262bf3 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-30 00:16:34 +00:00
dexturr ab180875b1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-29 18:07:34 +00:00
dexturr 66d3e89b9e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-29 12:09:56 +00:00
dexturr c9cce87606 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-29 06:08:49 +00:00
dexturr 50232ab089 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-29 00:16:25 +00:00
dexturr e86fb6d0b4 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-28 18:08:10 +00:00
Madalina Raicu 3f05089e63 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-04-28 20:53:13 +03:00
Sam Keen 473ef3ae83 feat(governance): default font Alpha (#3543) 2023-04-28 17:08:36 +00:00
Edd 77ab719b37 fix(explorer): fix asset links and deterministic order details (#3567) 2023-04-28 16:00:49 +00:00
Madalina Raicu 632b5dffb8 feat(oracles): update test and storybook config 2023-04-28 16:08:55 +03:00
Edd a10f67d7ab feat(explorer): add epoch to block explorer homepage (#3536) 2023-04-28 13:08:42 +00:00
dexturr 66d2b83513 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-28 12:09:23 +00:00
dexturr e4fd040933 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-28 06:08:57 +00:00
dexturr 30c1dbd019 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-28 00:14:44 +00:00
daro-majandm.ray 5e558c4cd3 test(trading): 7001-COLL-collateral - e2e tests (#3561)
Co-authored-by: m.ray <16125548+MadalinaRaicu@users.noreply.github.com>
2023-04-27 21:28:25 +02:00
dexturr 85060a0421 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-27 18:10:05 +00:00
Sam Keen b336291b49 fix(governance): use default jsonrpc connector when the provider from useWe… (#3563) 2023-04-27 16:26:00 +00:00
Madalina Raicu 6227a2ef8d Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-04-27 18:20:15 +03:00
Joe Tsang 0f7bffd38b test(ci): capsule update v0.71.1 (#3559) 2023-04-27 14:37:55 +01:00
dexturr 3665375b75 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-27 12:09:22 +00:00
Madalina Raicu 3400f58907 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-04-27 14:12:04 +03:00
m.ray 8572c0a570 feat(trading): data grid dropdown menu in collateral table and vega icons (#3472) 2023-04-27 09:21:05 +00:00
Maciek 6a29dc82ef feat(ledger): add link for download ledger entries to .csv (#3454) 2023-04-27 08:53:28 +00:00
Bartłomiej Głownia c19bcc5e0c feat(trading): add oracle banner e2e tests (#3524) 2023-04-27 09:47:18 +01:00
Madalina Raicu 74dab3c338 fix(explorer): market details oracle build 2023-04-26 00:02:37 +03:00
Madalina Raicu a263384387 fix(oracle): globe icon and key 2023-04-25 23:31:03 +03:00
Madalina Raicu e10ea0e369 fix(oracles): fix initial layout 2023-04-25 23:26:16 +03:00
Madalina Raicu 4be343e0e5 Merge branch 'feat/data-grid-dropdown' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-04-25 15:09:31 +03:00
Madalina Raicu 1e75c3cdba Merge branch 'feat/data-grid-dropdown' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-04-25 11:21:21 +03:00
Madalina Raicu 0a81a6b7d1 Merge branch 'feat/data-grid-dropdown-icons' of github.com:vegaprotocol/frontend-monorepo into feat/oracle-basic-profile 2023-04-24 23:43:43 +03:00
Madalina Raicu 82c7939c5f fix(icons): add icons 2023-04-12 23:41:02 +03:00
Madalina Raicu 3dfd3e9470 fix(oracles): oracle basic profile bootstrap 2023-04-12 23:25:31 +03:00
179 changed files with 4043 additions and 992 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
secrets: inherit secrets: inherit
lint-test-build: lint-test-build:
timeout-minutes: 35 timeout-minutes: 60
needs: node-modules needs: node-modules
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
name: '(CI) lint + unit test + build' name: '(CI) lint + unit test + build'
+2 -2
View File
@@ -1,7 +1,7 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=http://localhost:26617 NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_ENV=CUSTOM NX_VEGA_ENV=CUSTOM
NX_VEGA_CONFIG_URL= NX_VEGA_CONFIG_URL=
@@ -18,4 +18,4 @@ NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1 NX_EXPLORER_VALIDATORS=1
CYPRESS_VEGA_WALLET_API_TOKEN= CYPRESS_VEGA_WALLET_API_TOKEN=
CYPRESS_VEGA_URL=http://localhost:3028/query CYPRESS_VEGA_URL=http://localhost:3008/graphql
+1 -1
View File
@@ -25,7 +25,7 @@ module.exports = defineConfig({
}, },
env: { env: {
environment: 'CUSTOM', environment: 'CUSTOM',
networkQueryUrl: 'http://localhost:3028/query', networkQueryUrl: 'http://localhost:3008/graphql',
ethUrl: 'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8', ethUrl: 'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
commitHash: 'dev', commitHash: 'dev',
tsConfig: 'tsconfig.json', tsConfig: 'tsconfig.json',
+18 -46
View File
@@ -9,21 +9,22 @@ context('Home Page', function () {
it('should show connected environment stats', function () { it('should show connected environment stats', function () {
const statTitles = { const statTitles = {
0: 'Status', 0: 'Status',
1: 'Block height', 1: 'Epoch',
2: 'Uptime', 2: 'Block height',
3: 'Total nodes', 3: 'Uptime',
4: 'Total staked', 4: 'Total nodes',
5: 'Backlog', 5: 'Total staked',
6: 'Trades / second', 6: 'Backlog',
7: 'Orders / block', 7: 'Trades / second',
8: 'Orders / second', 8: 'Orders / block',
9: 'Transactions / block', 9: 'Orders / second',
10: 'Block time', 10: 'Transactions / block',
11: 'Time', 11: 'Block time',
12: 'App', 12: 'Time',
13: 'Tendermint', 13: 'App',
14: 'Up since', 14: 'Tendermint',
15: 'Chain ID', 15: 'Up since',
16: 'Chain ID',
}; };
cy.get('[data-testid="stats-title"]') cy.get('[data-testid="stats-title"]')
@@ -31,42 +32,13 @@ context('Home Page', function () {
cy.wrap($list).should('contain.text', statTitles[index]); cy.wrap($list).should('contain.text', statTitles[index]);
}) })
.then(($list) => { .then(($list) => {
cy.wrap($list).should('have.length', 16); cy.wrap($list).should('have.length', 17);
}); });
cy.get(statsValue).eq(0).should('contain.text', 'CONNECTED');
cy.get(statsValue).eq(1).should('not.be.empty');
cy.get(statsValue)
.eq(2)
.invoke('text')
.should('match', /\d+d \d+h \d+m \d+s/i);
cy.get(statsValue).eq(3).should('contain.text', '2');
cy.get(statsValue)
.eq(4)
.invoke('text')
.should('match', /\d+\.\d\d(?!\d)/i);
cy.get(statsValue).eq(5).should('contain.text', '0');
cy.get(statsValue).eq(6).should('contain.text', '0');
cy.get(statsValue).eq(7).should('contain.text', '0');
cy.get(statsValue).eq(8).should('contain.text', '0');
cy.get(statsValue).eq(9).should('not.be.empty');
cy.get(statsValue).eq(10).should('not.be.empty');
cy.get(statsValue).eq(11).should('not.be.empty');
cy.get(statsValue)
.eq(12)
.invoke('text')
.should('match', /v\d+\.\d+\.\d+/i);
cy.get(statsValue)
.eq(13)
.invoke('text')
.should('match', /\d+\.\d+\.\d+/i);
cy.get(statsValue).eq(14).should('not.be.empty');
cy.get(statsValue).eq(15).should('not.be.empty');
}); });
it('Block height should be updating', function () { it('Block height should be updating', function () {
cy.get(statsValue) cy.get(statsValue)
.eq(1) .eq(2)
.invoke('text') .invoke('text')
.then((blockHeightTxt) => { .then((blockHeightTxt) => {
cy.get(statsValue) cy.get(statsValue)
@@ -6,7 +6,7 @@ const customNodeBtn = 'custom-node';
context.skip('Node switcher', { tags: '@regression' }, function () { context.skip('Node switcher', { tags: '@regression' }, function () {
beforeEach('visit home page', function () { beforeEach('visit home page', function () {
cy.intercept('GET', 'https://static.vega.xyz/assets/capsule-network.json', { cy.intercept('GET', 'https://static.vega.xyz/assets/capsule-network.json', {
hosts: ['http://localhost:3028/query'], hosts: ['http://localhost:3008/graphql'],
}).as('nodeData'); }).as('nodeData');
cy.visit('/'); cy.visit('/');
cy.wait('@nodeData'); cy.wait('@nodeData');
@@ -219,7 +219,7 @@ context.skip('Parties page', { tags: '@regression' }, function () {
balance type asset {id symbol decimals}}}}}}}}'; balance type asset {id symbol decimals}}}}}}}}';
cy.request({ cy.request({
method: 'POST', method: 'POST',
url: `http://localhost:3028/query`, url: `http://localhost:3008/graphql`,
body: { body: {
query: mutation, query: mutation,
}, },
@@ -4,7 +4,7 @@ import { t } from '@vegaprotocol/i18n';
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 { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid'; 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';
@@ -43,7 +43,7 @@ export const AssetLink = ({
if (asDialog) { if (asDialog) {
open(assetId, e.target as HTMLElement); open(assetId, e.target as HTMLElement);
} else { } else {
navigate(`${Routes.ASSETS}/${asset?.id}`); navigate(`/${Routes.ASSETS}/${asset?.id}`);
} }
}} }}
{...props} {...props}
@@ -14,7 +14,6 @@ import {
SettlementAssetInfoPanel, SettlementAssetInfoPanel,
} from '@vegaprotocol/market-info'; } from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info'; import { MarketInfoTable } from '@vegaprotocol/market-info';
import { Link } from 'react-router-dom';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => { export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
if (!market) return null; if (!market) return null;
@@ -97,22 +96,19 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
), ),
}, },
{ {
title: t('Oracle'), title: t('Settlement Oracle'),
content: ( content: (
<OracleInfoPanel noBorder={false} market={market}> <OracleInfoPanel
<Link noBorder={false}
className="text-xs hover:underline" market={market}
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`} type="settlementData"
> />
{t('View settlement data oracle specification')} ),
</Link> },
<Link {
className="text-xs hover:underline" title: t('Termination Oracle'),
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForTradingTermination.id}`} content: (
> <OracleInfoPanel noBorder={false} market={market} type="termination" />
{t('View termination oracle specification')}
</Link>
</OracleInfoPanel>
), ),
}, },
]; ];
@@ -3,7 +3,7 @@ import { t } from '@vegaprotocol/i18n';
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 { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import type { import type {
VegaICellRendererParams, VegaICellRendererParams,
VegaValueGetterParams, VegaValueGetterParams,
@@ -9,7 +9,7 @@ import SizeInMarket from '../size-in-market/size-in-market';
export interface DeterministicOrderDetailsProps { export interface DeterministicOrderDetailsProps {
id: string; id: string;
// Version to fetch, with 0 being 'latest' and 1 being 'first'. Defaults to 0 // Version to fetch, with 0 being 'latest' and 1 being 'first'. Defaults to 0
version?: number; version?: number | null;
} }
export const wrapperClasses = export const wrapperClasses =
@@ -28,7 +28,7 @@ export const wrapperClasses =
*/ */
const DeterministicOrderDetails = ({ const DeterministicOrderDetails = ({
id, id,
version = 0, version = null,
}: DeterministicOrderDetailsProps) => { }: DeterministicOrderDetailsProps) => {
const { data, error } = useExplorerDeterministicOrderQuery({ const { data, error } = useExplorerDeterministicOrderQuery({
variables: { orderId: id, version }, variables: { orderId: id, version },
@@ -3,7 +3,7 @@ import { VoteProgress } from '@vegaprotocol/proposals';
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 { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid'; import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import type { import type {
VegaICellRendererParams, VegaICellRendererParams,
VegaValueFormatterParams, VegaValueFormatterParams,
@@ -71,7 +71,7 @@ export const PartyAccounts = ({ accounts }: PartyAccountsProps) => {
/> />
</td> </td>
<td className="text-md"> <td className="text-md">
<AssetLink assetId={account.asset.id} /> <AssetLink assetId={account.asset.id} asDialog={true} />
</td> </td>
</TableRow> </TableRow>
); );
+44
View File
@@ -1,3 +1,7 @@
@import 'ag-grid-community/dist/styles/ag-grid.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
/* You can add global styles to this file, and also import other style files */ /* You can add global styles to this file, and also import other style files */
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@@ -11,3 +15,43 @@
.react-markdown-container a:before { .react-markdown-container a:before {
content: '🔗 '; content: '🔗 ';
} }
/* AG GRID - Do not edit without updating other global stylesheets for each app */
.vega-ag-grid .ag-root-wrapper {
border: solid 0px;
}
.vega-ag-grid .ag-react-container {
overflow: hidden;
text-overflow: ellipsis;
}
.vega-ag-grid .ag-cell,
.vega-ag-grid .ag-full-width-row .ag-cell-wrapper.ag-row-group {
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
/* Light variables */
.ag-theme-balham {
--ag-background-color: theme(colors.white);
--ag-border-color: theme(colors.neutral[300]);
--ag-header-background-color: theme(colors.white);
--ag-odd-row-background-color: theme(colors.white);
--ag-header-column-separator-color: theme(colors.neutral[300]);
--ag-row-border-color: theme(colors.white);
--ag-row-hover-color: theme(colors.neutral[100]);
--ag-font-size: 12px;
}
/* Dark variables */
.ag-theme-balham-dark {
--ag-background-color: theme(colors.black);
--ag-border-color: theme(colors.neutral[700]);
--ag-header-background-color: theme(colors.black);
--ag-odd-row-background-color: theme(colors.black);
--ag-header-column-separator-color: theme(colors.neutral[600]);
--ag-row-border-color: theme(colors.black);
--ag-row-hover-color: theme(colors.neutral[800]);
--ag-font-size: 12px;
}
+2 -3
View File
@@ -5,7 +5,7 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false NX_FAIRGROUND=false
NX_VEGA_NETWORKS={} NX_VEGA_NETWORKS={}
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3008/graphql
NX_ETHEREUM_CHAIN_ID=1440 NX_ETHEREUM_CHAIN_ID=1440
NX_ETH_URL_CONNECT=1 NX_ETH_URL_CONNECT=1
NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
@@ -20,7 +20,7 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
#Test configuration variables #Test configuration variables
CYPRESS_FAIRGROUND=false CYPRESS_FAIRGROUND=false
CYPRESS_VEGA_URL=http://localhost:3028/query CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545 CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
CYPRESS_EXPLORER_URL=https://explorer.fairground.wtf CYPRESS_EXPLORER_URL=https://explorer.fairground.wtf
@@ -31,6 +31,5 @@ CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65 CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535 CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789 CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN= CYPRESS_VEGA_WALLET_API_TOKEN=
@@ -50,6 +50,8 @@ const liquidityVoteStatus = 'liquidity-votes-status';
const tokenVoteStatus = 'token-votes-status'; const tokenVoteStatus = 'token-votes-status';
const proposalTermsSection = 'proposal'; const proposalTermsSection = 'proposal';
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey'); const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
const fUSDCId =
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc';
const epochTimeout = Cypress.env('epochTimeout'); const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 }; const proposalTimeout = { timeout: 14000 };
@@ -264,7 +266,7 @@ context(
it('Unable to submit update market proposal without minimum amount of tokens', function () { it('Unable to submit update market proposal without minimum amount of tokens', function () {
vegaWalletTeardown(); vegaWalletTeardown();
vegaWalletFaucetAssetsWithoutCheck( vegaWalletFaucetAssetsWithoutCheck(
'fUSDC', fUSDCId,
'1000000', '1000000',
vegaWalletPublicKey vegaWalletPublicKey
); );
@@ -290,7 +292,7 @@ context(
// 3001-VOTE-092 3004-PMAC-001 // 3001-VOTE-092 3004-PMAC-001
it('Able to submit update market proposal and vote for proposal', function () { it('Able to submit update market proposal and vote for proposal', function () {
vegaWalletFaucetAssetsWithoutCheck( vegaWalletFaucetAssetsWithoutCheck(
'fUSDC', fUSDCId,
'1000000', '1000000',
vegaWalletPublicKey vegaWalletPublicKey
); );
@@ -55,7 +55,6 @@ context(
function () { function () {
// 2001-STKE-002, 2001-STKE-032 // 2001-STKE-002, 2001-STKE-032
before('visit staking tab and connect vega wallet', function () { before('visit staking tab and connect vega wallet', function () {
cy.clearAllLocalStorage();
cy.visit('/'); cy.visit('/');
ethereumWalletConnect(); ethereumWalletConnect();
// this is a workaround for #2422 which can be removed once issue is resolved // this is a workaround for #2422 which can be removed once issue is resolved
@@ -67,6 +66,7 @@ context(
beforeEach( beforeEach(
'teardown wallet & drill into a specific validator', 'teardown wallet & drill into a specific validator',
function () { function () {
cy.clearAllLocalStorage();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
@@ -131,7 +131,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
.within(() => { .within(() => {
cy.get('span') cy.get('span')
.first() .first()
.should('have.text', 'http://localhost:3028/query'); .should('have.text', 'http://localhost:3008/graphql');
cy.getByTestId('link').should('exist'); cy.getByTestId('link').should('exist');
}); });
}); });
@@ -17,10 +17,15 @@ const banner = 'view-banner';
context('View functionality with public key', { tags: '@smoke' }, function () { context('View functionality with public key', { tags: '@smoke' }, function () {
before('send asset to wallet', function () { before('send asset to wallet', function () {
vegaWalletFaucetAssetsWithoutCheck('fUSDC', '1000000', vegaWalletPubKey); vegaWalletFaucetAssetsWithoutCheck(
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc',
'1000000',
vegaWalletPubKey
);
}); });
beforeEach('visit home page', function () { beforeEach('visit home page', function () {
cy.clearLocalStorage();
cy.visit('/'); cy.visit('/');
waitForSpinner(); waitForSpinner();
cy.connectPublicKey(vegaWalletPubKey); cy.connectPublicKey(vegaWalletPubKey);
@@ -13,6 +13,7 @@ context(
{ tags: '@regression' }, { tags: '@regression' },
function () { function () {
before('navigate to rewards page', function () { before('navigate to rewards page', function () {
cy.clearLocalStorage();
cy.visit('/'); cy.visit('/');
navigateTo(navigation.rewards); navigateTo(navigation.rewards);
}); });
@@ -282,26 +282,30 @@ context(
describe('Vega wallet with assets', function () { describe('Vega wallet with assets', function () {
const assets = [ const assets = [
{ {
id: 'fUSDC', id: '816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc',
name: 'USDC (fake)', name: 'USDC (fake)',
symbol: 'fUSDC',
amount: '1000000', amount: '1000000',
expectedAmount: '10.00', expectedAmount: '10.00',
}, },
{ {
id: 'fDAI', id: '8566db7257222b5b7ef2886394ad28b938b28680a54a169bbc795027b89d6665',
name: 'DAI (fake)', name: 'DAI (fake)',
symbol: 'fDAI',
amount: '200000', amount: '200000',
expectedAmount: '2.00', expectedAmount: '2.00',
}, },
{ {
id: 'fBTC', id: '73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0',
name: 'BTC (fake)', name: 'BTC (fake)',
symbol: 'fBTC',
amount: '600000', amount: '600000',
expectedAmount: '6.00', expectedAmount: '6.00',
}, },
{ {
id: 'fEURO', id: 'e02d4c15d790d1d2dffaf2dcd1cf06a1fe656656cf4ed18c8ce99f9e83643567',
name: 'EURO (fake)', name: 'EURO (fake)',
symbol: 'fEURO',
amount: '800000', amount: '800000',
expectedAmount: '8.00', expectedAmount: '8.00',
}, },
@@ -322,15 +326,15 @@ context(
}); });
}); });
for (const { id, name, expectedAmount } of assets) { for (const { name, symbol, expectedAmount } of assets) {
it(`should see ${id} within vega wallet`, () => { it(`should see ${name} within vega wallet`, () => {
cy.get(walletContainer).within(() => { cy.get(walletContainer).within(() => {
cy.get(vegaWalletCurrencyTitle) cy.get(vegaWalletCurrencyTitle)
.contains(id, txTimeout) .contains(name, txTimeout)
.should('be.visible'); .should('be.visible');
cy.get(vegaWalletCurrencyTitle) cy.get(vegaWalletCurrencyTitle)
.contains(id) .contains(name)
.parent() .parent()
.siblings() .siblings()
.invoke('text') .invoke('text')
@@ -338,9 +342,9 @@ context(
.should('be.gte', parseFloat(expectedAmount)); .should('be.gte', parseFloat(expectedAmount));
cy.get(vegaWalletCurrencyTitle) cy.get(vegaWalletCurrencyTitle)
.contains(id) .contains(name)
.parent() .parent()
.contains(name); .contains(symbol);
}); });
}); });
} }
@@ -54,7 +54,7 @@ export function stakingValidatorPageRemoveStake(stake: string) {
.and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`) .and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`)
.and('be.visible') .and('be.visible')
.click(); .click();
cy.contains('been removed from validator').should('be.visible'); cy.contains('been removed from validator', txTimeout).should('be.visible');
closeDialog(); closeDialog();
} }
@@ -185,7 +185,7 @@ export function validateValidatorListTotalStakeAndShare(
) { ) {
cy.contains('Loading...', epochTimeout).should('not.exist'); cy.contains('Loading...', epochTimeout).should('not.exist');
waitForBeginningOfEpoch(); waitForBeginningOfEpoch();
cy.get(`[row-id="${positionOnList}"]:visible`) cy.get(`[row-id="${positionOnList}"]`)
.eq(1) .eq(1)
.within(() => { .within(() => {
cy.getByTestId(stakeValidatorListTotalStake, epochTimeout).should( cy.getByTestId(stakeValidatorListTotalStake, epochTimeout).should(
@@ -221,12 +221,12 @@ export function ensureSpecifiedUnstakedTokensAreAssociated(
} }
export function closeStakingDialog() { export function closeStakingDialog() {
cy.get('[data-testid="dialog-title"]:visible').should( cy.getByTestId('dialog-title').should(
'contain.text', 'contain.text',
'At the beginning of the next epoch' 'At the beginning of the next epoch'
); );
cy.get('[data-testid="dialog-content"]:visible') cy.getByTestId('dialog-content')
.first() .last()
.within(() => { .within(() => {
cy.get('a').should('have.text', 'Back to Staking').click(); cy.get('a').should('have.text', 'Back to Staking').click();
}); });
@@ -9,7 +9,7 @@ import {
import { ethers, Wallet } from 'ethers'; import { ethers, Wallet } from 'ethers';
const associatedAmountInWallet = '[data-testid="associated-amount"]:visible'; const associatedAmountInWallet = '[data-testid="associated-amount"]:visible';
const vegaWalletContainer = 'aside [data-testid="vega-wallet"]:visible'; const vegaWalletContainer = 'aside [data-testid="vega-wallet"]';
const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic'); const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic');
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey'); const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress'); const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
@@ -105,25 +105,24 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
{ timeout: transactionTimeout, log: false } { timeout: transactionTimeout, log: false }
).then((stakeBalance) => { ).then((stakeBalance) => {
if (Number(stakeBalance) != 0) { if (Number(stakeBalance) != 0) {
cy.get(vegaWalletContainer).within(() => { cy.get('[data-testid="vega-wallet-balance-unstaked"]:visible').within(
cy.getByTestId('currency-value') () => {
.invoke('text') cy.get(associatedAmountInWallet)
.then(($associatedAmount) => { .invoke('text')
cy.wrap( .then(($walletAmount) => {
stakingBridgeContract.remove_stake( cy.wrap(
String(stakeBalance), stakingBridgeContract.remove_stake(
vegaWalletPubKey String(stakeBalance),
), vegaWalletPubKey
{ timeout: transactionTimeout, log: false } ),
); { timeout: transactionTimeout, log: false }
cy.get("[data-testid='currency-value']") );
.first() cy.get(associatedAmountInWallet, {
.invoke('text', {
timeout: transactionTimeout, timeout: transactionTimeout,
}) }).should('not.have.text', $walletAmount);
.should('not.eq', $associatedAmount); });
}); }
}); );
} }
}); });
} }
+1 -1
View File
@@ -8,7 +8,7 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_CONFIG_URL='' NX_VEGA_CONFIG_URL=''
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3008/graphql
NX_ETHEREUM_CHAIN_ID=1440 NX_ETHEREUM_CHAIN_ID=1440
NX_ETH_URL_CONNECT=1 NX_ETH_URL_CONNECT=1
NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
@@ -0,0 +1,39 @@
import { render, screen } from '@testing-library/react';
import { DisconnectedNotice } from './disconnected-notice';
describe('DisconnectedNotice', () => {
it('renders Notification when isDisconnected is true and correctNetworkChainId is valid', () => {
render(
<DisconnectedNotice isDisconnected={true} correctNetworkChainId={'1'} />
);
const disconnectedNotice = screen.getByTestId('disconnected-notice');
expect(disconnectedNotice).toBeInTheDocument();
});
it("doesn't render Notification when isDisconnected is false", () => {
render(
<DisconnectedNotice isDisconnected={false} correctNetworkChainId={'1'} />
);
const disconnectedNotice = screen.queryByTestId('disconnected-notice');
expect(disconnectedNotice).not.toBeInTheDocument();
});
it("doesn't render Notification when correctNetworkChainId is undefined", () => {
render(
<DisconnectedNotice
isDisconnected={true}
correctNetworkChainId={undefined}
/>
);
const disconnectedNotice = screen.queryByTestId('disconnected-notice');
expect(disconnectedNotice).not.toBeInTheDocument();
});
it("doesn't render Notification when correctNetworkChainId is null", () => {
render(
<DisconnectedNotice isDisconnected={true} correctNetworkChainId={null} />
);
const disconnectedNotice = screen.queryByTestId('disconnected-notice');
expect(disconnectedNotice).not.toBeInTheDocument();
});
});
@@ -0,0 +1,33 @@
import { useTranslation } from 'react-i18next';
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
interface DisconnectedNoticeProps {
isDisconnected: boolean;
correctNetworkChainId?: string | null;
}
export const DisconnectedNotice = ({
isDisconnected,
correctNetworkChainId,
}: DisconnectedNoticeProps) => {
const { t } = useTranslation();
if (
!isDisconnected ||
correctNetworkChainId === undefined ||
correctNetworkChainId === null
) {
return null;
}
return (
<div className="col-span-full" data-testid="disconnected-notice">
<Notification
message={t('disconnectedNotice', {
correctNetwork: correctNetworkChainId,
})}
intent={Intent.Danger}
/>
</div>
);
};
@@ -0,0 +1 @@
export * from './disconnected-notice';
@@ -3,6 +3,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Button } from '@vegaprotocol/ui-toolkit'; import { Button } from '@vegaprotocol/ui-toolkit';
import { DisconnectedNotice } from '../disconnected-notice';
import { import {
AppStateActionType, AppStateActionType,
@@ -26,7 +27,8 @@ import {
import { Loader } from '@vegaprotocol/ui-toolkit'; import { Loader } from '@vegaprotocol/ui-toolkit';
import colors from 'tailwindcss/colors'; import colors from 'tailwindcss/colors';
import { useBalances } from '../../lib/balances/balances-store'; import { useBalances } from '../../lib/balances/balances-store';
import { useWeb3Disconnect } from '@vegaprotocol/web3'; import { useEthereumConfig, useWeb3Disconnect } from '@vegaprotocol/web3';
import { getChainName } from '@vegaprotocol/web3';
const removeLeadingAddressSymbol = (key: string) => { const removeLeadingAddressSymbol = (key: string) => {
if (key && key.length > 2 && key.slice(0, 2) === '0x') { if (key && key.length > 2 && key.slice(0, 2) === '0x') {
@@ -182,16 +184,21 @@ const ConnectedKey = () => {
export const EthWallet = () => { export const EthWallet = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { appDispatch } = useAppState(); const { appDispatch, appState } = useAppState();
const { account, connector } = useWeb3React(); const { account, connector } = useWeb3React();
const pendingTxs = usePendingTransactions(); const pendingTxs = usePendingTransactions();
const disconnect = useWeb3Disconnect(connector); const disconnect = useWeb3Disconnect(connector);
const { config } = useEthereumConfig();
return ( return (
<WalletCard> <WalletCard>
<section data-testid="ethereum-wallet"> <section data-testid="ethereum-wallet">
<WalletCardHeader> <WalletCardHeader>
<h1 className="m-0 uppercase">{t('ethereumKey')}</h1> <h1 className="m-0 uppercase">{t('ethereumKey')}</h1>
<DisconnectedNotice
isDisconnected={appState.disconnectNotice}
correctNetworkChainId={getChainName(Number(config?.chain_id))}
/>
{account && ( {account && (
<div className="place-self-end font-mono"> <div className="place-self-end font-mono">
<div <div
@@ -14,7 +14,7 @@ export const AppLayout = ({ children }: AppLayoutProps) => {
const { isReadOnly } = useVegaWallet(); const { isReadOnly } = useVegaWallet();
const AppLayoutClasses = classNames( const AppLayoutClasses = classNames(
'app w-full max-w-[1500px] mx-auto grid', 'app w-full max-w-[1500px] mx-auto grid',
'lg:text-body-large', 'font-alpha lg:text-body-large',
{ {
'grid-rows-[repeat(2,min-content)_1fr_min-content]': !isReadOnly, 'grid-rows-[repeat(2,min-content)_1fr_min-content]': !isReadOnly,
'grid-rows-[repeat(3,min-content)_1fr_min-content]': isReadOnly, 'grid-rows-[repeat(3,min-content)_1fr_min-content]': isReadOnly,
@@ -1,13 +1,12 @@
import { Button, Splash } from '@vegaprotocol/ui-toolkit'; import { Button, Splash } from '@vegaprotocol/ui-toolkit';
import { import {
getChainName,
useWeb3ConnectStore, useWeb3ConnectStore,
useWeb3Disconnect, useWeb3Disconnect,
Web3ConnectDialog, Web3ConnectDialog,
} from '@vegaprotocol/web3'; } from '@vegaprotocol/web3';
import { useWeb3React } from '@web3-react/core'; import { useWeb3React } from '@web3-react/core';
import type { ReactElement } from 'react'; import type { ReactElement } from 'react';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { import {
AppStateActionType, AppStateActionType,
useAppState, useAppState,
@@ -36,9 +35,7 @@ export function Web3Connector({
const appChainId = Number(chainId); const appChainId = Number(chainId);
return ( return (
<> <>
<Web3Content appChainId={appChainId} setDialogOpen={setDialogOpen}> <Web3Content appChainId={appChainId}>{children}</Web3Content>
{children}
</Web3Content>
<Web3ConnectDialog <Web3ConnectDialog
connectors={connectors} connectors={connectors}
dialogOpen={appState.ethConnectOverlay} dialogOpen={appState.ethConnectOverlay}
@@ -52,23 +49,59 @@ export function Web3Connector({
interface Web3ContentProps { interface Web3ContentProps {
children: ReactElement; children: ReactElement;
appChainId: number; appChainId: number;
setDialogOpen: (isOpen: boolean) => void;
} }
export const Web3Content = ({ children, appChainId }: Web3ContentProps) => { export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
const { appState, appDispatch } = useAppState();
const { connector, chainId } = useWeb3React(); const { connector, chainId } = useWeb3React();
const [previousChainId, setPreviousChainId] = useState(chainId);
const error = useWeb3ConnectStore((store) => store.error); const error = useWeb3ConnectStore((store) => store.error);
const disconnect = useWeb3Disconnect(connector); const disconnect = useWeb3Disconnect(connector);
const showDisconnectNotice = useCallback(
(isVisible: boolean) =>
appDispatch({
type: AppStateActionType.SET_DISCONNECT_NOTICE,
isVisible,
}),
[appDispatch]
);
useEffect(() => { useEffect(() => {
if (connector?.connectEagerly) { if (connector?.connectEagerly) {
connector.connectEagerly(); connector.connectEagerly();
} }
// wallet connect doesnt handle connectEagerly being called when connector is also in the // wallet connect doesn't handle connectEagerly being called when connector is also in the
// deps array. // deps array.
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
useEffect(() => {
if (chainId !== undefined) {
// We use this to detect when the user switches networks.
setPreviousChainId(chainId);
if (chainId !== appChainId) {
disconnect();
// If the user was previously connected, show the disconnect explanation notice.
if (previousChainId !== undefined && !appState.disconnectNotice) {
showDisconnectNotice(true);
}
} else if (appState.disconnectNotice) {
showDisconnectNotice(false);
}
}
}, [
appChainId,
appDispatch,
appState.disconnectNotice,
chainId,
disconnect,
previousChainId,
showDisconnectNotice,
]);
if (error) { if (error) {
return ( return (
<Splash> <Splash>
@@ -80,18 +113,5 @@ export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
); );
} }
if (chainId !== undefined && chainId !== appChainId) {
return (
<Splash>
<div className="flex flex-col items-center gap-12">
<p className="text-white">
This app only works on {getChainName(appChainId)}
</p>
<Button onClick={() => disconnect()}>Disconnect</Button>
</div>
</Splash>
);
}
return children; return children;
}; };
@@ -43,6 +43,11 @@ export interface AppState {
* Message to display in a banner at the top of the screen, currently always shown as a warning/error * Message to display in a banner at the top of the screen, currently always shown as a warning/error
*/ */
bannerMessage: string; bannerMessage: string;
/**
* Displays a notice to the user that they have been disconnected because they've changed their
* ethereum network to an incompatible one.
*/
disconnectNotice: boolean;
} }
export enum AppStateActionType { export enum AppStateActionType {
@@ -58,6 +63,7 @@ export enum AppStateActionType {
SET_ASSOCIATION_BREAKDOWN, SET_ASSOCIATION_BREAKDOWN,
SET_TRANSACTION_OVERLAY, SET_TRANSACTION_OVERLAY,
SET_BANNER_MESSAGE, SET_BANNER_MESSAGE,
SET_DISCONNECT_NOTICE,
} }
export type AppStateAction = export type AppStateAction =
@@ -90,6 +96,10 @@ export type AppStateAction =
| { | {
type: AppStateActionType.SET_BANNER_MESSAGE; type: AppStateActionType.SET_BANNER_MESSAGE;
message: string; message: string;
}
| {
type: AppStateActionType.SET_DISCONNECT_NOTICE;
isVisible: boolean;
}; };
type AppStateContextShape = { type AppStateContextShape = {
@@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import { BigNumber } from '../../lib/bignumber'; import { BigNumber } from '../../lib/bignumber';
import { AppStateActionType, AppStateContext } from './app-state-context';
import type { AppState, AppStateAction } from './app-state-context'; import type { AppState, AppStateAction } from './app-state-context';
import { AppStateActionType, AppStateContext } from './app-state-context';
interface AppStateProviderProps { interface AppStateProviderProps {
children: React.ReactNode; children: React.ReactNode;
@@ -19,6 +19,7 @@ const initialAppState: AppState = {
ethConnectOverlay: false, ethConnectOverlay: false,
transactionOverlay: false, transactionOverlay: false,
bannerMessage: '', bannerMessage: '',
disconnectNotice: false,
}; };
function appStateReducer(state: AppState, action: AppStateAction): AppState { function appStateReducer(state: AppState, action: AppStateAction): AppState {
@@ -68,6 +69,12 @@ function appStateReducer(state: AppState, action: AppStateAction): AppState {
bannerMessage: action.message, bannerMessage: action.message,
}; };
} }
case AppStateActionType.SET_DISCONNECT_NOTICE: {
return {
...state,
disconnectNotice: action.isVisible,
};
}
} }
} }
@@ -14,13 +14,17 @@ import { ContractsContext } from './contracts-context';
import { createDefaultProvider } from '../../lib/web3-connectors'; import { createDefaultProvider } from '../../lib/web3-connectors';
import { useEthereumConfig } from '@vegaprotocol/web3'; import { useEthereumConfig } from '@vegaprotocol/web3';
import { useEnvironment } from '@vegaprotocol/environment'; import { useEnvironment } from '@vegaprotocol/environment';
import { ENV } from '../../config/env'; import { ENV } from '../../config';
/** /**
* Provides Vega Ethereum contract instances to its children. * Provides Vega Ethereum contract instances to its children.
*/ */
export const ContractsProvider = ({ children }: { children: JSX.Element }) => { export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
const { provider: activeProvider, account } = useWeb3React(); const {
provider: activeProvider,
account,
chainId: activeChainId,
} = useWeb3React();
const { config } = useEthereumConfig(); const { config } = useEthereumConfig();
const { VEGA_ENV, ETHEREUM_PROVIDER_URL } = useEnvironment(); const { VEGA_ENV, ETHEREUM_PROVIDER_URL } = useEnvironment();
const [contracts, setContracts] = const [contracts, setContracts] =
@@ -39,7 +43,11 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
ETHEREUM_PROVIDER_URL, ETHEREUM_PROVIDER_URL,
Number(config.chain_id) Number(config.chain_id)
); );
const provider = activeProvider ? activeProvider : defaultProvider;
const provider =
activeProvider && activeChainId === Number(config.chain_id)
? activeProvider
: defaultProvider;
if ( if (
account && account &&
@@ -84,7 +92,14 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
// TODO: hacky quick fix for release to prevent race condition, find a better fix for this. // TODO: hacky quick fix for release to prevent race condition, find a better fix for this.
cancelled = true; cancelled = true;
}; };
}, [activeProvider, account, config, VEGA_ENV, ETHEREUM_PROVIDER_URL]); }, [
activeProvider,
activeChainId,
account,
config,
VEGA_ENV,
ETHEREUM_PROVIDER_URL,
]);
if (!contracts) { if (!contracts) {
return ( return (
@@ -790,5 +790,6 @@
"approval (% validator voting power)": "approval (% validator voting power)", "approval (% validator voting power)": "approval (% validator voting power)",
"67% voting power required": "67% voting power required", "67% voting power required": "67% voting power required",
"Token": "Token", "Token": "Token",
"associateVegaNow": "Associate $VEGA now" "associateVegaNow": "Associate $VEGA now",
"disconnectedNotice": "You have been disconnected. Connect your ETH wallet to the {{correctNetwork}} network to use this app."
} }
@@ -56,6 +56,7 @@ const mockAppState: AppState = {
ethConnectOverlay: false, ethConnectOverlay: false,
transactionOverlay: false, transactionOverlay: false,
bannerMessage: '', bannerMessage: '',
disconnectNotice: false,
}; };
jest.mock('../../../contexts/app-state/app-state-context', () => ({ jest.mock('../../../contexts/app-state/app-state-context', () => ({
@@ -19,6 +19,7 @@ const mockAppState: AppState = {
ethConnectOverlay: false, ethConnectOverlay: false,
transactionOverlay: false, transactionOverlay: false,
bannerMessage: '', bannerMessage: '',
disconnectNotice: false,
}; };
jest.mock('../../../contexts/app-state/app-state-context', () => ({ jest.mock('../../../contexts/app-state/app-state-context', () => ({
@@ -9,6 +9,9 @@ query ProposalMarketsQuery {
code code
} }
} }
proposal {
state
}
} }
} }
} }
@@ -6,7 +6,7 @@ const defaultOptions = {} as const;
export type ProposalMarketsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>; export type ProposalMarketsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ProposalMarketsQueryQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string } } } }> } | null }; export type ProposalMarketsQueryQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string } }, proposal?: { __typename?: 'Proposal', state: Types.ProposalState } | null } }> } | null };
export const ProposalMarketsQueryDocument = gql` export const ProposalMarketsQueryDocument = gql`
@@ -21,6 +21,9 @@ export const ProposalMarketsQueryDocument = gql`
code code
} }
} }
proposal {
state
}
} }
} }
} }
@@ -1,94 +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 ProposalMarketsQueryQueryVariables = Types.Exact<{
[key: string]: never;
}>;
export type ProposalMarketsQueryQuery = {
__typename?: 'Query';
marketsConnection?: {
__typename?: 'MarketConnection';
edges: Array<{
__typename?: 'MarketEdge';
node: {
__typename?: 'Market';
id: string;
tradableInstrument: {
__typename?: 'TradableInstrument';
instrument: { __typename?: 'Instrument'; name: string; code: string };
};
};
}>;
} | null;
};
export const ProposalMarketsQueryDocument = gql`
query ProposalMarketsQuery {
marketsConnection {
edges {
node {
id
tradableInstrument {
instrument {
name
code
}
}
}
}
}
}
`;
/**
* __useProposalMarketsQueryQuery__
*
* To run a query within a React component, call `useProposalMarketsQueryQuery` and pass it any options that fit your needs.
* When your component renders, `useProposalMarketsQueryQuery` 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 } = useProposalMarketsQueryQuery({
* variables: {
* },
* });
*/
export function useProposalMarketsQueryQuery(
baseOptions?: Apollo.QueryHookOptions<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>(ProposalMarketsQueryDocument, options);
}
export function useProposalMarketsQueryLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>(ProposalMarketsQueryDocument, options);
}
export type ProposalMarketsQueryQueryHookResult = ReturnType<
typeof useProposalMarketsQueryQuery
>;
export type ProposalMarketsQueryLazyQueryHookResult = ReturnType<
typeof useProposalMarketsQueryLazyQuery
>;
export type ProposalMarketsQueryQueryResult = Apollo.QueryResult<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>;
@@ -1,15 +1,16 @@
import type { MockedResponse } from '@apollo/client/testing'; import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
import { MemoryRouter as Router } from 'react-router-dom'; import { MemoryRouter as Router } from 'react-router-dom';
import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { VegaWalletContext } from '@vegaprotocol/wallet'; import { VegaWalletContext } from '@vegaprotocol/wallet';
import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider'; import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider';
import { mockWalletContext } from '../../test-helpers/mocks'; import { mockWalletContext } from '../../test-helpers/mocks';
import { ProposeUpdateMarket } from './propose-update-market'; import { ProposeUpdateMarket } from './propose-update-market';
import type { NetworkParamsQuery } from '@vegaprotocol/react-helpers'; import type { NetworkParamsQuery } from '@vegaprotocol/react-helpers';
import { NetworkParamsDocument } from '@vegaprotocol/react-helpers'; import { NetworkParamsDocument } from '@vegaprotocol/react-helpers';
import type { ProposalMarketsQueryQuery } from './__generated___/UpdateMarket'; import type { ProposalMarketsQueryQuery } from './__generated__/UpdateMarket';
import { ProposalMarketsQueryDocument } from './__generated___/UpdateMarket'; import { ProposalMarketsQueryDocument } from './__generated__/UpdateMarket';
import { ProposalState } from '@vegaprotocol/types';
const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = { const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
request: { request: {
@@ -89,6 +90,10 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
code: 'ETHiUSDT', code: 'ETHiUSDT',
}, },
}, },
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_ENACTED,
},
}, },
}, },
{ {
@@ -101,11 +106,16 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
instrument: { instrument: {
__typename: 'Instrument', __typename: 'Instrument',
name: 'Las Vegas nuggets', name: 'Las Vegas nuggets',
code: 'Nuggets2', code: 'Nuggets',
}, },
}, },
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_OPEN,
},
}, },
}, },
{ {
__typename: 'MarketEdge', __typename: 'MarketEdge',
node: { node: {
@@ -115,10 +125,14 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
__typename: 'TradableInstrument', __typename: 'TradableInstrument',
instrument: { instrument: {
__typename: 'Instrument', __typename: 'Instrument',
name: 'Nuggets', name: 'California Nuggets',
code: 'Nuggets', code: 'Nuggets2',
}, },
}, },
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_WAITING_FOR_NODE_VOTE,
},
}, },
}, },
{ {
@@ -130,10 +144,71 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
__typename: 'TradableInstrument', __typename: 'TradableInstrument',
instrument: { instrument: {
__typename: 'Instrument', __typename: 'Instrument',
name: 'CELUSD (June 2022)', name: 'Nevada Nuggets',
code: 'CELUSD', code: 'Nugetts3',
}, },
}, },
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_REJECTED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'asdfe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'NZ Nuggets',
code: 'Nugetts4',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_DECLINED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'asdfe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'Aussie Nuggets',
code: 'Nugetts5',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_PASSED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'xcvbe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'Tasmanian Nuggets',
code: 'Nugetts6',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_FAILED,
},
}, },
}, },
], ],
@@ -199,6 +274,27 @@ describe('Propose Update Market', () => {
expect(screen.getByTestId('proposal-market-select')).toHaveValue(''); expect(screen.getByTestId('proposal-market-select')).toHaveValue('');
}); });
it('should only render enacted markets', async () => {
renderComponent();
expect(
await screen.findByText('Update market proposal')
).toBeInTheDocument();
// (state enacted)
expect(screen.getByText('ETHUSD (September Market)')).toBeInTheDocument();
// (state open)
expect(screen.queryByText('Las Vegas nuggets')).not.toBeInTheDocument();
// (state waiting for node vote)
expect(screen.queryByText('California nuggets')).not.toBeInTheDocument();
// (state rejected)
expect(screen.queryByText('Nevada nuggets')).not.toBeInTheDocument();
// (state declined)
expect(screen.queryByText('NZ nuggets')).not.toBeInTheDocument();
// (state passed)
expect(screen.queryByText('Aussie nuggets')).not.toBeInTheDocument();
// (state failed)
expect(screen.queryByText('Tasmanian nuggets')).not.toBeInTheDocument();
});
it('should render the correct market details when the market select is used', async () => { it('should render the correct market details when the market select is used', async () => {
renderComponent(); renderComponent();
expect( expect(
@@ -2,25 +2,28 @@ import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { import {
doesValueEquateToParam,
getClosingTimestamp, getClosingTimestamp,
getEnactmentTimestamp, getEnactmentTimestamp,
useProposalSubmit, useProposalSubmit,
doesValueEquateToParam,
} from '@vegaprotocol/proposals'; } from '@vegaprotocol/proposals';
import { useEnvironment } from '@vegaprotocol/environment'; import { useEnvironment } from '@vegaprotocol/environment';
import { createDocsLinks, validateJson } from '@vegaprotocol/utils'; import { createDocsLinks, validateJson } from '@vegaprotocol/utils';
import { NetworkParams, useNetworkParams } from '@vegaprotocol/react-helpers'; import { NetworkParams, useNetworkParams } from '@vegaprotocol/react-helpers';
import { import {
ProposalFormDescription, ProposalFormDescription,
ProposalFormDownloadJson,
ProposalFormSubheader, ProposalFormSubheader,
ProposalFormSubmit, ProposalFormSubmit,
ProposalFormTerms, ProposalFormTerms,
ProposalFormTitle, ProposalFormTitle,
ProposalFormTransactionDialog, ProposalFormTransactionDialog,
ProposalFormDownloadJson,
ProposalFormVoteAndEnactmentDeadline, ProposalFormVoteAndEnactmentDeadline,
} from '../../components/propose'; } from '../../components/propose';
import { ProposalMinRequirements } from '../../components/shared'; import {
ProposalMinRequirements,
ProposalUserAction,
} from '../../components/shared';
import { import {
AsyncRenderer, AsyncRenderer,
ExternalLink, ExternalLink,
@@ -31,9 +34,9 @@ import {
Select, Select,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading'; import { Heading } from '../../../../components/heading';
import { ProposalUserAction } from '../../components/shared'; import { useProposalMarketsQueryQuery } from './__generated__/UpdateMarket';
import { useProposalMarketsQueryQuery } from './__generated___/UpdateMarket';
import { downloadJson } from '../../../../lib/download-json'; import { downloadJson } from '../../../../lib/download-json';
import { ProposalState } from '@vegaprotocol/types';
export interface UpdateMarketProposalFormFields { export interface UpdateMarketProposalFormFields {
proposalVoteDeadline: string; proposalVoteDeadline: string;
@@ -73,6 +76,9 @@ export const ProposeUpdateMarket = () => {
return marketsData.marketsConnection.edges return marketsData.marketsConnection.edges
.map((edge) => edge.node) .map((edge) => edge.node)
.filter(
(market) => market.proposal?.state === ProposalState.STATE_ENACTED
)
.sort((a, b) => { .sort((a, b) => {
const aName = a.tradableInstrument.instrument.name; const aName = a.tradableInstrument.instrument.name;
const bName = b.tradableInstrument.instrument.name; const bName = b.tradableInstrument.instrument.name;
@@ -3,7 +3,7 @@ import { forwardRef, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Button, Icon } from '@vegaprotocol/ui-toolkit'; import { Button, Icon } from '@vegaprotocol/ui-toolkit';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid'; import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { useAppState } from '../../../../contexts/app-state/app-state-context'; import { useAppState } from '../../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../../lib/bignumber'; import { BigNumber } from '../../../../lib/bignumber';
import { import {
@@ -17,7 +17,6 @@ import {
} from '../../shared'; } from '../../shared';
import { import {
defaultColDef, defaultColDef,
NODE_LIST_GRID_STYLES,
PendingStakeRenderer, PendingStakeRenderer,
stakedTotalPercentage, stakedTotalPercentage,
StakeShareRenderer, StakeShareRenderer,
@@ -382,12 +381,14 @@ export const ConsensusValidatorsTable = ({
); );
return ( return (
<div data-testid="consensus-validators-table"> <div
data-testid="consensus-validators-table"
className="validators-table"
>
{nodes.length > 0 && ( {nodes.length > 0 && (
<AgGrid <AgGrid
domLayout="autoHeight" domLayout="autoHeight"
style={{ width: '100%' }} style={{ width: '100%' }}
customThemeParams={NODE_LIST_GRID_STYLES}
getRowHeight={(params: RowHeightParams) => getRowHeight(params)} getRowHeight={(params: RowHeightParams) => getRowHeight(params)}
defaultColDef={defaultColDef} defaultColDef={defaultColDef}
tooltipShowDelay={0} tooltipShowDelay={0}
@@ -79,17 +79,6 @@ export interface ValidatorsTableProps {
validatorsView: ValidatorsView; validatorsView: ValidatorsView;
} }
// Custom styling to account for the scrollbar. This is needed because the
// AG Grid places the scrollbar over the bottom validator, which obstructs
export const NODE_LIST_GRID_STYLES = `
.ag-theme-balham-dark .ag-body-horizontal-scroll {
opacity: 0.75;
}
.ag-theme-balham-dark *:hover {
cursor: pointer;
}
`;
export const stakedTotalPercentage = (stakeScore: string) => export const stakedTotalPercentage = (stakeScore: string) =>
formatNumberPercentage(toBigNum(stakeScore, 0).times(100), 2); formatNumberPercentage(toBigNum(stakeScore, 0).times(100), 2);
@@ -1,7 +1,7 @@
import { forwardRef, useMemo, useRef } from 'react'; import { forwardRef, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid'; import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { useAppState } from '../../../../contexts/app-state/app-state-context'; import { useAppState } from '../../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../../lib/bignumber'; import { BigNumber } from '../../../../lib/bignumber';
import { import {
@@ -13,7 +13,6 @@ import {
} from '../../shared'; } from '../../shared';
import { import {
defaultColDef, defaultColDef,
NODE_LIST_GRID_STYLES,
StakeNeededForPromotionRenderer, StakeNeededForPromotionRenderer,
stakedTotalPercentage, stakedTotalPercentage,
ValidatorFields, ValidatorFields,
@@ -248,11 +247,13 @@ export const StandbyPendingValidatorsTable = ({
); );
return ( return (
<div data-testid="standby-pending-validators-table"> <div
data-testid="standby-pending-validators-table"
className="validators-table"
>
<AgGrid <AgGrid
domLayout="autoHeight" domLayout="autoHeight"
style={{ width: '100%' }} style={{ width: '100%' }}
customThemeParams={NODE_LIST_GRID_STYLES}
rowHeight={68} rowHeight={68}
defaultColDef={defaultColDef} defaultColDef={defaultColDef}
tooltipShowDelay={0} tooltipShowDelay={0}
+44
View File
@@ -1,3 +1,7 @@
@import 'ag-grid-community/dist/styles/ag-grid.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@@ -19,3 +23,43 @@
@apply border-vega-dark-200; @apply border-vega-dark-200;
} }
} }
/* AG GRID - Do not edit without updating other global stylesheets for each app */
.vega-ag-grid .ag-root-wrapper {
border: solid 0px;
}
.vega-ag-grid .ag-react-container {
overflow: hidden;
text-overflow: ellipsis;
}
.vega-ag-grid .ag-cell,
.vega-ag-grid .ag-full-width-row .ag-cell-wrapper.ag-row-group {
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
/* Light variables */
.ag-theme-balham {
--ag-background-color: theme(colors.white);
--ag-border-color: theme(colors.neutral[300]);
--ag-header-background-color: theme(colors.white);
--ag-odd-row-background-color: theme(colors.white);
--ag-header-column-separator-color: theme(colors.neutral[300]);
--ag-row-border-color: theme(colors.white);
--ag-row-hover-color: theme(colors.neutral[100]);
--ag-font-size: 12px;
}
/* Dark variables */
.ag-theme-balham-dark {
--ag-background-color: theme(colors.black);
--ag-border-color: theme(colors.neutral[700]);
--ag-header-background-color: theme(colors.black);
--ag-odd-row-background-color: theme(colors.black);
--ag-header-column-separator-color: theme(colors.neutral[600]);
--ag-row-border-color: theme(colors.black);
--ag-row-hover-color: theme(colors.neutral[800]);
--ag-font-size: 12px;
}
@@ -1,3 +1,3 @@
# App configuration variables # App configuration variables
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_ENV=LOCAL NX_VEGA_ENV=LOCAL
+400 -69
View File
@@ -37,8 +37,8 @@
"tranche_start": "2023-04-20T00:00:00.000Z", "tranche_start": "2023-04-20T00:00:00.000Z",
"tranche_end": "2023-05-20T00:00:00.000Z", "tranche_end": "2023-05-20T00:00:00.000Z",
"total_added": "19242.125", "total_added": "19242.125",
"total_removed": "397.984073768865", "total_removed": "959.3245960538025",
"locked_amount": "14587.4163594714507360625", "locked_amount": "10740.2904998553229338",
"deposits": [ "deposits": [
{ {
"amount": "188", "amount": "188",
@@ -221,6 +221,21 @@
"amount": "195.89040769089", "amount": "195.89040769089",
"user": "0xDd7a98557586ce21f770662319C2047C5a3bD605", "user": "0xDd7a98557586ce21f770662319C2047C5a3bD605",
"tx": "0x338ca1f2a725add8aa5328efa43ac7cb1e91c35bf01a2312431c0dbb57137387" "tx": "0x338ca1f2a725add8aa5328efa43ac7cb1e91c35bf01a2312431c0dbb57137387"
},
{
"amount": "96.6447222258",
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
"tx": "0x13b160a21d48eab98cc304bbb46cd675da08afbf6e0ad261c67c10ba34dc4d74"
},
{
"amount": "42.592326391125",
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
"tx": "0x5f544a659ae728cc7b1a29dcda14740425cadf1f47aa74bae92bf2ade3c8093d"
},
{
"amount": "422.1034736680125",
"user": "0xf915Da10e5136352Ba049acB0545Deb119054256",
"tx": "0x5932f574afe019060f5812fc89c7298ab9f768cddebe0a803c27e9914b45dc3d"
} }
], ],
"users": [ "users": [
@@ -270,11 +285,23 @@
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756", "user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
"tranche_id": 56, "tranche_id": 56,
"tx": "0x300c18b4220d3bc357f054792cb65f05d4005912bf8e5d9580b5b830cc3c0845" "tx": "0x300c18b4220d3bc357f054792cb65f05d4005912bf8e5d9580b5b830cc3c0845"
},
{
"amount": "96.6447222258",
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
"tranche_id": 56,
"tx": "0x13b160a21d48eab98cc304bbb46cd675da08afbf6e0ad261c67c10ba34dc4d74"
},
{
"amount": "42.592326391125",
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
"tranche_id": 56,
"tx": "0x5f544a659ae728cc7b1a29dcda14740425cadf1f47aa74bae92bf2ade3c8093d"
} }
], ],
"total_tokens": "1207.5", "total_tokens": "1207.5",
"withdrawn_tokens": "202.093666077975", "withdrawn_tokens": "341.3307146949",
"remaining_tokens": "1005.406333922025" "remaining_tokens": "866.1692853051"
}, },
{ {
"address": "0x33Ce1D9E53AFb7367E34749517C086405a651a95", "address": "0x33Ce1D9E53AFb7367E34749517C086405a651a95",
@@ -644,10 +671,17 @@
"tx": "0x6840e2b579765303fc31a04f43fcea1d5ccf157b46bbd1e3f3e7f6a2e6cea039" "tx": "0x6840e2b579765303fc31a04f43fcea1d5ccf157b46bbd1e3f3e7f6a2e6cea039"
} }
], ],
"withdrawals": [], "withdrawals": [
{
"amount": "422.1034736680125",
"user": "0xf915Da10e5136352Ba049acB0545Deb119054256",
"tranche_id": 56,
"tx": "0x5932f574afe019060f5812fc89c7298ab9f768cddebe0a803c27e9914b45dc3d"
}
],
"total_tokens": "1121.25", "total_tokens": "1121.25",
"withdrawn_tokens": "0", "withdrawn_tokens": "422.1034736680125",
"remaining_tokens": "1121.25" "remaining_tokens": "699.1465263319875"
}, },
{ {
"address": "0x237D23FcA6d7B2530C7614a9cB921CF27924911E", "address": "0x237D23FcA6d7B2530C7614a9cB921CF27924911E",
@@ -809,15 +843,25 @@
"tranche_id": 54, "tranche_id": 54,
"tranche_start": "2023-04-06T00:00:00.000Z", "tranche_start": "2023-04-06T00:00:00.000Z",
"tranche_end": "2023-05-06T00:00:00.000Z", "tranche_end": "2023-05-06T00:00:00.000Z",
"total_added": "8976", "total_added": "14520",
"total_removed": "596.64743517951", "total_removed": "5079.76864115505",
"locked_amount": "2615.8875925925923488", "locked_amount": "1328.5631944444439712",
"deposits": [ "deposits": [
{ {
"amount": "111", "amount": "111",
"user": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241", "user": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241",
"tx": "0x1229e077f48b796678436bfa8143cea3ae71df58b589ac922be205c4482be235" "tx": "0x1229e077f48b796678436bfa8143cea3ae71df58b589ac922be205c4482be235"
}, },
{
"amount": "5010",
"user": "0x83D7eD53E7CB97b542F1F71f40561d51F8019C8B",
"tx": "0xf0d2927bb8d9363ddefaad3783f9a0abf8e468316c4baea24766991f6cb8cdac"
},
{
"amount": "534",
"user": "0x2586bA83696a92b5467Aaa0CF9EEC052F28F2c02",
"tx": "0xf970ea0ce3e36fa0014d24bb830dd2ea0dbea06f6e53af486de5ee7e1c63e540"
},
{ {
"amount": "33", "amount": "33",
"user": "0xBf1AaB792D729fA125e6D7122D4b916a1E1C44B1", "user": "0xBf1AaB792D729fA125e6D7122D4b916a1E1C44B1",
@@ -960,6 +1004,16 @@
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9", "user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
"tx": "0x4027743264e01043ddb16676c6f7914c110df9e7212bd3f21cb6842614ce238f" "tx": "0x4027743264e01043ddb16676c6f7914c110df9e7212bd3f21cb6842614ce238f"
}, },
{
"amount": "135.13897222254",
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
"tx": "0x29905e6ae54245e824fe9ea488f491b1a3c33f6d8b9345cf2b6b00aec305c5bf"
},
{
"amount": "4347.982233753",
"user": "0x83D7eD53E7CB97b542F1F71f40561d51F8019C8B",
"tx": "0x23b713ac5ee16f744549b0c4d8b49943117d0964ca2b635d9629931ae2f4a961"
},
{ {
"amount": "5.46866782407", "amount": "5.46866782407",
"user": "0x92A1e98C6f09970e45645Cbe57c6DcaF4547c8FE", "user": "0x92A1e98C6f09970e45645Cbe57c6DcaF4547c8FE",
@@ -1007,6 +1061,43 @@
"withdrawn_tokens": "0", "withdrawn_tokens": "0",
"remaining_tokens": "111" "remaining_tokens": "111"
}, },
{
"address": "0x83D7eD53E7CB97b542F1F71f40561d51F8019C8B",
"deposits": [
{
"amount": "5010",
"user": "0x83D7eD53E7CB97b542F1F71f40561d51F8019C8B",
"tranche_id": 54,
"tx": "0xf0d2927bb8d9363ddefaad3783f9a0abf8e468316c4baea24766991f6cb8cdac"
}
],
"withdrawals": [
{
"amount": "4347.982233753",
"user": "0x83D7eD53E7CB97b542F1F71f40561d51F8019C8B",
"tranche_id": 54,
"tx": "0x23b713ac5ee16f744549b0c4d8b49943117d0964ca2b635d9629931ae2f4a961"
}
],
"total_tokens": "5010",
"withdrawn_tokens": "4347.982233753",
"remaining_tokens": "662.017766247"
},
{
"address": "0x2586bA83696a92b5467Aaa0CF9EEC052F28F2c02",
"deposits": [
{
"amount": "534",
"user": "0x2586bA83696a92b5467Aaa0CF9EEC052F28F2c02",
"tranche_id": 54,
"tx": "0xf970ea0ce3e36fa0014d24bb830dd2ea0dbea06f6e53af486de5ee7e1c63e540"
}
],
"withdrawals": [],
"total_tokens": "534",
"withdrawn_tokens": "0",
"remaining_tokens": "534"
},
{ {
"address": "0xBf1AaB792D729fA125e6D7122D4b916a1E1C44B1", "address": "0xBf1AaB792D729fA125e6D7122D4b916a1E1C44B1",
"deposits": [ "deposits": [
@@ -1219,6 +1310,12 @@
"tranche_id": 54, "tranche_id": 54,
"tx": "0x4027743264e01043ddb16676c6f7914c110df9e7212bd3f21cb6842614ce238f" "tx": "0x4027743264e01043ddb16676c6f7914c110df9e7212bd3f21cb6842614ce238f"
}, },
{
"amount": "135.13897222254",
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
"tranche_id": 54,
"tx": "0x29905e6ae54245e824fe9ea488f491b1a3c33f6d8b9345cf2b6b00aec305c5bf"
},
{ {
"amount": "155.03186111556", "amount": "155.03186111556",
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9", "user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
@@ -1245,8 +1342,8 @@
} }
], ],
"total_tokens": "858", "total_tokens": "858",
"withdrawn_tokens": "531.01030786518", "withdrawn_tokens": "666.14928008772",
"remaining_tokens": "326.98969213482" "remaining_tokens": "191.85071991228"
}, },
{ {
"address": "0x0bBf7580e036eA5D69ABe679CC90117EeC2e3dc1", "address": "0x0bBf7580e036eA5D69ABe679CC90117EeC2e3dc1",
@@ -1583,7 +1680,7 @@
"tranche_start": "2023-03-06T00:00:00.000Z", "tranche_start": "2023-03-06T00:00:00.000Z",
"tranche_end": "2023-04-06T00:00:00.000Z", "tranche_end": "2023-04-06T00:00:00.000Z",
"total_added": "14099", "total_added": "14099",
"total_removed": "3112.49002352036", "total_removed": "3142.49002352036",
"locked_amount": "0", "locked_amount": "0",
"deposits": [ "deposits": [
{ {
@@ -2348,6 +2445,11 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "30",
"user": "0xBe9F912Ad481C61B653463E8F1D2b2b310D49861",
"tx": "0x191a1901917ada560c9c30efd3d24c0ec116b9dc131a6966cc67ad7e3701df3b"
},
{ {
"amount": "30", "amount": "30",
"user": "0x8499411Bff99ddE9A02903008F917EEa0E27B42A", "user": "0x8499411Bff99ddE9A02903008F917EEa0E27B42A",
@@ -2582,10 +2684,17 @@
"tx": "0x20d505a766d3d8e376509ed8003a5b9f35fd0524f0979a5a57c7d3714d01d3e5" "tx": "0x20d505a766d3d8e376509ed8003a5b9f35fd0524f0979a5a57c7d3714d01d3e5"
} }
], ],
"withdrawals": [], "withdrawals": [
{
"amount": "30",
"user": "0xBe9F912Ad481C61B653463E8F1D2b2b310D49861",
"tranche_id": 53,
"tx": "0x191a1901917ada560c9c30efd3d24c0ec116b9dc131a6966cc67ad7e3701df3b"
}
],
"total_tokens": "30", "total_tokens": "30",
"withdrawn_tokens": "0", "withdrawn_tokens": "30",
"remaining_tokens": "30" "remaining_tokens": "0"
}, },
{ {
"address": "0xA9821681fEF27Ed817DF77E476DDDAf0aDac4443", "address": "0xA9821681fEF27Ed817DF77E476DDDAf0aDac4443",
@@ -4594,7 +4703,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z", "tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "86666.297", "total_added": "86666.297",
"total_removed": "0", "total_removed": "0",
"locked_amount": "52651.0670675174430414228", "locked_amount": "51226.896539776924515462",
"deposits": [ "deposits": [
{ {
"amount": "86666.297", "amount": "86666.297",
@@ -4660,7 +4769,7 @@
"tranche_end": "2023-06-01T00:00:00.000Z", "tranche_end": "2023-06-01T00:00:00.000Z",
"total_added": "2500", "total_added": "2500",
"total_removed": "0", "total_removed": "0",
"locked_amount": "477.23818426943425", "locked_amount": "394.848424145299",
"deposits": [ "deposits": [
{ {
"amount": "2500", "amount": "2500",
@@ -4693,7 +4802,7 @@
"tranche_end": "2023-11-01T00:00:00.000Z", "tranche_end": "2023-11-01T00:00:00.000Z",
"total_added": "15000.000000000000015", "total_added": "15000.000000000000015",
"total_removed": "0", "total_removed": "0",
"locked_amount": "15000.000000000000015", "locked_amount": "14816.165647644927014816165647644927",
"deposits": [ "deposits": [
{ {
"amount": "1.5e-14", "amount": "1.5e-14",
@@ -4781,7 +4890,7 @@
"tranche_end": "2023-09-01T00:00:00.000Z", "tranche_end": "2023-09-01T00:00:00.000Z",
"total_added": "17500", "total_added": "17500",
"total_removed": "0", "total_removed": "0",
"locked_amount": "12054.35568890901775", "locked_amount": "11483.8961541364725",
"deposits": [ "deposits": [
{ {
"amount": "12500", "amount": "12500",
@@ -5047,8 +5156,8 @@
"tranche_start": "2023-02-01T00:00:00.000Z", "tranche_start": "2023-02-01T00:00:00.000Z",
"tranche_end": "2023-08-01T00:00:00.000Z", "tranche_end": "2023-08-01T00:00:00.000Z",
"total_added": "37500", "total_added": "37500",
"total_removed": "12704.026146825", "total_removed": "17836.1796921",
"locked_amount": "19836.24443677102875", "locked_amount": "18593.57015423572875",
"deposits": [ "deposits": [
{ {
"amount": "7500", "amount": "7500",
@@ -5067,6 +5176,16 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x4dc6eefb43f5b1704894582aa926f0c6ecd94550ac354b7d5b5f49b0f17261fd" "tx": "0x4dc6eefb43f5b1704894582aa926f0c6ecd94550ac354b7d5b5f49b0f17261fd"
}, },
{
"amount": "4974.3093924",
"user": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
"tx": "0xfce75d8b6bf0d20cbdb1ef29cfabcae4f4504c30b30ca166b4e66d37f7f04339"
},
{
"amount": "157.844152875",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x6bb6303a6a322698e6e295ad38b2a22bd20d8b44306d423a3e513bb0b858ad56"
},
{ {
"amount": "126.30064455", "amount": "126.30064455",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -5231,6 +5350,12 @@
"tranche_id": 34, "tranche_id": 34,
"tx": "0x4dc6eefb43f5b1704894582aa926f0c6ecd94550ac354b7d5b5f49b0f17261fd" "tx": "0x4dc6eefb43f5b1704894582aa926f0c6ecd94550ac354b7d5b5f49b0f17261fd"
}, },
{
"amount": "157.844152875",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 34,
"tx": "0x6bb6303a6a322698e6e295ad38b2a22bd20d8b44306d423a3e513bb0b858ad56"
},
{ {
"amount": "126.30064455", "amount": "126.30064455",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -5395,8 +5520,8 @@
} }
], ],
"total_tokens": "7500", "total_tokens": "7500",
"withdrawn_tokens": "3468.576868425", "withdrawn_tokens": "3626.4210213",
"remaining_tokens": "4031.423131575" "remaining_tokens": "3873.5789787"
}, },
{ {
"address": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600", "address": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
@@ -5409,6 +5534,12 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "4974.3093924",
"user": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
"tranche_id": 34,
"tx": "0xfce75d8b6bf0d20cbdb1ef29cfabcae4f4504c30b30ca166b4e66d37f7f04339"
},
{ {
"amount": "6960.3360957", "amount": "6960.3360957",
"user": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600", "user": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
@@ -5423,8 +5554,8 @@
} }
], ],
"total_tokens": "30000", "total_tokens": "30000",
"withdrawn_tokens": "9235.4492784", "withdrawn_tokens": "14209.7586708",
"remaining_tokens": "20764.5507216" "remaining_tokens": "15790.2413292"
} }
] ]
}, },
@@ -5434,7 +5565,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z", "tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45", "total_added": "129999.45",
"total_removed": "0", "total_removed": "0",
"locked_amount": "52603.029593629619941305", "locked_amount": "51180.15844229965399674",
"deposits": [ "deposits": [
{ {
"amount": "129999.45", "amount": "129999.45",
@@ -5467,7 +5598,7 @@
"tranche_end": "2024-04-01T00:00:00.000Z", "tranche_end": "2024-04-01T00:00:00.000Z",
"total_added": "54144.7663", "total_added": "54144.7663",
"total_removed": "0", "total_removed": "0",
"locked_amount": "50260.38819220796159812442", "locked_amount": "49373.06871247784644592557",
"deposits": [ "deposits": [
{ {
"amount": "54144.7663", "amount": "54144.7663",
@@ -5500,7 +5631,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z", "tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "62600", "total_added": "62600",
"total_removed": "0", "total_removed": "0",
"locked_amount": "22080.29597919837872", "locked_amount": "21051.60226407915008",
"deposits": [ "deposits": [
{ {
"amount": "10000", "amount": "10000",
@@ -5693,7 +5824,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z", "tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000", "total_added": "5000",
"total_removed": "0", "total_removed": "0",
"locked_amount": "1955.382737189244", "locked_amount": "1873.218702435312",
"deposits": [ "deposits": [
{ {
"amount": "5000", "amount": "5000",
@@ -6233,8 +6364,8 @@
"tranche_start": "2022-11-01T00:00:00.000Z", "tranche_start": "2022-11-01T00:00:00.000Z",
"tranche_end": "2023-05-01T00:00:00.000Z", "tranche_end": "2023-05-01T00:00:00.000Z",
"total_added": "22500", "total_added": "22500",
"total_removed": "7280.725809525", "total_removed": "7438.558452225",
"locked_amount": "465.2825736648258", "locked_amount": "0",
"deposits": [ "deposits": [
{ {
"amount": "7500", "amount": "7500",
@@ -6253,6 +6384,11 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xa9dd827abcfaa4b289c6bcf5923d455380c1d4f9ce4ce615415a513df60b1ea8" "tx": "0xa9dd827abcfaa4b289c6bcf5923d455380c1d4f9ce4ce615415a513df60b1ea8"
}, },
{
"amount": "157.8326427",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xb76564ca91603758216069d7b139c683037029425e10b1694af25b478c19e26f"
},
{ {
"amount": "126.2948895", "amount": "126.2948895",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -6472,6 +6608,12 @@
"tranche_id": 33, "tranche_id": 33,
"tx": "0xa9dd827abcfaa4b289c6bcf5923d455380c1d4f9ce4ce615415a513df60b1ea8" "tx": "0xa9dd827abcfaa4b289c6bcf5923d455380c1d4f9ce4ce615415a513df60b1ea8"
}, },
{
"amount": "157.8326427",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 33,
"tx": "0xb76564ca91603758216069d7b139c683037029425e10b1694af25b478c19e26f"
},
{ {
"amount": "126.2948895", "amount": "126.2948895",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -6714,8 +6856,8 @@
} }
], ],
"total_tokens": "7500", "total_tokens": "7500",
"withdrawn_tokens": "7280.725809525", "withdrawn_tokens": "7438.558452225",
"remaining_tokens": "219.274190475" "remaining_tokens": "61.441547775"
}, },
{ {
"address": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1", "address": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1",
@@ -6740,7 +6882,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z", "tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38", "total_added": "1939928.38",
"total_removed": "1709370.7872515768348", "total_removed": "1709370.7872515768348",
"locked_amount": "189969.1598120306593902572", "locked_amount": "158090.6912451388393129414",
"deposits": [ "deposits": [
{ {
"amount": "1852091.69", "amount": "1852091.69",
@@ -9760,10 +9902,15 @@
"tranche_id": 10, "tranche_id": 10,
"tranche_start": "2021-07-15T23:37:11.000Z", "tranche_start": "2021-07-15T23:37:11.000Z",
"tranche_end": "2021-07-15T23:37:11.000Z", "tranche_end": "2021-07-15T23:37:11.000Z",
"total_added": "6459302.299000000000000001", "total_added": "6559302.299000000000000001",
"total_removed": "6413483.280000000000000001", "total_removed": "6513483.280000000000000001",
"locked_amount": "0", "locked_amount": "0",
"deposits": [ "deposits": [
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"tx": "0xfe7ab31de818986a1984617dea435e8bb02fba8fca50c1e173b5808fc8c2a81e"
},
{ {
"amount": "100000", "amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
@@ -10301,6 +10448,11 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"tx": "0xfe7ab31de818986a1984617dea435e8bb02fba8fca50c1e173b5808fc8c2a81e"
},
{ {
"amount": "100000", "amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
@@ -10781,6 +10933,12 @@
{ {
"address": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", "address": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"deposits": [ "deposits": [
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"tranche_id": 10,
"tx": "0xfe7ab31de818986a1984617dea435e8bb02fba8fca50c1e173b5808fc8c2a81e"
},
{ {
"amount": "100000", "amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
@@ -10981,6 +11139,12 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"tranche_id": 10,
"tx": "0xfe7ab31de818986a1984617dea435e8bb02fba8fca50c1e173b5808fc8c2a81e"
},
{ {
"amount": "100000", "amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
@@ -11174,8 +11338,8 @@
"tx": "0xac16a4ce688d40a482a59914d68c3a676592f8804ee8f0781b66a4ba5ccfbdfc" "tx": "0xac16a4ce688d40a482a59914d68c3a676592f8804ee8f0781b66a4ba5ccfbdfc"
} }
], ],
"total_tokens": "3256651", "total_tokens": "3356651",
"withdrawn_tokens": "3256651", "withdrawn_tokens": "3356651",
"remaining_tokens": "0" "remaining_tokens": "0"
}, },
{ {
@@ -12240,7 +12404,7 @@
"tranche_start": "2021-09-03T00:00:00.000Z", "tranche_start": "2021-09-03T00:00:00.000Z",
"tranche_end": "2022-09-03T00:00:00.000Z", "tranche_end": "2022-09-03T00:00:00.000Z",
"total_added": "57278.000000000000000003", "total_added": "57278.000000000000000003",
"total_removed": "48182.21518131551", "total_removed": "50196.35141572991",
"locked_amount": "0", "locked_amount": "0",
"deposits": [ "deposits": [
{ {
@@ -22825,6 +22989,16 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "725",
"user": "0x52Dd36AB8e8eec8f6bE968E93679838dc73b19D3",
"tx": "0xbc67aa993d42656a84c7da90e6abcc0a3c00e7e9e21da4013251b0f8582567ca"
},
{
"amount": "1289.1362344144",
"user": "0xab6dE081Af6C78433AFDaC5B756804bcE17e9eC1",
"tx": "0x9e6077e2dc83701a70b2a04028ab533e89cd7f1bb757ea4fe45e1388cfee600d"
},
{ {
"amount": "25", "amount": "25",
"user": "0x363D3d06d70761c34D6EfEB25E409A9549E6970D", "user": "0x363D3d06d70761c34D6EfEB25E409A9549E6970D",
@@ -32334,10 +32508,17 @@
"tx": "0x1a0e42b837a8f3908bc4e36e9b024f48c371b98f066a0db36fd98793cd178f57" "tx": "0x1a0e42b837a8f3908bc4e36e9b024f48c371b98f066a0db36fd98793cd178f57"
} }
], ],
"withdrawals": [], "withdrawals": [
{
"amount": "725",
"user": "0x52Dd36AB8e8eec8f6bE968E93679838dc73b19D3",
"tranche_id": 11,
"tx": "0xbc67aa993d42656a84c7da90e6abcc0a3c00e7e9e21da4013251b0f8582567ca"
}
],
"total_tokens": "725", "total_tokens": "725",
"withdrawn_tokens": "0", "withdrawn_tokens": "725",
"remaining_tokens": "725" "remaining_tokens": "0"
}, },
{ {
"address": "0xab6dE081Af6C78433AFDaC5B756804bcE17e9eC1", "address": "0xab6dE081Af6C78433AFDaC5B756804bcE17e9eC1",
@@ -33040,6 +33221,12 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "1289.1362344144",
"user": "0xab6dE081Af6C78433AFDaC5B756804bcE17e9eC1",
"tranche_id": 11,
"tx": "0x9e6077e2dc83701a70b2a04028ab533e89cd7f1bb757ea4fe45e1388cfee600d"
},
{ {
"amount": "842.29689345648", "amount": "842.29689345648",
"user": "0xab6dE081Af6C78433AFDaC5B756804bcE17e9eC1", "user": "0xab6dE081Af6C78433AFDaC5B756804bcE17e9eC1",
@@ -33084,8 +33271,8 @@
} }
], ],
"total_tokens": "3439", "total_tokens": "3439",
"withdrawn_tokens": "2149.8637655856", "withdrawn_tokens": "3439",
"remaining_tokens": "1289.1362344144" "remaining_tokens": "0"
}, },
{ {
"address": "0x23E18CBa049393DFebC5a17e3b5ec9aF584CAE04", "address": "0x23E18CBa049393DFebC5a17e3b5ec9aF584CAE04",
@@ -40567,7 +40754,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z", "tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671", "total_added": "3732368.4671",
"total_removed": "715655.108029600523393", "total_removed": "715655.108029600523393",
"locked_amount": "316417.783123780845942826482", "locked_amount": "267431.675840398797767447499",
"deposits": [ "deposits": [
{ {
"amount": "1998.95815", "amount": "1998.95815",
@@ -41959,8 +42146,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z", "tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z", "tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001", "total_added": "15870102.715470999700000001",
"total_removed": "864400.93329864929559852", "total_removed": "866687.25765937723884852",
"locked_amount": "6421684.7286343349090524101959629311219249", "locked_amount": "6247983.1374161640607671780970752321127332",
"deposits": [ "deposits": [
{ {
"amount": "16249.93", "amount": "16249.93",
@@ -42494,6 +42681,21 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x28d2b3f088965906ac3da878c491309729680c302fb98e2a435d07f88d6b962a" "tx": "0x28d2b3f088965906ac3da878c491309729680c302fb98e2a435d07f88d6b962a"
}, },
{
"amount": "381.93267176186375",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x6d5ce55a076149d5f66e5e84720d3bd46f31e5c79c54632927c1a00d1fdbce37"
},
{
"amount": "980.13570973214325",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x45de80ad7201a69e9ac4f1f964218840867adaf64a7fc6020b51baa5de37816e"
},
{
"amount": "924.25597923393625",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x2e3b57da0245aea9164e96cd7421d82a3f34df2ab34bc9a64b91e629fb5cb31c"
},
{ {
"amount": "981.387731774910625", "amount": "981.387731774910625",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -44620,6 +44822,24 @@
"tranche_id": 2, "tranche_id": 2,
"tx": "0x28d2b3f088965906ac3da878c491309729680c302fb98e2a435d07f88d6b962a" "tx": "0x28d2b3f088965906ac3da878c491309729680c302fb98e2a435d07f88d6b962a"
}, },
{
"amount": "381.93267176186375",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0x6d5ce55a076149d5f66e5e84720d3bd46f31e5c79c54632927c1a00d1fdbce37"
},
{
"amount": "980.13570973214325",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0x45de80ad7201a69e9ac4f1f964218840867adaf64a7fc6020b51baa5de37816e"
},
{
"amount": "924.25597923393625",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0x2e3b57da0245aea9164e96cd7421d82a3f34df2ab34bc9a64b91e629fb5cb31c"
},
{ {
"amount": "981.387731774910625", "amount": "981.387731774910625",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -46128,8 +46348,8 @@
} }
], ],
"total_tokens": "259998.8875", "total_tokens": "259998.8875",
"withdrawn_tokens": "154502.7650820091405", "withdrawn_tokens": "156789.08944273708375",
"remaining_tokens": "105496.1224179908595" "remaining_tokens": "103209.79805726291625"
}, },
{ {
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c", "address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
@@ -48504,8 +48724,8 @@
"tranche_start": "2021-11-05T00:00:00.000Z", "tranche_start": "2021-11-05T00:00:00.000Z",
"tranche_end": "2023-05-05T00:00:00.000Z", "tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999", "total_added": "14597706.0446472999",
"total_removed": "6129688.581848831721813882", "total_removed": "6168897.174282186485373182",
"locked_amount": "207013.1123407730577557502438032262", "locked_amount": "46652.9124232901388230326056764886",
"deposits": [ "deposits": [
{ {
"amount": "129284.449", "amount": "129284.449",
@@ -48734,6 +48954,36 @@
"user": "0xDdc5F6484349B242A9B23382Aa21f49B5Dc9a089", "user": "0xDdc5F6484349B242A9B23382Aa21f49B5Dc9a089",
"tx": "0xba1fdde929e0e2d4fe79de4dbac92cb5d20bb8b1dd7e5ff9bab961b728e7dae2" "tx": "0xba1fdde929e0e2d4fe79de4dbac92cb5d20bb8b1dd7e5ff9bab961b728e7dae2"
}, },
{
"amount": "529.38555487723284925",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x0c555d0f3b2b4b3fb50f208d9155b5886c83511a552518af11cadd5d5a06acec"
},
{
"amount": "1358.95419763598962675",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x59bc5ab04aa250d84bd2ffe62dba38ed926c26f8ac2497e9414f3a7df2b3a661"
},
{
"amount": "35040.39233886007943262",
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
"tx": "0x956f4f6e867e23aa7a3f0fb29612074de4edaf259eb1597f61b5289add0bedb2"
},
{
"amount": "4.18758350477578368",
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
"tx": "0xa83729135615d88392e9ec5164e60ae9fe049b0127c7829c44dc94ee1b28d73e"
},
{
"amount": "1289.709285120855118",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x2c531bd9c61e0a3705f161bba2c03703722f1e41533725684fcccb9176117e0e"
},
{
"amount": "985.963473355830749",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x53d67a8df4d069f956ae1eb76d5e099642dcc8d7e40fa9357be0b8ae879b90c4"
},
{ {
"amount": "1360.32447632896938825", "amount": "1360.32447632896938825",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -52052,6 +52302,30 @@
"tranche_id": 3, "tranche_id": 3,
"tx": "0xc37374c867eb2543ba3de47bf14990096f3371a93609cfd557a1eeaa3fb3e774" "tx": "0xc37374c867eb2543ba3de47bf14990096f3371a93609cfd557a1eeaa3fb3e774"
}, },
{
"amount": "529.38555487723284925",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x0c555d0f3b2b4b3fb50f208d9155b5886c83511a552518af11cadd5d5a06acec"
},
{
"amount": "1358.95419763598962675",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x59bc5ab04aa250d84bd2ffe62dba38ed926c26f8ac2497e9414f3a7df2b3a661"
},
{
"amount": "1289.709285120855118",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x2c531bd9c61e0a3705f161bba2c03703722f1e41533725684fcccb9176117e0e"
},
{
"amount": "985.963473355830749",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x53d67a8df4d069f956ae1eb76d5e099642dcc8d7e40fa9357be0b8ae879b90c4"
},
{ {
"amount": "1360.32447632896938825", "amount": "1360.32447632896938825",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -54874,8 +55148,8 @@
} }
], ],
"total_tokens": "359123.469575", "total_tokens": "359123.469575",
"withdrawn_tokens": "353628.4490036538056375", "withdrawn_tokens": "357792.4615146437139805",
"remaining_tokens": "5495.0205713461943625" "remaining_tokens": "1331.0080603562860195"
}, },
{ {
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB", "address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
@@ -55105,6 +55379,18 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "35040.39233886007943262",
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
"tranche_id": 3,
"tx": "0x956f4f6e867e23aa7a3f0fb29612074de4edaf259eb1597f61b5289add0bedb2"
},
{
"amount": "4.18758350477578368",
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
"tranche_id": 3,
"tx": "0xa83729135615d88392e9ec5164e60ae9fe049b0127c7829c44dc94ee1b28d73e"
},
{ {
"amount": "5074.06012653876566886", "amount": "5074.06012653876566886",
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8", "user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
@@ -55497,8 +55783,8 @@
} }
], ],
"total_tokens": "1266324.603486", "total_tokens": "1266324.603486",
"withdrawn_tokens": "1220819.41847917671599364", "withdrawn_tokens": "1255863.99840154157120994",
"remaining_tokens": "45505.18500682328400636" "remaining_tokens": "10460.60508445842879006"
}, },
{ {
"address": "0xC5d9221EB9c28A69859264c0A2Fe0d3272228296", "address": "0xC5d9221EB9c28A69859264c0A2Fe0d3272228296",
@@ -56332,7 +56618,7 @@
"tranche_start": "2021-10-05T00:00:00.000Z", "tranche_start": "2021-10-05T00:00:00.000Z",
"tranche_end": "2023-04-05T00:00:00.000Z", "tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "5778205.3912159303", "total_added": "5778205.3912159303",
"total_removed": "3480709.486904665102263769", "total_removed": "3480901.398845846498418769",
"locked_amount": "0", "locked_amount": "0",
"deposits": [ "deposits": [
{ {
@@ -56482,6 +56768,11 @@
"user": "0x83b1a48376E045D26420200345414e6b93066396", "user": "0x83b1a48376E045D26420200345414e6b93066396",
"tx": "0xeb193da202cd833a574a524eff7f1dd13a0ee8669e51a7db36984ef4d6735fd6" "tx": "0xeb193da202cd833a574a524eff7f1dd13a0ee8669e51a7db36984ef4d6735fd6"
}, },
{
"amount": "191.911941181396155",
"user": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75",
"tx": "0xb741f4e653131d11eed34bc9c5f3f8425d23cf054b336f3dc61fbd936b39744a"
},
{ {
"amount": "219.945520329711288", "amount": "219.945520329711288",
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90", "user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
@@ -57504,6 +57795,12 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "191.911941181396155",
"user": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75",
"tranche_id": 4,
"tx": "0xb741f4e653131d11eed34bc9c5f3f8425d23cf054b336f3dc61fbd936b39744a"
},
{ {
"amount": "10509.407528939748325", "amount": "10509.407528939748325",
"user": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75", "user": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75",
@@ -57614,8 +57911,8 @@
} }
], ],
"total_tokens": "110499.5291", "total_tokens": "110499.5291",
"withdrawn_tokens": "110307.617158818603845", "withdrawn_tokens": "110499.5291",
"remaining_tokens": "191.911941181396155" "remaining_tokens": "0"
}, },
{ {
"address": "0xdbC5d439F373EB646345e1c67D1d46231ACE7dD3", "address": "0xdbC5d439F373EB646345e1c67D1d46231ACE7dD3",
@@ -58526,8 +58823,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z", "tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-06-05T00:00:00.000Z", "tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996", "total_added": "472355.6199999996",
"total_removed": "43935.8732690563416", "total_removed": "44078.8527972103416",
"locked_amount": "50138.206457121953572821564586524", "locked_amount": "42376.077741542987921938344901044",
"deposits": [ "deposits": [
{ {
"amount": "3000", "amount": "3000",
@@ -65171,6 +65468,16 @@
"user": "0x0a6A5e1da768709A2bF17b2E58B2B73120051D03", "user": "0x0a6A5e1da768709A2bF17b2E58B2B73120051D03",
"tx": "0x097e43cb4f64f1cb502f321eceb8b91e6378cac0b3b6fe558fc1d543aec597e2" "tx": "0x097e43cb4f64f1cb502f321eceb8b91e6378cac0b3b6fe558fc1d543aec597e2"
}, },
{
"amount": "61.181050224",
"user": "0xe7770271d882C54C46B9f00137e96a3BbfFD4d94",
"tx": "0x3c7d0394e431000fa5c733213116dc39b0f87a9a32a40e75cec3c2fce7795b0b"
},
{
"amount": "81.79847793",
"user": "0x4d4AA3f302cbA998AAFC03F9d73484434ed9Fd53",
"tx": "0x1e4902d0a3cb7b4f2ba7119dfcaa681a784e1d724c984961767e9feaa078fe54"
},
{ {
"amount": "168.502276762", "amount": "168.502276762",
"user": "0x38A292CB98Dc602ECAFF94E8E5fADD9800e4bA13", "user": "0x38A292CB98Dc602ECAFF94E8E5fADD9800e4bA13",
@@ -78176,6 +78483,12 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "61.181050224",
"user": "0xe7770271d882C54C46B9f00137e96a3BbfFD4d94",
"tranche_id": 5,
"tx": "0x3c7d0394e431000fa5c733213116dc39b0f87a9a32a40e75cec3c2fce7795b0b"
},
{ {
"amount": "101.521461192", "amount": "101.521461192",
"user": "0xe7770271d882C54C46B9f00137e96a3BbfFD4d94", "user": "0xe7770271d882C54C46B9f00137e96a3BbfFD4d94",
@@ -78214,8 +78527,8 @@
} }
], ],
"total_tokens": "600", "total_tokens": "600",
"withdrawn_tokens": "476.48491248", "withdrawn_tokens": "537.665962704",
"remaining_tokens": "123.51508752" "remaining_tokens": "62.334037296"
}, },
{ {
"address": "0x79D8ff1699911f065fD97a95a6B47216925C4B0e", "address": "0x79D8ff1699911f065fD97a95a6B47216925C4B0e",
@@ -87309,6 +87622,12 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "81.79847793",
"user": "0x4d4AA3f302cbA998AAFC03F9d73484434ed9Fd53",
"tranche_id": 5,
"tx": "0x1e4902d0a3cb7b4f2ba7119dfcaa681a784e1d724c984961767e9feaa078fe54"
},
{ {
"amount": "32.02214612", "amount": "32.02214612",
"user": "0x4d4AA3f302cbA998AAFC03F9d73484434ed9Fd53", "user": "0x4d4AA3f302cbA998AAFC03F9d73484434ed9Fd53",
@@ -87335,8 +87654,8 @@
} }
], ],
"total_tokens": "200", "total_tokens": "200",
"withdrawn_tokens": "99.05242897", "withdrawn_tokens": "180.8509069",
"remaining_tokens": "100.94757103" "remaining_tokens": "19.1490931"
}, },
{ {
"address": "0xd9390b46a1749DEe5325A490490491db9a826D1F", "address": "0xd9390b46a1749DEe5325A490490491db9a826D1F",
@@ -88271,7 +88590,7 @@
"tranche_start": "2021-12-05T00:00:00.000Z", "tranche_start": "2021-12-05T00:00:00.000Z",
"tranche_end": "2022-06-05T00:00:00.000Z", "tranche_end": "2022-06-05T00:00:00.000Z",
"total_added": "171288.42", "total_added": "171288.42",
"total_removed": "69890.5995794947989", "total_removed": "70140.5995794947989",
"locked_amount": "0", "locked_amount": "0",
"deposits": [ "deposits": [
{ {
@@ -92496,6 +92815,11 @@
} }
], ],
"withdrawals": [ "withdrawals": [
{
"amount": "250",
"user": "0x0E3407C9A94effa675471afe7A9D37e687C32141",
"tx": "0x6086c36011fd863c6a34f1a7cd45a798bb1bf6bde6f0e4106c51071c46dbef79"
},
{ {
"amount": "250", "amount": "250",
"user": "0x99492aF57325BA3971542B9ea4036186BE50fa07", "user": "0x99492aF57325BA3971542B9ea4036186BE50fa07",
@@ -95770,10 +96094,17 @@
"tx": "0xee02e72ef8e0755982704385da512cc12c8ff0ea7b58056fa3d5a5932394e9ca" "tx": "0xee02e72ef8e0755982704385da512cc12c8ff0ea7b58056fa3d5a5932394e9ca"
} }
], ],
"withdrawals": [], "withdrawals": [
{
"amount": "250",
"user": "0x0E3407C9A94effa675471afe7A9D37e687C32141",
"tranche_id": 6,
"tx": "0x6086c36011fd863c6a34f1a7cd45a798bb1bf6bde6f0e4106c51071c46dbef79"
}
],
"total_tokens": "250", "total_tokens": "250",
"withdrawn_tokens": "0", "withdrawn_tokens": "250",
"remaining_tokens": "250" "remaining_tokens": "0"
}, },
{ {
"address": "0x953680303b33898962AB7FadCD485374CeDFf87e", "address": "0x953680303b33898962AB7FadCD485374CeDFf87e",
+2 -2
View File
@@ -8,7 +8,7 @@ NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"} NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/ NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session" NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
@@ -27,6 +27,6 @@ CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65 CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535 CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_VEGA_WALLET_URL=http://localhost:1789 CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN= CYPRESS_VEGA_WALLET_API_TOKEN=
+2 -2
View File
@@ -7,7 +7,7 @@ NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"} NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/ NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session" NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
@@ -24,6 +24,6 @@ CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65 CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535 CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_VEGA_WALLET_URL=http://localhost:1789 CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN= CYPRESS_VEGA_WALLET_API_TOKEN=
@@ -0,0 +1,375 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
import { addDays, subDays } from 'date-fns';
import {
chainIdQuery,
statisticsQuery,
createDataConnection,
oracleSpecDataConnectionQuery,
createMarketFragment,
marketsQuery,
marketsDataQuery,
createMarketsDataFragment,
assetQuery,
networkParamsQuery,
} from '@vegaprotocol/mock';
import {
addDecimalsFormatNumber,
getDateTimeFormat,
} from '@vegaprotocol/utils';
describe('Closed markets', { tags: '@smoke' }, () => {
const rowSelector =
'[data-testid="tab-closed-markets"] .ag-center-cols-container .ag-row';
const assetsResult = assetQuery();
// @ts-ignore asset definitely exists
const settlementAsset = assetsResult.assetsConnection.edges[0].node;
const settledMarket = createMarketFragment({
id: '0',
state: MarketState.STATE_SETTLED,
marketTimestamps: {
open: subDays(new Date(), 10).toISOString(),
close: subDays(new Date(), 4).toISOString(),
},
tradableInstrument: {
instrument: {
product: {
dataSourceSpecForTradingTermination: {
id: 'market-1-trading-termination-oracle-id',
},
dataSourceSpecForSettlementData: {
id: 'market-1-settlement-data-oracle-id',
},
settlementAsset,
},
},
},
});
const terminatedMarket = createMarketFragment({
id: '1',
state: MarketState.STATE_TRADING_TERMINATED,
marketTimestamps: {
open: subDays(new Date(), 10).toISOString(),
close: null, // market
},
tradableInstrument: {
instrument: {
metadata: {
tags: [
`settlement-expiry-date:${addDays(new Date(), 4).toISOString()}`,
],
},
},
},
});
const delayedSettledMarket = createMarketFragment({
id: '2',
state: MarketState.STATE_TRADING_TERMINATED,
marketTimestamps: {
open: subDays(new Date(), 10).toISOString(),
close: null, // market
},
tradableInstrument: {
instrument: {
metadata: {
tags: [
`settlement-expiry-date:${subDays(new Date(), 2).toISOString()}`,
],
},
},
},
});
const unknownMarket = createMarketFragment({
id: '3',
state: MarketState.STATE_SETTLED,
});
const closedMarketsResult = [
{
node: settledMarket,
},
{
node: terminatedMarket,
},
{
node: delayedSettledMarket,
},
{ node: unknownMarket },
{
node: createMarketFragment({ id: '4', state: MarketState.STATE_PENDING }),
},
{
node: createMarketFragment({ id: '5', state: MarketState.STATE_ACTIVE }),
},
];
const settledMarketData = createMarketsDataFragment({
market: {
id: settledMarket.id,
},
bestBidPrice: '1000',
bestOfferPrice: '2000',
markPrice: '1500',
});
const closedMarketsDataResult = [
{
node: {
data: settledMarketData,
},
},
{
node: {
data: createMarketsDataFragment({
market: {
id: terminatedMarket.id,
},
}),
},
},
{
node: {
data: createMarketsDataFragment({
market: {
id: delayedSettledMarket.id,
},
}),
},
},
{
node: {
data: createMarketsDataFragment({
market: {
id: unknownMarket.id,
},
}),
},
},
];
const specDataConnection = createDataConnection();
before(() => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery(req, 'NetworkParams', networkParamsQuery());
aliasGQLQuery(
req,
'Markets',
marketsQuery({
marketsConnection: {
edges: closedMarketsResult,
},
})
);
aliasGQLQuery(
req,
'MarketsData',
marketsDataQuery({
marketsConnection: {
edges: closedMarketsDataResult,
},
})
);
aliasGQLQuery(
req,
'OracleSpecDataConnection',
oracleSpecDataConnectionQuery()
);
});
cy.mockSubscription();
cy.visit('/#/markets/all');
cy.get('[data-testid="Closed markets"]').click();
});
it('renders a settled market', () => {
const expectedMarkets = closedMarketsResult.filter((edge) => {
return [
MarketState.STATE_SETTLED,
MarketState.STATE_TRADING_TERMINATED,
].includes(edge.node.state);
});
const product = settledMarket.tradableInstrument.instrument.product;
// rows should be filtered to only include settled/terminated markets
cy.get(rowSelector).should('have.length', expectedMarkets.length);
// check each column in the first row renders correctly
// 6001-MARK-001
cy.get(rowSelector)
.first()
.find('[col-id="code"]')
.should('have.text', settledMarket.tradableInstrument.instrument.code);
// 6001-MARK-002
cy.get(rowSelector)
.first()
.find('[col-id="name"]')
.should('have.text', settledMarket.tradableInstrument.instrument.name);
// 6001-MARK-003
cy.get(rowSelector)
.first()
.find('[col-id="state"]')
.should('have.text', MarketStateMapping[settledMarket.state]);
// 6001-MARK-004
// 6001-MARK-005
// 6001-MARK-009
// 6001-MARK-008
// 6001-MARK-010
cy.get(rowSelector)
.first()
.find('[col-id="settlementDate"]')
.find('[data-testid="link"]')
.should(($el) => {
const href = $el.attr('href');
expect(href).to.match(
new RegExp(
`/oracles/${product.dataSourceSpecForTradingTermination.id}`
)
);
})
.should('have.text', '4 days ago')
.should(
'have.attr',
'title',
getDateTimeFormat().format(
new Date(settledMarket.marketTimestamps.close)
)
);
// 6001-MARK-011
cy.get(rowSelector)
.first()
.find('[col-id="bestBidPrice"]')
.should(
'have.text',
addDecimalsFormatNumber(
settledMarketData.bestBidPrice,
settledMarket.decimalPlaces
)
);
// 6001-MARK-012
cy.get(rowSelector)
.first()
.find('[col-id="bestOfferPrice"]')
.should(
'have.text',
addDecimalsFormatNumber(
settledMarketData.bestOfferPrice,
settledMarket.decimalPlaces
)
);
// 6001-MARK-013
cy.get(rowSelector).first().find('[col-id="markPrice"]').should(
'have.text',
addDecimalsFormatNumber(
settledMarketData.markPrice,
settledMarket.decimalPlaces
)
);
// 6001-MARK-014
// 6001-MARK-015
// 6001-MARK-016
cy.get(rowSelector)
.first()
.find('[col-id="settlementDataOracleId"]')
.find('[data-testid="link"]')
.should(($el) => {
const href = $el.attr('href');
expect(href).to.match(
new RegExp(`/oracles/${product.dataSourceSpecForSettlementData.id}`)
);
})
.should(
'have.text',
addDecimalsFormatNumber(
// @ts-ignore cannot deep un-partial
specDataConnection.externalData.data.data[0].value,
settledMarket.decimalPlaces
)
);
// 6001-MARK-017
cy.get(rowSelector)
.first()
.find('[col-id="realisedPNL"]')
.should('have.text', '-');
// 6001-MARK-018
cy.get(rowSelector)
.first()
.find('[col-id="settlementAsset"]')
.should('have.text', product.settlementAsset.symbol);
// 6001-MARK-020
cy.get(rowSelector)
.first()
.find('[col-id="id"]')
.should('have.text', settledMarket.id);
});
// test market list for market in terminated state
it('renders a terminated market', () => {
cy.get(rowSelector)
.eq(1)
.find('[col-id="state"]')
.should('have.text', MarketStateMapping[terminatedMarket.state]);
// 6001-MARK-006
// 6001-MARK-007
cy.get(rowSelector)
.eq(1)
.find('[col-id="settlementDate"]')
.find('[data-testid="link"]')
.should('have.text', 'Expected in 4 days');
});
it('renders a terminated market which was expected to have settled', () => {
cy.get(rowSelector)
.eq(2)
.find('[col-id="settlementDate"]')
.should('have.class', 'text-danger')
.find('[data-testid="link"]')
.should('have.text', 'Expected 2 days ago');
});
it('renders terminated market which doesnt have settlement date metadata', () => {
cy.get(rowSelector)
.eq(3)
.find('[col-id="settlementDate"]')
.find('[data-testid="link"]')
.should('have.text', 'Unknown');
});
it('can open asset detail dialog', () => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Asset', assetsResult);
});
cy.get(rowSelector)
.first()
.find('[col-id="settlementAsset"]')
.find('button')
.click();
// 6001-MARK-019
cy.get('[data-testid="dialog-title"]').should(
'have.text',
`Asset details - ${settlementAsset.symbol}`
);
});
});
@@ -101,7 +101,7 @@ describe('deposit actions', { tags: '@smoke' }, () => {
cy.mockTradingPage(); cy.mockTradingPage();
cy.mockSubscription(); cy.mockSubscription();
cy.setVegaWallet(); cy.setVegaWallet();
cy.visit('/'); cy.visit('/#/markets/market-1');
cy.wait('@MarketsCandles'); cy.wait('@MarketsCandles');
cy.getByTestId('dialog-close').click(); cy.getByTestId('dialog-close').click();
}); });
@@ -112,7 +112,6 @@ describe('deposit actions', { tags: '@smoke' }, () => {
'be.visible' 'be.visible'
); );
cy.contains('[data-testid="deposit"]', 'Deposit to trade').click(); cy.contains('[data-testid="deposit"]', 'Deposit to trade').click();
connectEthereumWallet('MetaMask');
cy.getByTestId('deposit-submit').should('be.visible'); cy.getByTestId('deposit-submit').should('be.visible');
}); });
}); });
+2 -1
View File
@@ -153,7 +153,7 @@ describe('home', { tags: '@regression' }, () => {
// the choose market overlay is no longer showing // the choose market overlay is no longer showing
cy.contains('Select a market to get started').should('not.exist'); cy.contains('Select a market to get started').should('not.exist');
cy.contains('Loading...').should('not.exist'); cy.contains('Loading...').should('not.exist');
cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-1'); cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-0');
}); });
}); });
@@ -172,6 +172,7 @@ describe('home', { tags: '@regression' }, () => {
], ],
}, },
}; };
// @ts-ignore partial deep check failing
const data = marketsDataQuery(override); const data = marketsDataQuery(override);
cy.mockGQL((req) => { cy.mockGQL((req) => {
aliasGQLQuery(req, 'MarketsData', data); aliasGQLQuery(req, 'MarketsData', data);
@@ -1,4 +1,5 @@
import { MarketTradingModeMapping } from '@vegaprotocol/types'; import { MarketTradingModeMapping } from '@vegaprotocol/types';
import { MarketState } from '@vegaprotocol/types';
const marketInfoBtn = 'Info'; const marketInfoBtn = 'Info';
const row = 'key-value-table-row'; const row = 'key-value-table-row';
@@ -12,7 +13,12 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
}); });
before(() => { before(() => {
cy.mockTradingPage(); cy.mockTradingPage(
MarketState.STATE_ACTIVE,
undefined,
undefined,
'COMPROMISED'
);
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Markets'); cy.wait('@Markets');
@@ -20,6 +26,11 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
cy.wait('@MarketInfo'); cy.wait('@MarketInfo');
}); });
it('show oracle banner', () => {
cy.getByTestId(marketTitle).contains('Oracle').click();
cy.getByTestId('oracle-status').should('contain.text', 'COMPROMISED');
});
it('current fees displayed', () => { it('current fees displayed', () => {
cy.getByTestId(marketTitle).contains('Current fees').click(); cy.getByTestId(marketTitle).contains('Current fees').click();
validateMarketDataRow(0, 'Maker Fee', '0.02%'); validateMarketDataRow(0, 'Maker Fee', '0.02%');
@@ -169,25 +180,21 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
it('oracle displayed', () => { it('oracle displayed', () => {
cy.getByTestId(marketTitle).contains('Oracle').click(); cy.getByTestId(marketTitle).contains('Oracle').click();
validateMarketDataRow(0, 'Settlement Data Property', 'prices.BTC.value');
validateMarketDataRow(
1,
'Trading Termination Property',
'termination.BTC.value'
);
// check that links to github for oracle proofs are shown
cy.getByTestId(accordionContent) cy.getByTestId(accordionContent)
.getByTestId('oracle-proof-links') .getByTestId('provider-name')
.find(`[data-testid="${externalLink}"]`) .and('contain', 'Another oracle');
.should('have.attr', 'href')
.and('contain', 'https://github.com/vegaprotocol/well-known');
cy.getByTestId(accordionContent) cy.getByTestId(accordionContent)
.getByTestId('oracle-spec-links') .getByTestId('signed-proofs')
.find(`[data-testid="${externalLink}"]`) .and('contain', '1');
.should('have.attr', 'href')
.and('contain', '/oracles'); cy.getByTestId(accordionContent)
.getByTestId('verified-proofs')
.and('contain', '1');
cy.getByTestId(accordionContent)
.getByTestId('signed-proofs')
.and('contain', '1');
}); });
it('proposal displayed', () => { it('proposal displayed', () => {
@@ -222,6 +222,7 @@ describe('markets table', { tags: '@smoke' }, () => {
], ],
}, },
}; };
// @ts-ignore partial deep check failing
const market = marketsQuery(override); const market = marketsQuery(override);
aliasGQLQuery(req, 'Market', market); aliasGQLQuery(req, 'Market', market);
aliasGQLQuery(req, 'ProposalOfMarket', { aliasGQLQuery(req, 'ProposalOfMarket', {
@@ -1,12 +1,12 @@
import { closeWelcomeDialog } from '../support/helpers';
describe('Settings page', { tags: '@smoke' }, () => { describe('Settings page', { tags: '@smoke' }, () => {
beforeEach(() => { beforeEach(() => {
cy.clearLocalStorage().then(() => { cy.clearLocalStorage().then(() => {
cy.mockTradingPage(); cy.mockTradingPage();
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/'); cy.visit('/');
cy.get('[role=dialog]').within(() => { closeWelcomeDialog();
cy.getByTestId('dialog-close').click();
});
cy.get('[aria-label="cog icon"]').click(); cy.get('[aria-label="cog icon"]').click();
}); });
}); });
@@ -1,17 +1,25 @@
import { checkSorting } from '@vegaprotocol/cypress'; import { checkSorting } from '@vegaprotocol/cypress';
const dialogClose = 'dialog-close';
describe('accounts', { tags: '@smoke' }, () => { describe('accounts', { tags: '@smoke' }, () => {
before(() => { beforeEach(() => {
cy.clearAllLocalStorage();
cy.mockTradingPage(); cy.mockTradingPage();
cy.mockWeb3Provider(); cy.mockWeb3Provider();
cy.mockSubscription(); cy.mockSubscription();
cy.setVegaWallet(); cy.setVegaWallet();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Assets');
}); });
it('renders accounts', () => { it('renders accounts', () => {
// 7001-COLL-001
// 7001-COLL-002
// 7001-COLL-003
// 7001-COLL-004
// 7001-COLL-005
// 7001-COLL-006
// 7001-COLL-007
const tradingAccountRowId = '[row-id="t-0"]'; const tradingAccountRowId = '[row-id="t-0"]';
cy.getByTestId('Collateral').click(); cy.getByTestId('Collateral').click();
@@ -24,24 +32,113 @@ describe('accounts', { tags: '@smoke' }, () => {
cy.getByTestId('tab-accounts') cy.getByTestId('tab-accounts')
.get(tradingAccountRowId) .get(tradingAccountRowId)
.find('[col-id="accounts-actions"]') .find('[col-id="used"]')
.should('have.text', ''); .should('have.text', '1.010.00%');
cy.getByTestId('tab-accounts') cy.getByTestId('tab-accounts')
.get(tradingAccountRowId) .get(tradingAccountRowId)
.find('[col-id="accounts-actions"]') .find('[col-id="available"]')
.should('have.text', ''); .should('have.text', '100,000.00');
cy.getByTestId('tab-accounts') cy.getByTestId('tab-accounts')
.get(tradingAccountRowId) .get(tradingAccountRowId)
.find('[col-id="total"]') .find('[col-id="total"]')
.should('have.text', '100,001.01'); .should('have.text', '100,001.01');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="accounts-actions"]')
.should('have.text', ' ');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="total"]')
.should('have.text', '100,001.01');
cy.getByTestId('tab-accounts')
.get('[col-id="accounts-actions"]')
.find('[data-testid="dropdown-menu"]')
.eq(1)
.click();
cy.getByTestId('deposit').should('be.visible');
cy.getByTestId('withdraw').should('be.visible');
cy.getByTestId('breakdown').should('be.visible');
cy.getByTestId('Collateral').click({ force: true });
}); });
it('should open asset details dialog when clicked on symbol', () => { it('should open asset details dialog when clicked on symbol', () => {
// 7001-COLL-008
// 6501-ASSE-001
// 6501-ASSE-002
// 6501-ASSE-003
// 6501-ASSE-004
// 6501-ASSE-005
// 6501-ASSE-006
// 6501-ASSE-007
// 6501-ASSE-008
// 6501-ASSE-009
// 6501-ASSE-010
// 6501-ASSE-011
// 6501-ASSE-012
// 6501-ASSE-013
const titles = [
'ID',
'Type',
'Name',
'Symbol',
'Decimals',
'Quantum',
'Status',
'Contract address',
'Withdrawal threshold',
'Lifetime limit',
'Infrastructure fee account balance',
'Global reward pool account balance',
'Maker paid fees account balance',
'Maker received fees account balance',
'Liquidity provision fee reward account balance',
'Market proposer reward account balance',
];
cy.getByTestId('asset').contains('tEURO').click(); cy.getByTestId('asset').contains('tEURO').click();
cy.get('[data-testid="dialog-content"]:visible').should('exist'); cy.get('[data-testid$="_label"]').should('have.length', 16);
cy.get('[data-testid="dialog-close"]:visible').click(); cy.get('[data-testid$="_label"]').each((element, index) => {
cy.wrap(element).should('have.text', titles[index]);
});
cy.getByTestId(dialogClose).click();
cy.getByTestId(dialogClose).should('not.exist');
});
it('should open usage breakdown dialog when clicked on used', () => {
// 7001-COLL-009
cy.getByTestId('breakdown').contains('1.01').click();
const headers = ['Market', 'Account type', 'Balance'];
cy.getByTestId('usage-breakdown').within(($headers) => {
cy.wrap($headers)
.get('.ag-header-cell-text')
.each(($header, i) => {
cy.wrap($header).should('have.text', headers[i]);
});
});
cy.getByTestId(dialogClose).click();
});
it('sorting usage breakdown columns should work well', () => {
// 7001-COLL-010
cy.getByTestId('breakdown').contains('1.01').click();
cy.getByTestId('usage-breakdown')
.find('[col-id="type"]')
.eq(1)
.should('have.text', 'Margin');
cy.getByTestId('usage-breakdown')
.find('[col-id="type"]')
.eq(2)
.should('have.text', 'Margin');
cy.getByTestId('usage-breakdown')
.find('[col-id="type"]')
.eq(3)
.should('have.text', 'General');
cy.getByTestId(dialogClose).click();
}); });
describe('sorting by ag-grid columns should work well', () => { describe('sorting by ag-grid columns should work well', () => {
@@ -88,5 +88,18 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
'Size cannot be lower than 1' 'Size cannot be lower than 1'
); );
}); });
it('must have total margin available', () => {
// 7001-COLL-011
cy.getByTestId('tab-ticket')
.find('.text-xs')
.eq(5)
.within(() => {
cy.get('[data-state="closed"]').should(
'have.text',
'Total margin available'
);
cy.get('.text-neutral-500').should('have.text', '~100,000.01 tDAI');
});
});
}); });
}); });
@@ -455,7 +455,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
}); });
}); });
it('must be warned (pre-submit) if the input price has too many digits after the decimal place for the market', () => { it('must be warned (pre-submit) if the input price has too many digits after the decimal place for the market', () => {
// 7003-MORD-016 // 7003-MORD-013
updateOrder({ updateOrder({
id: orderId, id: orderId,
status: Schema.OrderStatus.STATUS_ACTIVE, status: Schema.OrderStatus.STATUS_ACTIVE,
+5
View File
@@ -9,3 +9,8 @@ export const selectAsset = (assetIndex: number) => {
// eslint-disable-next-line // eslint-disable-next-line
cy.wait(100); cy.wait(100);
}; };
export const closeWelcomeDialog = () => {
cy.getByTestId('select-market-list').should('exist');
cy.getByTestId('dialog-close').click();
};
@@ -26,6 +26,7 @@ export function updateOrder(
override?: PartialDeep<OrderUpdateFieldsFragment> override?: PartialDeep<OrderUpdateFieldsFragment>
): void { ): void {
const update: OrdersUpdateSubscription = orderUpdateSubscription({ const update: OrdersUpdateSubscription = orderUpdateSubscription({
// @ts-ignore partial deep check failing
orders: [override], orders: [override],
}); });
if (!sendOrderUpdate) { if (!sendOrderUpdate) {
+38 -29
View File
@@ -1,6 +1,7 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress'; import { aliasGQLQuery } from '@vegaprotocol/cypress';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { CyHttpMessages } from 'cypress/types/net-stubbing'; import type { CyHttpMessages } from 'cypress/types/net-stubbing';
import type { Provider, Status } from '@vegaprotocol/oracles';
import { import {
accountsQuery, accountsQuery,
assetQuery, assetQuery,
@@ -45,7 +46,9 @@ const marketDataOverride = (
{ {
node: { node: {
data: { data: {
// @ts-ignore conflict between incoming and outgoing types
trigger: data.trigger, trigger: data.trigger,
// @ts-ignore same as above
marketTradingMode: data.tradingMode, marketTradingMode: data.tradingMode,
marketState: data.state, marketState: data.state,
}, },
@@ -62,6 +65,7 @@ const marketsDataOverride = (
edges: [ edges: [
{ {
node: { node: {
// @ts-ignore conflict between incoming and outgoing types
tradingMode: data.tradingMode, tradingMode: data.tradingMode,
state: data.state, state: data.state,
}, },
@@ -155,7 +159,6 @@ const mockTradingPage = (
aliasGQLQuery(req, 'ProposalsList', proposalListQuery()); aliasGQLQuery(req, 'ProposalsList', proposalListQuery());
aliasGQLQuery(req, 'Deposits', depositsQuery()); aliasGQLQuery(req, 'Deposits', depositsQuery());
}; };
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace // eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress { namespace Cypress {
@@ -164,50 +167,56 @@ declare global {
mockTradingPage( mockTradingPage(
state?: Schema.MarketState, state?: Schema.MarketState,
tradingMode?: Schema.MarketTradingMode, tradingMode?: Schema.MarketTradingMode,
trigger?: Schema.AuctionTrigger trigger?: Schema.AuctionTrigger,
oracleStatus?: Status
): void; ): void;
} }
} }
} }
export const addMockTradingPage = () => { export const addMockTradingPage = () => {
Cypress.Commands.add( Cypress.Commands.add(
'mockTradingPage', 'mockTradingPage',
(state = Schema.MarketState.STATE_ACTIVE, tradingMode, trigger) => { (
state = Schema.MarketState.STATE_ACTIVE,
tradingMode,
trigger,
oracleStatus
) => {
cy.mockGQL((req) => { cy.mockGQL((req) => {
mockTradingPage(req, state, tradingMode, trigger); mockTradingPage(req, state, tradingMode, trigger);
}); });
const oracle: Provider = {
name: 'Another oracle',
url: 'https://zombo.com',
description_markdown:
'Some markdown describing the oracle provider.\n\nTwitter: @FacesPics2\n',
oracle: {
status: oracleStatus || 'GOOD',
status_reason: '',
first_verified: '2022-01-01T00:00:00.000Z',
last_verified: '2022-12-31T00:00:00.000Z',
type: 'public_key',
public_key: ORACLE_PUBKEY,
},
proofs: [
{
format: 'signed_message',
available: true,
type: 'public_key',
public_key: ORACLE_PUBKEY,
message: 'SOMEHEX',
},
],
github_link: `https://github.com/vegaprotocol/well-known/blob/main/oracle-providers/public_key-${ORACLE_PUBKEY}.toml`,
};
// Prevent request to github, return some dummy content // Prevent request to github, return some dummy content
cy.intercept( cy.intercept(
'GET', 'GET',
/^https:\/\/raw.githubusercontent.com\/vegaprotocol\/well-known/, /^https:\/\/raw.githubusercontent.com\/vegaprotocol\/well-known/,
{ {
body: [ body: [oracle],
{
name: 'Another oracle',
url: 'https://zombo.com',
description_markdown:
'Some markdown describing the oracle provider.\n\nTwitter: @FacesPics2\n',
oracle: {
status: 'GOOD',
status_reason: '',
first_verified: '2022-01-01T00:00:00.000Z',
last_verified: '2022-12-31T00:00:00.000Z',
type: 'public_key',
public_key: ORACLE_PUBKEY,
},
proofs: [
{
format: 'signed_message',
available: true,
type: 'public_key',
public_key: ORACLE_PUBKEY,
message: 'SOMEHEX',
},
],
github_link: `https://github.com/vegaprotocol/well-known/blob/main/oracle-providers/public_key-${ORACLE_PUBKEY}.toml`,
},
],
} }
); );
} }
+1 -1
View File
@@ -7,7 +7,7 @@ NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"} NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+32 -18
View File
@@ -27,7 +27,10 @@ import { NO_MARKET } from './constants';
import { LiquidityContainer } from '../liquidity/liquidity'; import { LiquidityContainer } from '../liquidity/liquidity';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import type { PinnedAsset } from '@vegaprotocol/accounts'; import type { PinnedAsset } from '@vegaprotocol/accounts';
import { useScreenDimensions } from '@vegaprotocol/react-helpers'; import {
usePaneLayout,
useScreenDimensions,
} from '@vegaprotocol/react-helpers';
import { import {
useMarketClickHandler, useMarketClickHandler,
useMarketLiquidityClickHandler, useMarketLiquidityClickHandler,
@@ -83,15 +86,20 @@ interface BottomPanelProps {
const MarketBottomPanel = memo( const MarketBottomPanel = memo(
({ marketId, pinnedAsset }: BottomPanelProps) => { ({ marketId, pinnedAsset }: BottomPanelProps) => {
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'bottom' });
const { screenSize } = useScreenDimensions(); const { screenSize } = useScreenDimensions();
const onMarketClick = useMarketClickHandler(true); const onMarketClick = useMarketClickHandler(true);
const onOrderTypeClick = useMarketLiquidityClickHandler(true); const onOrderTypeClick = useMarketLiquidityClickHandler(true);
return 'xxxl' === screenSize ? ( return 'xxxl' === screenSize ? (
<ResizableGrid proportionalLayout minSize={200}> <ResizableGrid
proportionalLayout
minSize={200}
onChange={handleOnLayoutChange}
>
<ResizableGridPanel <ResizableGridPanel
priority={LayoutPriority.Low} priority={LayoutPriority.Low}
preferredSize="50%" preferredSize={sizes[0] || '50%'}
minSize={50} minSize={50}
> >
<TradeGridChild> <TradeGridChild>
@@ -119,7 +127,7 @@ const MarketBottomPanel = memo(
</ResizableGridPanel> </ResizableGridPanel>
<ResizableGridPanel <ResizableGridPanel
priority={LayoutPriority.Low} priority={LayoutPriority.Low}
preferredSize="50%" preferredSize={sizes[1] || '50%'}
minSize={50} minSize={50}
> >
<TradeGridChild> <TradeGridChild>
@@ -186,22 +194,29 @@ MarketBottomPanel.displayName = 'MarketBottomPanel';
const MainGrid = memo( const MainGrid = memo(
({ ({
marketId, marketId,
onSelect,
pinnedAsset, pinnedAsset,
}: { }: {
marketId: string; marketId: string;
onSelect: (marketId: string, metaKey?: boolean) => void;
pinnedAsset?: PinnedAsset; pinnedAsset?: PinnedAsset;
}) => { }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'top' });
const [sizesMiddle, handleOnMiddleLayoutChange] = usePaneLayout({
id: 'middle',
});
return ( return (
<ResizableGrid vertical> <ResizableGrid vertical onChange={handleOnLayoutChange}>
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}> <ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
<ResizableGrid proportionalLayout={false} minSize={200}> <ResizableGrid
proportionalLayout={false}
minSize={200}
onChange={handleOnMiddleLayoutChange}
>
<ResizableGridPanel <ResizableGridPanel
priority={LayoutPriority.High} priority={LayoutPriority.High}
minSize={200} minSize={200}
preferredSize="50%" preferredSize={sizesMiddle[0] || '50%'}
> >
<TradeGridChild> <TradeGridChild>
<Tabs storageKey="console-trade-grid-main-left"> <Tabs storageKey="console-trade-grid-main-left">
@@ -219,7 +234,7 @@ const MainGrid = memo(
</ResizableGridPanel> </ResizableGridPanel>
<ResizableGridPanel <ResizableGridPanel
priority={LayoutPriority.Low} priority={LayoutPriority.Low}
preferredSize={330} preferredSize={sizesMiddle[1] || 330}
minSize={300} minSize={300}
> >
<TradeGridChild> <TradeGridChild>
@@ -238,7 +253,7 @@ const MainGrid = memo(
</ResizableGridPanel> </ResizableGridPanel>
<ResizableGridPanel <ResizableGridPanel
priority={LayoutPriority.Low} priority={LayoutPriority.Low}
preferredSize={430} preferredSize={sizesMiddle[2] || 430}
minSize={200} minSize={200}
> >
<TradeGridChild> <TradeGridChild>
@@ -256,7 +271,7 @@ const MainGrid = memo(
</ResizableGridPanel> </ResizableGridPanel>
<ResizableGridPanel <ResizableGridPanel
priority={LayoutPriority.Low} priority={LayoutPriority.Low}
preferredSize="25%" preferredSize={sizes[1] || '25%'}
minSize={50} minSize={50}
> >
<MarketBottomPanel marketId={marketId} pinnedAsset={pinnedAsset} /> <MarketBottomPanel marketId={marketId} pinnedAsset={pinnedAsset} />
@@ -278,11 +293,7 @@ export const TradeGrid = ({
<TradeMarketHeader market={market} onSelect={onSelect} /> <TradeMarketHeader market={market} onSelect={onSelect} />
<OracleBanner marketId={market?.id || ''} /> <OracleBanner marketId={market?.id || ''} />
</div> </div>
<MainGrid <MainGrid marketId={market?.id || ''} pinnedAsset={pinnedAsset} />
marketId={market?.id || ''}
onSelect={onSelect}
pinnedAsset={pinnedAsset}
/>
</div> </div>
); );
}; };
@@ -350,7 +361,10 @@ export const TradePanels = ({
return ( return (
<div className="h-full grid grid-rows-[min-content_1fr_min-content]"> <div className="h-full grid grid-rows-[min-content_1fr_min-content]">
<TradeMarketHeader market={market} onSelect={onSelect} /> <div>
<TradeMarketHeader market={market} onSelect={onSelect} />
<OracleBanner marketId={market?.id || ''} />
</div>
<div className="h-full"> <div className="h-full">
<AutoSizer> <AutoSizer>
{({ width, height }) => ( {({ width, height }) => (
@@ -0,0 +1,335 @@
import { act, render, screen, within } from '@testing-library/react';
import { Closed } from './closed';
import { MarketStateMapping } from '@vegaprotocol/types';
import { PositionStatus } from '@vegaprotocol/types';
import { MarketState } from '@vegaprotocol/types';
import { subDays } from 'date-fns';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/oracles';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/oracles';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import type {
PositionsQuery,
PositionFieldsFragment,
} from '@vegaprotocol/positions';
import { PositionsDocument } from '@vegaprotocol/positions';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import type { MarketsDataQuery, MarketsQuery } from '@vegaprotocol/market-list';
import { MarketsDataDocument } from '@vegaprotocol/market-list';
import { MarketsDocument } from '@vegaprotocol/market-list';
import {
createMarketFragment,
marketsQuery,
marketsDataQuery,
createMarketsDataFragment,
} from '@vegaprotocol/mock';
describe('Closed', () => {
let originalNow: typeof Date.now;
const mockNowTimestamp = 1672531200000;
const settlementDateMetaDate = subDays(
new Date(mockNowTimestamp),
3
).toISOString();
const settlementDateTag = `settlement-expiry-date:${settlementDateMetaDate}`;
const pubKey = 'pubKey';
const marketId = 'market-0';
const settlementDataProperty = 'spec-binding';
const settlementDataId = 'settlement-data-oracle-id';
const market = createMarketFragment({
id: marketId,
state: MarketState.STATE_SETTLED,
tradableInstrument: {
instrument: {
metadata: {
tags: [settlementDateTag],
},
product: {
dataSourceSpecForSettlementData: {
id: settlementDataId,
},
dataSourceSpecBinding: {
settlementDataProperty,
},
},
},
},
});
const marketsMock: MockedResponse<MarketsQuery> = {
request: {
query: MarketsDocument,
},
result: {
data: marketsQuery({
marketsConnection: {
edges: [
{
node: market,
},
],
},
}),
},
};
const marketsData = createMarketsDataFragment({
__typename: 'MarketData',
market: {
__typename: 'Market',
id: marketId,
},
bestBidPrice: '1000',
bestOfferPrice: '2000',
markPrice: '1500',
});
const marketsDataMock: MockedResponse<MarketsDataQuery> = {
request: {
query: MarketsDataDocument,
},
result: {
data: marketsDataQuery({
marketsConnection: {
edges: [
{
node: {
data: marketsData,
},
},
],
},
}),
},
};
// Create mock oracle data
const property = {
__typename: 'Property' as const,
name: settlementDataProperty,
value: '12345',
};
const oracleDataMock: MockedResponse<OracleSpecDataConnectionQuery> = {
request: {
query: OracleSpecDataConnectionDocument,
variables: {
oracleSpecId: settlementDataId,
},
},
result: {
data: {
oracleSpec: {
dataConnection: {
edges: [
{
node: {
externalData: {
data: {
data: [property],
},
},
},
},
],
},
},
},
},
};
// Create mock position
const createPosition = (): PositionFieldsFragment => {
return {
__typename: 'Position' as const,
realisedPNL: '1000',
unrealisedPNL: '2000',
openVolume: '3000',
averageEntryPrice: '100',
updatedAt: new Date().toISOString(),
positionStatus: PositionStatus.POSITION_STATUS_UNSPECIFIED,
lossSocializationAmount: '1000',
market: {
__typename: 'Market',
id: marketId,
},
};
};
const position = createPosition();
const positionsMock: MockedResponse<PositionsQuery> = {
request: {
query: PositionsDocument,
variables: {
partyId: pubKey,
},
},
result: {
data: {
party: {
__typename: 'Party',
id: pubKey,
positionsConnection: {
__typename: 'PositionConnection',
edges: [{ __typename: 'PositionEdge', node: position }],
},
},
},
},
};
beforeAll(() => {
originalNow = Date.now;
Date.now = jest.fn().mockReturnValue(mockNowTimestamp);
});
afterAll(() => {
Date.now = originalNow;
});
it('renders correctly formatted and filtered rows', async () => {
await act(async () => {
render(
<MockedProvider
mocks={[marketsMock, marketsDataMock, positionsMock, oracleDataMock]}
>
<VegaWalletContext.Provider
value={{ pubKey } as VegaWalletContextShape}
>
<Closed />
</VegaWalletContext.Provider>
</MockedProvider>
);
});
// screen.debug(document, Infinity);
const headers = screen.getAllByRole('columnheader');
const expectedHeaders = [
'Market',
'Description',
'Status',
'Settlement date',
'Best bid',
'Best offer',
'Mark price',
'Settlement price',
'Realised PNL',
'Settlement asset',
'Market ID',
];
expect(headers).toHaveLength(expectedHeaders.length);
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
const cells = screen.getAllByRole('gridcell');
const expectedValues = [
market.tradableInstrument.instrument.code,
market.tradableInstrument.instrument.name,
MarketStateMapping[market.state],
'3 days ago',
/* eslint-disable @typescript-eslint/no-non-null-assertion */
addDecimalsFormatNumber(marketsData.bestBidPrice, market.decimalPlaces),
addDecimalsFormatNumber(
marketsData!.bestOfferPrice,
market.decimalPlaces
),
addDecimalsFormatNumber(marketsData!.markPrice, market.decimalPlaces),
/* eslint-enable @typescript-eslint/no-non-null-assertion */
addDecimalsFormatNumber(property.value, market.decimalPlaces),
addDecimalsFormatNumber(position.realisedPNL, market.decimalPlaces),
market.tradableInstrument.instrument.product.settlementAsset.symbol,
market.id,
];
cells.forEach((cell, i) => {
expect(cell).toHaveTextContent(expectedValues[i]);
});
});
it('only renders settled and terminated markets', async () => {
const mixedMarkets = [
{
// inlclude as settled
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'include-0',
state: MarketState.STATE_SETTLED,
}),
},
{
// omit this market
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'discard-0',
state: MarketState.STATE_SUSPENDED,
}),
},
{
// include as terminated
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'include-1',
state: MarketState.STATE_TRADING_TERMINATED,
}),
},
{
// omit this market
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'discard-1',
state: MarketState.STATE_ACTIVE,
}),
},
];
const mixedMarketsMock: MockedResponse<MarketsQuery> = {
request: {
query: MarketsDocument,
},
result: {
data: {
marketsConnection: {
__typename: 'MarketConnection',
edges: mixedMarkets,
},
},
},
};
await act(async () => {
render(
<MockedProvider
mocks={[
mixedMarketsMock,
marketsDataMock,
positionsMock,
oracleDataMock,
]}
>
<VegaWalletContext.Provider
value={{ pubKey } as VegaWalletContextShape}
>
<Closed />
</VegaWalletContext.Provider>
</MockedProvider>
);
});
// check that the number of rows in datagrid is 2
const container = within(
document.querySelector('.ag-center-cols-container') as HTMLElement
);
const expectedRows = mixedMarkets.filter((m) => {
return [
MarketState.STATE_SETTLED,
MarketState.STATE_TRADING_TERMINATED,
].includes(m.node.state);
});
// check rows length is correct
const rows = container.getAllByRole('row');
expect(rows).toHaveLength(expectedRows.length);
// check that only included ids are shown
const cells = screen
.getAllByRole('gridcell')
.filter((cell) => cell.getAttribute('col-id') === 'id')
.map((cell) => cell.textContent?.trim());
expect(cells).toEqual(expectedRows.map((m) => m.node.id));
});
});
@@ -0,0 +1,285 @@
import compact from 'lodash/compact';
import { isAfter } from 'date-fns';
import type {
VegaICellRendererParams,
VegaValueFormatterParams,
} from '@vegaprotocol/datagrid';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { useMemo } from 'react';
import { t } from '@vegaprotocol/i18n';
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
import {
addDecimalsFormatNumber,
getMarketExpiryDate,
} from '@vegaprotocol/utils';
import { usePositionsQuery } from '@vegaprotocol/positions';
import type { MarketMaybeWithData } from '@vegaprotocol/market-list';
import { closedMarketsWithDataProvider } from '@vegaprotocol/market-list';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import type { ColDef } from 'ag-grid-community';
import { SettlementDateCell } from './settlement-date-cell';
import { SettlementPriceCell } from './settlement-price-cell';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
type SettlementAsset =
MarketMaybeWithData['tradableInstrument']['instrument']['product']['settlementAsset'];
interface Row {
id: string;
code: string;
name: string;
decimalPlaces: number;
state: MarketState;
metadata: string[];
closeTimestamp: string | null;
bestBidPrice: string | undefined;
bestOfferPrice: string | undefined;
markPrice: string | undefined;
settlementDataOracleId: string;
settlementDataSpecBinding: string;
tradingTerminationOracleId: string;
settlementAsset: SettlementAsset;
realisedPNL: string | undefined;
}
export const Closed = () => {
const { pubKey } = useVegaWallet();
const {
data: marketData,
loading,
error,
reload,
} = useDataProvider({
dataProvider: closedMarketsWithDataProvider,
variables: undefined,
});
const { data: positionData } = usePositionsQuery({
variables: {
partyId: pubKey || '',
},
skip: !pubKey,
});
// find a position for each market and add the realised pnl to
// a normalized object
const rowData = compact(marketData).map((market) => {
const position = positionData?.party?.positionsConnection?.edges?.find(
(edge) => {
return edge.node.market.id === market.id;
}
);
const row: Row = {
id: market.id,
code: market.tradableInstrument.instrument.code,
name: market.tradableInstrument.instrument.name,
decimalPlaces: market.decimalPlaces,
state: market.state,
metadata: market.tradableInstrument.instrument.metadata.tags ?? [],
closeTimestamp: market.marketTimestamps.close,
bestBidPrice: market.data?.bestBidPrice,
bestOfferPrice: market.data?.bestOfferPrice,
markPrice: market.data?.markPrice,
settlementDataOracleId:
market.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.id,
settlementDataSpecBinding:
market.tradableInstrument.instrument.product.dataSourceSpecBinding
.settlementDataProperty,
tradingTerminationOracleId:
market.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.id,
settlementAsset:
market.tradableInstrument.instrument.product.settlementAsset,
realisedPNL: position?.node.realisedPNL,
};
return row;
});
return (
<div className="h-full relative">
<ClosedMarketsDataGrid rowData={rowData} />
<div className="pointer-events-none absolute inset-0">
<AsyncRenderer
loading={loading}
error={error}
data={marketData}
noDataMessage={t('No markets')}
reload={reload}
/>
</div>
</div>
);
};
const ClosedMarketsDataGrid = ({ rowData }: { rowData: Row[] }) => {
const openAssetDialog = useAssetDetailsDialogStore((store) => store.open);
const colDefs = useMemo(() => {
const cols: ColDef[] = [
{
headerName: t('Market'),
field: 'code',
},
{
headerName: t('Description'),
field: 'name',
},
{
headerName: t('Status'),
field: 'state',
valueFormatter: ({ value }: VegaValueFormatterParams<Row, 'state'>) => {
if (!value) return '-';
return MarketStateMapping[value];
},
},
{
headerName: t('Settlement date'),
colId: 'settlementDate', // colId needed if no field property provided otherwise column order is ruined in tests
valueGetter: ({ data }: { data: Row }) => {
return getMarketExpiryDate(data.metadata);
},
cellRenderer: ({ value, data }: { value: Date | null; data: Row }) => {
return (
<SettlementDateCell
oracleSpecId={data.tradingTerminationOracleId}
metaDate={value}
marketState={data.state}
closeTimestamp={data.closeTimestamp}
/>
);
},
cellClassRules: {
'text-danger': ({
value,
data,
}: {
value: Date | null;
data: Row;
}) => {
const date = data.closeTimestamp
? new Date(data.closeTimestamp)
: value;
if (!date) return false;
if (
// expiry has passed and market is not yet settled
isAfter(new Date(), date) &&
data.state !== MarketState.STATE_SETTLED
) {
return true;
}
return false;
},
},
},
{
headerName: t('Best bid'),
field: 'bestBidPrice',
type: 'numericColumn',
cellClass: 'font-mono ag-right-aligned-cell',
valueFormatter: ({
value,
data,
}: VegaValueFormatterParams<Row, 'bestBidPrice'>) => {
if (!value || !data) return '-';
return addDecimalsFormatNumber(value, data.decimalPlaces);
},
},
{
headerName: t('Best offer'),
field: 'bestOfferPrice',
cellClass: 'font-mono ag-right-aligned-cell',
type: 'numericColumn',
valueFormatter: ({
value,
data,
}: VegaValueFormatterParams<Row, 'bestOfferPrice'>) => {
if (!value || !data) return '-';
return addDecimalsFormatNumber(value, data.decimalPlaces);
},
},
{
headerName: t('Mark price'),
field: 'markPrice',
cellClass: 'font-mono ag-right-aligned-cell',
type: 'numericColumn',
valueFormatter: ({
value,
data,
}: VegaValueFormatterParams<Row, 'markPrice'>) => {
if (!value || !data) return '-';
return addDecimalsFormatNumber(value, data.decimalPlaces);
},
},
{
headerName: t('Settlement price'),
type: 'numericColumn',
field: 'settlementDataOracleId',
// 'tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id',
cellRenderer: ({
value,
data,
}: VegaICellRendererParams<Row, 'settlementDataOracleId'>) => (
<SettlementPriceCell
oracleSpecId={value}
decimalPlaces={data?.decimalPlaces ?? 0}
settlementDataSpecBinding={data?.settlementDataSpecBinding}
/>
),
},
{
headerName: t('Realised PNL'),
field: 'realisedPNL',
cellClass: 'font-mono ag-right-aligned-cell',
type: 'numericColumn',
valueFormatter: ({
value,
data,
}: VegaValueFormatterParams<Row, 'realisedPNL'>) => {
if (!value || !data) return '-';
return addDecimalsFormatNumber(value, data.decimalPlaces);
},
},
{
headerName: t('Settlement asset'),
field: 'settlementAsset',
cellRenderer: ({
value,
data,
}: VegaValueFormatterParams<Row, 'settlementAsset'>) => (
<button
className="underline"
onClick={() => {
if (!value) return;
openAssetDialog(value.id);
}}
>
{value ? value.symbol : '-'}
</button>
),
},
{
headerName: t('Market ID'),
field: 'id',
},
];
return cols;
}, [openAssetDialog]);
return (
<AgGrid
style={{ width: '100%', height: '100%' }}
rowData={rowData}
columnDefs={colDefs}
getRowId={({ data }) => data.id}
defaultColDef={{
flex: 1,
resizable: true,
}}
overlayNoRowsTemplate="No data"
/>
);
};
@@ -5,6 +5,7 @@ import { LocalStoragePersistTabs as Tabs, Tab } from '@vegaprotocol/ui-toolkit';
import { Markets } from './markets'; import { Markets } from './markets';
import { Proposed } from './proposed'; import { Proposed } from './proposed';
import { usePageTitleStore } from '../../stores'; import { usePageTitleStore } from '../../stores';
import { Closed } from './closed';
export const MarketsPage = () => { export const MarketsPage = () => {
const { updateTitle } = usePageTitleStore((store) => ({ const { updateTitle } = usePageTitleStore((store) => ({
@@ -21,6 +22,9 @@ export const MarketsPage = () => {
<Tab id="proposed-markets" name={t('Proposed markets')}> <Tab id="proposed-markets" name={t('Proposed markets')}>
<Proposed /> <Proposed />
</Tab> </Tab>
<Tab id="closed-markets" name={t('Closed markets')}>
<Closed />
</Tab>
</Tabs> </Tabs>
); );
}; };
@@ -12,7 +12,9 @@ export const Proposed = () => {
const externalLink = tokenLink(TOKEN_NEW_MARKET_PROPOSAL); const externalLink = tokenLink(TOKEN_NEW_MARKET_PROPOSAL);
return ( return (
<> <>
<ProposalsList /> <div className="min-h-[200px]">
<ProposalsList />
</div>
<ExternalLink className="py-4 px-[11px] text-sm" href={externalLink}> <ExternalLink className="py-4 px-[11px] text-sm" href={externalLink}>
{t('Propose a new market')} {t('Propose a new market')}
</ExternalLink> </ExternalLink>
@@ -0,0 +1,105 @@
import { render, screen } from '@testing-library/react';
import { MarketState } from '@vegaprotocol/types';
import { addDays, subDays } from 'date-fns';
import type { SettlementDataCellProps } from './settlement-date-cell';
import { SettlementDateCell } from './settlement-date-cell';
describe('SettlementDateCell', () => {
let originalNow: typeof Date.now;
const mockNowTimestamp = 1672531200000;
const createProps = (): SettlementDataCellProps => {
return {
oracleSpecId: 'oracle-spec-id',
metaDate: null,
closeTimestamp: null,
marketState: MarketState.STATE_SETTLED,
};
};
beforeAll(() => {
originalNow = Date.now;
Date.now = jest.fn().mockReturnValue(mockNowTimestamp);
});
afterAll(() => {
Date.now = originalNow;
});
it('renders unknown if date cannot be determined', () => {
const props = createProps();
render(<SettlementDateCell {...props} />);
const link = screen.getByRole('link');
expect(link).toHaveTextContent('Unknown');
expect(link).toHaveAttribute(
'href',
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
);
});
it('renders using close timestamp if provided', () => {
const daysAgo = 3;
const props = createProps();
props.closeTimestamp = subDays(
new Date(mockNowTimestamp),
daysAgo
).toISOString();
render(<SettlementDateCell {...props} />);
const link = screen.getByRole('link');
expect(link).toHaveTextContent(`${daysAgo} days ago`);
expect(link).toHaveAttribute(
'href',
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
);
});
it('renders using meta tag date if no close timestamp provided', () => {
const daysAgo = 4;
const props = createProps();
props.metaDate = subDays(new Date(mockNowTimestamp), daysAgo);
render(<SettlementDateCell {...props} />);
const link = screen.getByRole('link');
expect(link).toHaveTextContent(`${daysAgo} days ago`);
expect(link).toHaveAttribute(
'href',
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
);
});
it('renders past expected settlement date', () => {
const daysAgo = 3;
const props = createProps();
props.metaDate = subDays(new Date(mockNowTimestamp), daysAgo);
props.marketState = MarketState.STATE_TRADING_TERMINATED;
render(<SettlementDateCell {...props} />);
const link = screen.getByRole('link');
expect(link).toHaveTextContent(`Expected ${daysAgo} days ago`);
expect(link).toHaveAttribute(
'href',
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
);
});
it('renders future expected settlement date', () => {
const daysAgo = 3;
const props = createProps();
props.metaDate = addDays(new Date(mockNowTimestamp), daysAgo);
props.marketState = MarketState.STATE_TRADING_TERMINATED;
render(<SettlementDateCell {...props} />);
const link = screen.getByRole('link');
expect(link).toHaveTextContent(`Expected in ${daysAgo} days`);
expect(link).toHaveAttribute(
'href',
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
);
});
});
@@ -0,0 +1,55 @@
import { DApp, EXPLORER_ORACLE, useLinks } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { MarketState } from '@vegaprotocol/types';
import { Link } from '@vegaprotocol/ui-toolkit';
import { getDateTimeFormat } from '@vegaprotocol/utils';
import { formatDistanceToNowStrict, isAfter } from 'date-fns';
export interface SettlementDataCellProps {
oracleSpecId: string;
metaDate: Date | null;
closeTimestamp: string | null;
marketState: MarketState;
}
export const SettlementDateCell = ({
oracleSpecId,
metaDate,
closeTimestamp,
marketState,
}: SettlementDataCellProps) => {
const linkCreator = useLinks(DApp.Explorer);
const date = closeTimestamp ? new Date(closeTimestamp) : metaDate;
let text = '';
if (!date) {
text = t('Unknown');
} else {
// pass Date.now() to date constructor for easier mocking
const expiryHasPassed = isAfter(new Date(Date.now()), date);
const distance = formatDistanceToNowStrict(date); // X days/mins ago
if (expiryHasPassed) {
if (marketState !== MarketState.STATE_SETTLED) {
text = t('Expected %s ago', distance);
} else {
text = t('%s ago', distance);
}
} else {
text = t('Expected in %s', distance);
}
}
return (
<Link
href={linkCreator(EXPLORER_ORACLE.replace(':id', oracleSpecId))}
className="underline"
target="_blank"
title={
date ? getDateTimeFormat().format(date) : t('Unknown settlement date')
}
>
{text}
</Link>
);
};
@@ -0,0 +1,113 @@
import { render, screen } from '@testing-library/react';
import type { Property } from '@vegaprotocol/types';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/oracles';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/oracles';
import type { SettlementPriceCellProps } from './settlement-price-cell';
import { SettlementPriceCell } from './settlement-price-cell';
describe('SettlementPriceCell', () => {
const createMock = (
id: string,
property: Property
): MockedResponse<OracleSpecDataConnectionQuery> => {
return {
request: {
query: OracleSpecDataConnectionDocument,
variables: {
oracleSpecId: id,
},
},
result: {
data: {
oracleSpec: {
dataConnection: {
edges: [
{
node: {
externalData: {
data: {
data: [property],
},
},
},
},
],
},
},
},
},
};
};
const createProps = (): SettlementPriceCellProps => {
return {
oracleSpecId: 'oracle-spec-id',
decimalPlaces: 2,
settlementDataSpecBinding: 'settlement-data-spec-binding',
};
};
it('renders fetches and renders the settlment data value', async () => {
const props = createProps();
const property = {
__typename: 'Property' as const,
name: props.settlementDataSpecBinding as string,
value: '1234',
};
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const mock = createMock(props.oracleSpecId!, property);
render(
<MockedProvider mocks={[mock]}>
<SettlementPriceCell {...props} />
</MockedProvider>
);
expect(screen.getByText('-')).toBeInTheDocument();
const link = await screen.findByRole('link');
expect(link).toHaveTextContent('12.34');
expect(link).toHaveAttribute(
'href',
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
);
});
it('renders "-" if no spec value is found', async () => {
const props = createProps();
const property = {
__typename: 'Property' as const,
name: 'no matching spec binding',
value: '1234',
};
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const mock = createMock(props.oracleSpecId!, property);
render(
<MockedProvider mocks={[mock]}>
<SettlementPriceCell {...props} />
</MockedProvider>
);
expect(screen.getByText('-')).toBeInTheDocument();
const link = await screen.findByRole('link');
expect(link).toHaveTextContent('-');
expect(link).toHaveAttribute(
'href',
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
);
});
it('renders "-" with no link if oracle spec id is not provided', () => {
const props = createProps();
props.oracleSpecId = undefined;
render(
<MockedProvider mocks={[]}>
<SettlementPriceCell {...props} />
</MockedProvider>
);
expect(screen.getByText('-')).toBeInTheDocument();
expect(screen.queryByRole('link')).not.toBeInTheDocument();
});
});
@@ -0,0 +1,39 @@
import { DApp, EXPLORER_ORACLE, useLinks } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { useOracleSpecBindingData } from '@vegaprotocol/oracles';
import { Link } from '@vegaprotocol/ui-toolkit';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
export interface SettlementPriceCellProps {
oracleSpecId: string | undefined;
decimalPlaces: number;
settlementDataSpecBinding: string | undefined;
}
export const SettlementPriceCell = ({
oracleSpecId,
decimalPlaces,
settlementDataSpecBinding,
}: SettlementPriceCellProps) => {
const linkCreator = useLinks(DApp.Explorer);
const { property, loading } = useOracleSpecBindingData(
oracleSpecId,
settlementDataSpecBinding
);
if (!oracleSpecId || loading) {
return <span>-</span>;
}
return (
<Link
href={linkCreator(EXPLORER_ORACLE.replace(':id', oracleSpecId))}
className="underline font-mono"
target="_blank"
>
{property
? addDecimalsFormatNumber(property.value, decimalPlaces)
: t('-')}
</Link>
);
};
@@ -7,6 +7,7 @@ import { WithdrawalsContainer } from './withdrawals-container';
import { FillsContainer } from '@vegaprotocol/fills'; import { FillsContainer } from '@vegaprotocol/fills';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { usePaneLayout } from '@vegaprotocol/react-helpers';
import { VegaWalletContainer } from '../../components/vega-wallet-container'; import { VegaWalletContainer } from '../../components/vega-wallet-container';
import { DepositsContainer } from './deposits-container'; import { DepositsContainer } from './deposits-container';
import { LayoutPriority } from 'allotment'; import { LayoutPriority } from 'allotment';
@@ -34,11 +35,11 @@ export const Portfolio = () => {
const onMarketClick = useMarketClickHandler(true); const onMarketClick = useMarketClickHandler(true);
const onOrderTypeClick = useMarketLiquidityClickHandler(true); const onOrderTypeClick = useMarketLiquidityClickHandler(true);
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'portfolio' });
const wrapperClasses = 'h-full max-h-full flex flex-col'; const wrapperClasses = 'h-full max-h-full flex flex-col';
return ( return (
<div className={wrapperClasses}> <div className={wrapperClasses}>
<ResizableGrid vertical> <ResizableGrid vertical onChange={handleOnLayoutChange}>
<ResizableGridPanel minSize={75}> <ResizableGridPanel minSize={75}>
<PortfolioGridChild> <PortfolioGridChild>
<Tabs storageKey="console-portfolio-top"> <Tabs storageKey="console-portfolio-top">
@@ -78,7 +79,7 @@ export const Portfolio = () => {
</ResizableGridPanel> </ResizableGridPanel>
<ResizableGridPanel <ResizableGridPanel
priority={LayoutPriority.Low} priority={LayoutPriority.Low}
preferredSize={300} preferredSize={sizes[1] || 300}
minSize={50} minSize={50}
> >
<PortfolioGridChild> <PortfolioGridChild>
@@ -36,7 +36,11 @@ export const Settings = () => {
/> />
</div> </div>
<Divider /> <Divider />
<TelemetryApproval isSettingsPage /> <TelemetryApproval
helpText={t(
'Help identify bugs and improve the service by sharing anonymous usage data.'
)}
/>
</RoundedWrapper> </RoundedWrapper>
</div> </div>
</div> </div>
@@ -26,7 +26,8 @@ export const OracleBanner = ({ marketId }: { marketId: string }) => {
return ( return (
<NotificationBanner intent={Intent.Danger}> <NotificationBanner intent={Intent.Danger}>
<div> <div>
Oracle status for this market is {oracle.status}.{' '} Oracle status for this market is{' '}
<span data-testId="oracle-status">{oracle.status}</span>.{' '}
{oracleStatuses[oracle.status]} {oracleStatuses[oracle.status]}
</div> </div>
{oracle.status_reason ? ( {oracle.status_reason ? (
+1 -1
View File
@@ -1,6 +1,6 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
export const THROTTLE_UPDATE_TIME = 500; export const THROTTLE_UPDATE_TIME = 500;
export const RISK_ACCEPTED_KEY = 'vega-risk-accepted'; export const RISK_ACCEPTED_KEY = 'vega_risk_accepted';
export const MAINNET_WELCOME_HEADER = t( export const MAINNET_WELCOME_HEADER = t(
'Trade cash settled futures on the fully decentralised Vega network.' 'Trade cash settled futures on the fully decentralised Vega network.'
); );
@@ -39,7 +39,17 @@ const MARKET_A: PartialMarket = {
symbol: 'ABC', symbol: 'ABC',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {
id: '', __typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecForSettlementData: {
__typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecBinding: {
__typename: 'DataSourceSpecToFutureBinding',
tradingTerminationProperty: 'trading-termination-property',
settlementDataProperty: 'settlement-data-property',
}, },
}, },
metadata: { metadata: {
@@ -115,7 +125,17 @@ const MARKET_B: PartialMarket = {
symbol: 'XYZ', symbol: 'XYZ',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {
id: '', __typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecForSettlementData: {
__typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecBinding: {
__typename: 'DataSourceSpecToFutureBinding',
tradingTerminationProperty: 'trading-termination-property',
settlementDataProperty: 'settlement-data-property',
}, },
}, },
metadata: { metadata: {
@@ -1,9 +1,6 @@
import { BrowserRouter } from 'react-router-dom';
import { render, screen, fireEvent } from '@testing-library/react'; import { render, screen, fireEvent } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import { Networks, useEnvironment } from '@vegaprotocol/environment'; import { Networks, useEnvironment } from '@vegaprotocol/environment';
import { RiskNoticeDialog } from './risk-notice-dialog'; import { RiskNoticeDialog } from './risk-notice-dialog';
import { WelcomeDialog } from './welcome-dialog';
jest.mock('@vegaprotocol/environment'); jest.mock('@vegaprotocol/environment');
@@ -14,7 +11,6 @@ const mockEnvDefinitions = {
}; };
describe('Risk notice dialog', () => { describe('Risk notice dialog', () => {
const introText = 'Regulation may apply to use of this app';
const mockOnClose = jest.fn(); const mockOnClose = jest.fn();
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
@@ -22,13 +18,12 @@ describe('Risk notice dialog', () => {
it.each` it.each`
assertion | network assertion | network
${'displays'} | ${Networks.MAINNET}
${'displays'} | ${Networks.CUSTOM} ${'displays'} | ${Networks.CUSTOM}
${'displays'} | ${Networks.DEVNET} ${'displays'} | ${Networks.DEVNET}
${'displays'} | ${Networks.STAGNET3} ${'displays'} | ${Networks.STAGNET3}
${'displays'} | ${Networks.TESTNET} ${'displays'} | ${Networks.TESTNET}
`( `(
'$assertion the risk notice on $network', '$assertion a generic message on $network',
async ({ assertion, network }) => { async ({ assertion, network }) => {
// @ts-ignore ignore mock implementation // @ts-ignore ignore mock implementation
useEnvironment.mockImplementation(() => ({ useEnvironment.mockImplementation(() => ({
@@ -36,27 +31,37 @@ describe('Risk notice dialog', () => {
VEGA_ENV: network, VEGA_ENV: network,
})); }));
render( render(<RiskNoticeDialog onClose={mockOnClose} network={network} />);
<MockedProvider>
<WelcomeDialog />
</MockedProvider>,
{ wrapper: BrowserRouter }
);
expect(screen.queryByText(introText)).toBeInTheDocument(); expect(
screen.getByText(
new RegExp(
`This application for trading on Vega is connected to ${network}`
)
)
).toBeInTheDocument();
const button = screen.getByRole('button', {
name: 'Continue',
});
fireEvent.click(button);
expect(mockOnClose).toHaveBeenCalled();
} }
); );
it("doesn't display the risk notice when previously acknowledged", () => { it('displays a risk message for mainnet', () => {
const introText = 'Regulation may apply to use of this app';
const network = Networks.MAINNET;
// @ts-ignore ignore mock implementation // @ts-ignore ignore mock implementation
useEnvironment.mockImplementation(() => ({ useEnvironment.mockImplementation(() => ({
...mockEnvDefinitions, ...mockEnvDefinitions,
VEGA_ENV: Networks.MAINNET, VEGA_ENV: network,
})); }));
render(<RiskNoticeDialog onClose={mockOnClose} />); render(<RiskNoticeDialog onClose={mockOnClose} network={network} />);
expect(screen.queryByText(introText)).toBeInTheDocument(); expect(screen.getByText(introText)).toBeInTheDocument();
const button = screen.getByRole('button', { const button = screen.getByRole('button', {
name: 'I understand, Continue', name: 'I understand, Continue',
@@ -1,25 +1,100 @@
import { useCallback } from 'react';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import { Button } from '@vegaprotocol/ui-toolkit'; import {
import { LocalStorage } from '@vegaprotocol/utils'; Button,
Link,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { RISK_ACCEPTED_KEY } from '../constants'; import { RISK_ACCEPTED_KEY } from '../constants';
import { TelemetryApproval } from './telemetry-approval'; import { TelemetryApproval } from './telemetry-approval';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
interface Props { interface Props {
onClose: () => void; onClose: () => void;
network: Networks;
} }
export const RiskNoticeDialog = ({ onClose }: Props) => { export const RiskNoticeDialog = ({ onClose, network }: Props) => {
const handleAcceptRisk = useCallback(() => { const [, setValue] = useLocalStorage(RISK_ACCEPTED_KEY);
onClose();
LocalStorage.setItem(RISK_ACCEPTED_KEY, 'true');
}, [onClose]);
const handleAcceptRisk = () => {
onClose();
setValue('true');
};
return (
<>
{network === Networks.MAINNET ? (
<MainnetContent />
) : (
<TestnetContent network={network} />
)}
<div className="my-4">
<TelemetryApproval
helpText={t(
'Help identify bugs and improve the service by sharing anonymous usage data. You can change this in your settings at any time.'
)}
/>
</div>
<Button onClick={handleAcceptRisk}>
{network === Networks.MAINNET
? t('I understand, Continue')
: t('Continue')}
</Button>
</>
);
};
const TestnetContent = ({ network }: { network: Networks }) => {
const { VEGA_DOCS_URL, GITHUB_FEEDBACK_URL, VEGA_WALLET_URL } =
useEnvironment();
return (
<>
<p className="mb-4">
{t(
'This application for trading on Vega is connected to %s, meaning you are free to try out trading with virtual assets and no risk.',
[network]
)}
</p>
<p className="mb-4">
{t(
'Your Vega wallet must also be connected to %s, and your Ethereum wallet must be connected to Sepolia.',
[network]
)}
</p>
{VEGA_DOCS_URL && GITHUB_FEEDBACK_URL && VEGA_WALLET_URL && (
<ul className="list-disc pl-4">
<li className="mb-1">
<Link href={VEGA_WALLET_URL} target="_blank">
<span className="underline">{t('Learn about Vega wallet')}</span>{' '}
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
</Link>
</li>
<li className="mb-1">
<Link href={VEGA_DOCS_URL} target="_blank">
<span className="underline">{t('View documentation')}</span>{' '}
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
</Link>
</li>
<li className="mb-1">
<Link href={GITHUB_FEEDBACK_URL} target="_blank">
<span className="underline">{t('Provide feedback')}</span>{' '}
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
</Link>
</li>
</ul>
)}
</>
);
};
const MainnetContent = () => {
return ( return (
<> <>
<h4 className="text-xl mb-2 mt-4"> <h4 className="text-xl mb-2 mt-4">
{t('Regulation may apply to use of this app')} {t('Regulation may apply to use of this app')}
</h4> </h4>
<p className="text-base mb-6"> <p className="mb-6">
{t( {t(
'This decentralised application allows you to connect to and use publicly available blockchain services operated by third parties that may include trading, financial products, or other services that may be subject to legal and regulatory restrictions in your jurisdiction. This application is a front end only and does not hold any funds or provide any products or services. It is available to anyone with an internet connection via IPFS and other methods, and the ability to access it does not imply any right to use any services or that it is legal for you to do so. By using this application you accept that it is your responsibility to ensure that your use of the application and any blockchain services accessed through it is compliant with applicable laws and regulations in your jusrisdiction.' 'This decentralised application allows you to connect to and use publicly available blockchain services operated by third parties that may include trading, financial products, or other services that may be subject to legal and regulatory restrictions in your jurisdiction. This application is a front end only and does not hold any funds or provide any products or services. It is available to anyone with an internet connection via IPFS and other methods, and the ability to access it does not imply any right to use any services or that it is legal for you to do so. By using this application you accept that it is your responsibility to ensure that your use of the application and any blockchain services accessed through it is compliant with applicable laws and regulations in your jusrisdiction.'
)} )}
@@ -27,15 +102,11 @@ export const RiskNoticeDialog = ({ onClose }: Props) => {
<h4 className="text-xl mb-2"> <h4 className="text-xl mb-2">
{t('Technical and financial risk of loss')} {t('Technical and financial risk of loss')}
</h4> </h4>
<p className="text-base mb-8"> <p className="mb-8">
{t( {t(
'The public blockchain services accessible via this decentralised application are operated by third parties and may carry significant risks including the potential loss of all funds that you deposit or hold with these services. Technical risks include the risk of loss in the event of the failure or compromise of the public blockchain infrastructure or smart contracts that provide any services you use. Financial risks include but are not limited to losses due to volatility, excessive leverage, low liquidity, and your own lack of understanding of the services you use. By using this decentralised application you accept that it is your responsibility to ensure that you understand any services you use and the technical and financial risks inherent in your use. Do not risk what you cannot afford to lose.' 'The public blockchain services accessible via this decentralised application are operated by third parties and may carry significant risks including the potential loss of all funds that you deposit or hold with these services. Technical risks include the risk of loss in the event of the failure or compromise of the public blockchain infrastructure or smart contracts that provide any services you use. Financial risks include but are not limited to losses due to volatility, excessive leverage, low liquidity, and your own lack of understanding of the services you use. By using this decentralised application you accept that it is your responsibility to ensure that you understand any services you use and the technical and financial risks inherent in your use. Do not risk what you cannot afford to lose.'
)} )}
</p> </p>
<Button onClick={handleAcceptRisk}>{t('I understand, Continue')}</Button>
<div className="text-base mt-8">
<TelemetryApproval />
</div>
</> </>
); );
}; };
@@ -3,7 +3,8 @@ import { TelemetryApproval } from './telemetry-approval';
describe('TelemetryApproval', () => { describe('TelemetryApproval', () => {
it('click on checkbox should be properly handled', () => { it('click on checkbox should be properly handled', () => {
render(<TelemetryApproval />); const helpText = 'My help text';
render(<TelemetryApproval helpText={helpText} />);
expect(screen.getByRole('checkbox')).toHaveAttribute( expect(screen.getByRole('checkbox')).toHaveAttribute(
'data-state', 'data-state',
'unchecked' 'unchecked'
@@ -15,5 +16,7 @@ describe('TelemetryApproval', () => {
'data-state', 'data-state',
'checked' 'checked'
); );
expect(screen.getByText('Share usage data')).toBeInTheDocument();
expect(screen.getByText(helpText)).toBeInTheDocument();
}); });
}); });
@@ -2,11 +2,7 @@ import { Checkbox } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import { useTelemetryApproval } from '../../lib/hooks/use-telemetry-approval'; import { useTelemetryApproval } from '../../lib/hooks/use-telemetry-approval';
export const TelemetryApproval = ({ export const TelemetryApproval = ({ helpText }: { helpText: string }) => {
isSettingsPage,
}: {
isSettingsPage?: boolean;
}) => {
const [isApproved, setIsApproved] = useTelemetryApproval(); const [isApproved, setIsApproved] = useTelemetryApproval();
return ( return (
<div className="flex flex-col px-2 py-3"> <div className="flex flex-col px-2 py-3">
@@ -19,13 +15,7 @@ export const TelemetryApproval = ({
/> />
</div> </div>
<div className="text-sm text-vega-light-300 dark:text-vega-dark-300 ml-6"> <div className="text-sm text-vega-light-300 dark:text-vega-dark-300 ml-6">
<span> <span>{helpText}</span>
{t(
'Help identify bugs and improve the service by sharing anonymous usage data.'
)}
{!isSettingsPage &&
' ' + t('You can change this in your settings at any time.')}
</span>
</div> </div>
</div> </div>
); );
@@ -9,8 +9,11 @@ import { RiskNoticeDialog } from './risk-notice-dialog';
import { WelcomeNoticeDialog } from './welcome-notice-dialog'; import { WelcomeNoticeDialog } from './welcome-notice-dialog';
import { WelcomeLandingDialog } from './welcome-landing-dialog'; import { WelcomeLandingDialog } from './welcome-landing-dialog';
import { useGlobalStore } from '../../stores'; import { useGlobalStore } from '../../stores';
import { useEnvironment } from '@vegaprotocol/environment';
import { Networks } from '@vegaprotocol/environment';
export const WelcomeDialog = () => { export const WelcomeDialog = () => {
const { VEGA_ENV } = useEnvironment();
const { pathname } = useLocation(); const { pathname } = useLocation();
let dialogContent: React.ReactNode; let dialogContent: React.ReactNode;
let title = ''; let title = '';
@@ -33,8 +36,10 @@ export const WelcomeDialog = () => {
}, [update, isRiskDialogNeeded]); }, [update, isRiskDialogNeeded]);
if (isRiskDialogNeeded) { if (isRiskDialogNeeded) {
dialogContent = <RiskNoticeDialog onClose={onCloseDialog} />; dialogContent = (
title = t('WARNING'); <RiskNoticeDialog onClose={onCloseDialog} network={VEGA_ENV} />
);
title = VEGA_ENV === Networks.MAINNET ? t('WARNING') : t('Vega Console');
size = 'medium'; size = 'medium';
} else if (isWelcomeDialogNeeded && data?.length === 0) { } else if (isWelcomeDialogNeeded && data?.length === 0) {
dialogContent = <WelcomeNoticeDialog />; dialogContent = <WelcomeNoticeDialog />;
@@ -41,7 +41,17 @@ const MARKET_A: PartialMarket = {
symbol: 'ABC', symbol: 'ABC',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {
id: '', __typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecForSettlementData: {
__typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecBinding: {
__typename: 'DataSourceSpecToFutureBinding',
tradingTerminationProperty: 'trading-termination-property',
settlementDataProperty: 'settlement-data-property',
}, },
}, },
metadata: { metadata: {
@@ -117,7 +127,17 @@ const MARKET_B: PartialMarket = {
symbol: 'XYZ', symbol: 'XYZ',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {
id: '', __typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecForSettlementData: {
__typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecBinding: {
__typename: 'DataSourceSpecToFutureBinding',
tradingTerminationProperty: 'trading-termination-property',
settlementDataProperty: 'settlement-data-property',
}, },
}, },
metadata: { metadata: {
+46 -1
View File
@@ -1,3 +1,7 @@
@import 'ag-grid-community/dist/styles/ag-grid.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@@ -24,7 +28,8 @@ html.dark {
@apply border-vega-light-200 dark:border-vega-dark-200; @apply border-vega-light-200 dark:border-vega-dark-200;
} }
/* Styles for charts */ /* PENNANT */
html [data-theme='dark'] { html [data-theme='dark'] {
--pennant-color-danger: theme('colors.vega.pink.DEFAULT'); --pennant-color-danger: theme('colors.vega.pink.DEFAULT');
@@ -71,3 +76,43 @@ html [data-theme='light'] {
--pennant-color-depth-sell-fill: theme('colors.vega.pink.400'); --pennant-color-depth-sell-fill: theme('colors.vega.pink.400');
--pennant-color-depth-sell-stroke: theme('colors.vega.pink.550'); --pennant-color-depth-sell-stroke: theme('colors.vega.pink.550');
} }
/* AG GRID - Do not edit without updating other global stylesheets for each app */
.vega-ag-grid .ag-root-wrapper {
border: solid 0px;
}
.vega-ag-grid .ag-react-container {
overflow: hidden;
text-overflow: ellipsis;
}
.vega-ag-grid .ag-cell,
.vega-ag-grid .ag-full-width-row .ag-cell-wrapper.ag-row-group {
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
/* Light variables */
.ag-theme-balham {
--ag-background-color: theme(colors.white);
--ag-border-color: theme(colors.neutral[300]);
--ag-header-background-color: theme(colors.white);
--ag-odd-row-background-color: theme(colors.white);
--ag-header-column-separator-color: theme(colors.neutral[300]);
--ag-row-border-color: theme(colors.white);
--ag-row-hover-color: theme(colors.neutral[100]);
--ag-font-size: 12px;
}
/* Dark variables */
.ag-theme-balham-dark {
--ag-background-color: theme(colors.black);
--ag-border-color: theme(colors.neutral[700]);
--ag-header-background-color: theme(colors.black);
--ag-odd-row-background-color: theme(colors.black);
--ag-header-column-separator-color: theme(colors.neutral[600]);
--ag-row-border-color: theme(colors.black);
--ag-row-hover-color: theme(colors.neutral[800]);
--ag-font-size: 12px;
}
@@ -23,7 +23,7 @@ describe('AccountManager', () => {
data: [], data: [],
}; };
}) })
.mockImplementationOnce((args) => { .mockImplementation((args) => {
return { return {
data: [ data: [
{ asset: { id: 'a1' }, party: { id: 't1' } }, { asset: { id: 'a1' }, party: { id: 't1' } },
@@ -49,7 +49,7 @@ describe('AccountManager', () => {
(helpers.useDataProvider as jest.Mock).mock.calls[0][0].variables (helpers.useDataProvider as jest.Mock).mock.calls[0][0].variables
.partyId .partyId
).toEqual('partyOne'); ).toEqual('partyOne');
await act(() => { await act(async () => {
rerender( rerender(
<AccountManager <AccountManager
partyId="partyTwo" partyId="partyTwo"
@@ -66,7 +66,7 @@ describe('AccountManager', () => {
it('update method should return proper result', async () => { it('update method should return proper result', async () => {
let rerenderer: (ui: React.ReactElement) => void; let rerenderer: (ui: React.ReactElement) => void;
await act(() => { await act(async () => {
const { rerender } = render( const { rerender } = render(
<AccountManager <AccountManager
partyId="partyOne" partyId="partyOne"
@@ -79,7 +79,7 @@ describe('AccountManager', () => {
await waitFor(() => { await waitFor(() => {
expect(screen.getByText('No accounts')).toBeInTheDocument(); expect(screen.getByText('No accounts')).toBeInTheDocument();
}); });
await act(() => { await act(async () => {
rerenderer( rerenderer(
<AccountManager <AccountManager
partyId="partyOne" partyId="partyOne"
+6 -2
View File
@@ -22,7 +22,7 @@ import {
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit'; import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
import { import {
AgGridDynamic as AgGrid, AgGridLazy as AgGrid,
CenteredGridCellWrapper, CenteredGridCellWrapper,
} from '@vegaprotocol/datagrid'; } from '@vegaprotocol/datagrid';
import { AgGridColumn } from 'ag-grid-react'; import { AgGridColumn } from 'ag-grid-react';
@@ -299,6 +299,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
<DropdownMenuTrigger <DropdownMenuTrigger
iconName="more" iconName="more"
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full" className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
data-testid="dropdown-menu"
></DropdownMenuTrigger> ></DropdownMenuTrigger>
} }
> >
@@ -359,7 +360,10 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
} }
</AgGrid> </AgGrid>
<Dialog size="medium" open={openBreakdown} onChange={setOpenBreakdown}> <Dialog size="medium" open={openBreakdown} onChange={setOpenBreakdown}>
<div className="h-[35vh] w-full m-auto flex flex-col"> <div
className="h-[35vh] w-full m-auto flex flex-col"
data-testid="usage-breakdown"
>
<h1 className="text-xl mb-4"> <h1 className="text-xl mb-4">
{row?.asset?.symbol} {t('usage breakdown')} {row?.asset?.symbol} {t('usage breakdown')}
</h1> </h1>
+1 -1
View File
@@ -11,7 +11,7 @@ import type {
VegaValueFormatterParams, VegaValueFormatterParams,
} from '@vegaprotocol/datagrid'; } from '@vegaprotocol/datagrid';
import { progressBarCellRendererSelector } from '@vegaprotocol/datagrid'; import { progressBarCellRendererSelector } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid, PriceCell } from '@vegaprotocol/datagrid'; import { AgGridLazy as AgGrid, PriceCell } from '@vegaprotocol/datagrid';
import type { ValueFormatterParams } from 'ag-grid-community'; import type { ValueFormatterParams } from 'ag-grid-community';
import { accountValuesComparator } from './accounts-table'; import { accountValuesComparator } from './accounts-table';
+1
View File
@@ -17,6 +17,7 @@ export * from '../market-list/src/lib/market-data.mock';
export * from '../market-list/src/lib/markets-candles.mock'; export * from '../market-list/src/lib/markets-candles.mock';
export * from '../market-list/src/lib/markets-data.mock'; export * from '../market-list/src/lib/markets-data.mock';
export * from '../market-list/src/lib/markets.mock'; export * from '../market-list/src/lib/markets.mock';
export * from '../oracles/src/lib/oracle-spec-data-connection.mock';
export * from '../orders/src/lib/components/order-data-provider/orders.mock'; export * from '../orders/src/lib/components/order-data-provider/orders.mock';
export * from '../positions/src/lib/positions.mock'; export * from '../positions/src/lib/positions.mock';
export * from '../react-helpers/src/hooks/network-params.mock'; export * from '../react-helpers/src/hooks/network-params.mock';
+4 -1
View File
@@ -1 +1,4 @@
export const ASSET_ID_FOR_MARKET = 'fUSDC'; export const ASSET_ID_FOR_MARKET =
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc';
export const ASSET_SYMBOL = 'fUSDC';
@@ -4,7 +4,7 @@ import { createLog } from './logging';
import type { ProposalSubmissionBody } from '@vegaprotocol/wallet'; import type { ProposalSubmissionBody } from '@vegaprotocol/wallet';
import { getProposal } from './get-proposal'; import { getProposal } from './get-proposal';
import { sendVegaTx } from './wallet-client'; import { sendVegaTx } from './wallet-client';
import { ASSET_ID_FOR_MARKET } from './contants'; import { ASSET_ID_FOR_MARKET, ASSET_SYMBOL } from './contants';
const log = createLog('propose-market'); const log = createLog('propose-market');
@@ -43,7 +43,7 @@ function createNewMarketProposal(): ProposalSubmissionBody {
code: 'TEST.24h', code: 'TEST.24h',
future: { future: {
settlementAsset: ASSET_ID_FOR_MARKET, settlementAsset: ASSET_ID_FOR_MARKET,
quoteName: ASSET_ID_FOR_MARKET, quoteName: ASSET_SYMBOL,
dataSourceSpecForSettlementData: { dataSourceSpecForSettlementData: {
external: { external: {
oracle: { oracle: {
+1 -1
View File
@@ -66,7 +66,7 @@ export function addGetAssets() {
cy.request({ cy.request({
method: 'POST', method: 'POST',
url: 'http://localhost:3028/query', url: 'http://localhost:3008/graphql',
body: { body: {
query: print(query), query: print(query),
}, },
@@ -24,7 +24,7 @@ export function addGetNetworkParameters() {
}`; }`;
cy.request({ cy.request({
method: 'POST', method: 'POST',
url: `http://localhost:3028/query`, url: `http://localhost:3008/graphql`,
body: { body: {
query: mutation, query: mutation,
}, },
+1 -1
View File
@@ -43,7 +43,7 @@ export function addGetNodes() {
cy.request({ cy.request({
method: 'POST', method: 'POST',
url: `http://localhost:3028/query`, url: `http://localhost:3008/graphql`,
body: { body: {
query: print(query), query: print(query),
}, },
-1
View File
@@ -1,4 +1,3 @@
export * from './lib/ag-grid/ag-grid-dynamic';
export * from './lib/ag-grid/ag-grid-lazy'; export * from './lib/ag-grid/ag-grid-lazy';
export * from './lib/cells/cumulative-vol-cell'; export * from './lib/cells/cumulative-vol-cell';
@@ -1,50 +0,0 @@
import type { ReactNode } from 'react';
import colors from 'tailwindcss/colors';
import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
const agGridDarkVariables = `
.ag-theme-balham-dark {
--ag-background-color: ${colors.black};
--ag-border-color: ${colors.neutral[700]};
--ag-header-background-color: ${colors.black};
--ag-odd-row-background-color: ${colors.black};
--ag-header-column-separator-color: ${colors.neutral[600]};
--ag-row-border-color:${colors.black};
--ag-row-hover-color: ${colors.neutral[800]};
--ag-font-size: 12px;
}
.ag-theme-balham-dark .ag-root-wrapper {
border: 0;
}
.ag-theme-balham-dark .ag-row {
border-width: 1px 0;
border-bottom: 1px solid transparent;
}
.ag-theme-balham-dark .ag-row.no-hover, .ag-theme-balham-dark .ag-row.no-hover:hover {
background: black;
}
.ag-theme-balham-dark .ag-react-container {
overflow: hidden;
text-overflow: ellipsis;
}
.ag-theme-balham-dark .ag-cell, .ag-theme-balham-dark .ag-full-width-row .ag-cell-wrapper.ag-row-group {
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
`;
export const AgGrid = ({
children,
customThemeParams,
}: {
children: ReactNode;
customThemeParams?: string;
}) => (
<>
<style>{agGridDarkVariables}</style>
{customThemeParams && <style>{customThemeParams}</style>}
{children}
</>
);
@@ -1,59 +0,0 @@
import type { ReactNode, FunctionComponent } from 'react';
import dynamic from 'next/dynamic';
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
import { AgGridReact } from 'ag-grid-react';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import 'ag-grid-community/dist/styles/ag-grid.css';
interface GridProps {
children: ReactNode;
customThemeParams: string;
}
const AgGridLightTheme = dynamic<GridProps>(
() => import('./ag-grid-light').then((mod) => mod.AgGrid),
{ ssr: false }
) as FunctionComponent<GridProps>;
const AgGridDarkTheme = dynamic(
() => import('./ag-grid-dark').then((mod) => mod.AgGrid),
{ ssr: false }
) as FunctionComponent<GridProps>;
export const AgGridThemed = ({
style,
className,
gridRef,
customThemeParams = '',
...props
}: (AgGridReactProps | AgReactUiProps) & {
style?: React.CSSProperties;
className?: string;
gridRef?: React.ForwardedRef<AgGridReact>;
customThemeParams?: string;
}) => {
const { theme } = useThemeSwitcher();
const defaultProps = {
rowHeight: 22,
headerHeight: 22,
enableCellTextSelection: true,
};
return (
<div
className={`${className ?? ''} ${
theme === 'dark' ? 'ag-theme-balham-dark' : 'ag-theme-balham'
}`}
style={style}
>
{theme === 'dark' ? (
<AgGridDarkTheme customThemeParams={customThemeParams}>
<AgGridReact {...defaultProps} {...props} ref={gridRef} />
</AgGridDarkTheme>
) : (
<AgGridLightTheme customThemeParams={customThemeParams}>
<AgGridReact {...defaultProps} {...props} ref={gridRef} />
</AgGridLightTheme>
)}
</div>
);
};
@@ -1,29 +0,0 @@
import * as React from 'react';
import dynamic from 'next/dynamic';
import type {
AgGridReactProps,
AgReactUiProps,
AgGridReact,
} from 'ag-grid-react';
type Props = (AgGridReactProps | AgReactUiProps) & {
style?: React.CSSProperties;
className?: string;
gridRef?: React.Ref<AgGridReact>;
customThemeParams?: string;
};
// https://stackoverflow.com/questions/69433673/nextjs-reactdomserver-does-not-yet-support-suspense
const AgGridDynamicInternal = dynamic<Props>(
() => import('./ag-grid-dynamic-themed').then((mod) => mod.AgGridThemed),
{
ssr: false,
// https://nextjs.org/docs/messages/invalid-dynamic-suspense
// suspense: true
}
) as React.FunctionComponent<Props>;
export const AgGridDynamic = React.forwardRef<AgGridReact, Props>(
(props, ref) => <AgGridDynamicInternal {...props} gridRef={ref} />
);
@@ -1,45 +1,30 @@
import * as React from 'react';
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react'; import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
import { AgGridReact } from 'ag-grid-react'; import { AgGridReact } from 'ag-grid-react';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers'; import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import 'ag-grid-community/dist/styles/ag-grid.css'; import classNames from 'classnames';
const AgGridLightTheme = React.lazy(() => export const AgGridThemed = ({
import('./ag-grid-light').then((module) => ({ style,
default: module.AgGrid, gridRef,
})) ...props
); }: (AgGridReactProps | AgReactUiProps) & {
style?: React.CSSProperties;
const AgGridDarkTheme = React.lazy(() => gridRef?: React.ForwardedRef<AgGridReact>;
import('./ag-grid-dark').then((module) => ({ }) => {
default: module.AgGrid,
}))
);
export const AgGridThemed = React.forwardRef<
AgGridReact,
(AgGridReactProps | AgReactUiProps) & {
style?: React.CSSProperties;
className?: string;
}
>(({ style, className, ...props }, ref) => {
const { theme } = useThemeSwitcher(); const { theme } = useThemeSwitcher();
const defaultProps = {
rowHeight: 22,
headerHeight: 22,
enableCellTextSelection: true,
};
const wrapperClasses = classNames('vega-ag-grid', {
'ag-theme-balham': theme === 'light',
'ag-theme-balham-dark': theme === 'dark',
});
return ( return (
<div <div className={wrapperClasses} style={style}>
className={`${className ?? ''} ${ <AgGridReact {...defaultProps} {...props} ref={gridRef} />
theme === 'dark' ? 'ag-theme-balham-dark' : 'ag-theme-balham'
}`}
style={style}
>
{theme === 'dark' ? (
<AgGridDarkTheme>
<AgGridReact {...props} ref={ref} enableCellTextSelection={true} />
</AgGridDarkTheme>
) : (
<AgGridLightTheme>
<AgGridReact {...props} ref={ref} enableCellTextSelection={true} />
</AgGridLightTheme>
)}
</div> </div>
); );
}); };
+10 -5
View File
@@ -1,12 +1,17 @@
import * as React from 'react'; import { forwardRef, lazy } from 'react';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReactProps, AgGridReact } from 'ag-grid-react';
export const AgGridLazyInternal = React.lazy(() => type Props = AgGridReactProps & {
style?: React.CSSProperties;
gridRef?: React.Ref<AgGridReact>;
};
export const AgGridLazyInternal = lazy(() =>
import('./ag-grid-lazy-themed').then((module) => ({ import('./ag-grid-lazy-themed').then((module) => ({
default: module.AgGridThemed, default: module.AgGridThemed,
})) }))
); );
export const AgGridLazy = React.forwardRef<AgGridReact>((props, ref) => ( export const AgGridLazy = forwardRef<AgGridReact, Props>((props, ref) => (
<AgGridLazyInternal {...props} ref={ref} /> <AgGridLazyInternal {...props} gridRef={ref} />
)); ));
@@ -1,50 +0,0 @@
import type { ReactNode } from 'react';
import colors from 'tailwindcss/colors';
import 'ag-grid-community/dist/styles/ag-theme-balham.css';
const agGridLightVariables = `
.ag-theme-balham {
--ag-background-color: ${colors.white};
--ag-border-color: ${colors.neutral[300]};
--ag-header-background-color: ${colors.white};
--ag-odd-row-background-color: ${colors.white};
--ag-header-column-separator-color: ${colors.neutral[300]};
--ag-row-border-color: ${colors.white};
--ag-row-hover-color: ${colors.neutral[100]};
--ag-font-size: 12px;
}
.ag-theme-balham .ag-root-wrapper {
border: 0;
}
.ag-theme-balham .ag-row {
border-width: 1px 0;
border-bottom: 1px solid transparent;
}
.ag-theme-balham .ag-row.no-hover, .ag-theme-balham .ag-row.no-hover:hover {
background: white;
}
.ag-theme-balham .ag-react-container {
overflow: hidden;
text-overflow: ellipsis;
}
.ag-theme-balham .ag-cell, .ag-theme-balham .ag-full-width-row .ag-cell-wrapper.ag-row-group {
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
`;
export const AgGrid = ({
children,
customThemeParams,
}: {
children: ReactNode;
customThemeParams?: string;
}) => (
<>
<style>{agGridLightVariables}</style>
{customThemeParams && <style>{customThemeParams}</style>}
{children}
</>
);
+11 -1
View File
@@ -35,7 +35,17 @@ export function generateMarket(override?: PartialDeep<Market>): Market {
__typename: 'Asset', __typename: 'Asset',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {
id: '', __typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecForSettlementData: {
__typename: 'DataSourceSpec',
id: 'oracleId',
},
dataSourceSpecBinding: {
__typename: 'DataSourceSpecToFutureBinding',
tradingTerminationProperty: 'trading-termination-property',
settlementDataProperty: 'settlement-data-property',
}, },
quoteName: 'BTC', quoteName: 'BTC',
__typename: 'Future', __typename: 'Future',

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