Compare commits
46
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e58c6656c | ||
|
|
030a5526eb | ||
|
|
d69d5ba39f | ||
|
|
e3c0ed3330 | ||
|
|
4d114ecf0d | ||
|
|
fe57be9cdb | ||
|
|
a7cec0b1b7 | ||
|
|
8bc5930bc1 | ||
|
|
2783729f47 | ||
|
|
ccb54af636 | ||
|
|
0cab5aaaf6 | ||
|
|
379b6cde7f | ||
|
|
8a1fe6e5b1 | ||
|
|
437f7ef807 | ||
|
|
2b3683d4a4 | ||
|
|
6c84153cdb | ||
|
|
ccce5a2848 | ||
|
|
5673620fbd | ||
|
|
41d6940b89 | ||
|
|
84150bec8c | ||
|
|
5a311d14c9 | ||
|
|
0f152a4b30 | ||
|
|
45d8b537a3 | ||
|
|
dc41be5715 | ||
|
|
a85cf66419 | ||
|
|
6e82e917ac | ||
|
|
8dfdccd4aa | ||
|
|
82833cc06a | ||
|
|
aac3799b14 | ||
|
|
0d1c9ff0f1 | ||
|
|
f8eec8a056 | ||
|
|
ee6f26d473 | ||
|
|
de62d2d972 | ||
|
|
955e233c46 | ||
|
|
0bafa4c7d5 | ||
|
|
045529dc38 | ||
|
|
5ca3e4d90f | ||
|
|
9048d41f72 | ||
|
|
d731c4797c | ||
|
|
4a931ca134 | ||
|
|
3398b15d8a | ||
|
|
1e98ecbd21 | ||
|
|
a9c7c2bb46 | ||
|
|
ba2c71de67 | ||
|
|
15d2aed343 | ||
|
|
0284eaf9a2 |
@@ -67,6 +67,7 @@ describe('market selector', { tags: '@smoke' }, () => {
|
||||
it('mobile view', () => {
|
||||
cy.viewport('iphone-xr');
|
||||
cy.visit(`/trading/${marketId}`);
|
||||
cy.connectVegaWallet();
|
||||
cy.get('[role="dialog"]').should('not.exist');
|
||||
cy.getByTestId('arrow-button').click();
|
||||
cy.get('[role="dialog"]').should('be.visible');
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import type { FieldErrors } from 'react-hook-form';
|
||||
import { useMemo } from 'react';
|
||||
import { t, toDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { DataGrid, t, toDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
MarketDataGrid,
|
||||
compileGridData,
|
||||
MarginWarning,
|
||||
isMarketInAuction,
|
||||
@@ -216,9 +215,7 @@ export const useOrderValidation = ({
|
||||
<span>
|
||||
{t('This market is in auction until it reaches')}{' '}
|
||||
<Tooltip
|
||||
description={
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
}
|
||||
description={<DataGrid grid={compileGridData(market)} />}
|
||||
>
|
||||
<span>{t('sufficient liquidity')}</span>
|
||||
</Tooltip>
|
||||
@@ -240,9 +237,7 @@ export const useOrderValidation = ({
|
||||
<span>
|
||||
{t('This market is in auction due to')}{' '}
|
||||
<Tooltip
|
||||
description={
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
}
|
||||
description={<DataGrid grid={compileGridData(market)} />}
|
||||
>
|
||||
<span>{t('high price volatility')}</span>
|
||||
</Tooltip>
|
||||
@@ -281,9 +276,7 @@ export const useOrderValidation = ({
|
||||
<span>
|
||||
{t('This market is in auction until it reaches')}{' '}
|
||||
<Tooltip
|
||||
description={
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
}
|
||||
description={<DataGrid grid={compileGridData(market)} />}
|
||||
>
|
||||
<span>{t('sufficient liquidity')}</span>
|
||||
</Tooltip>
|
||||
@@ -307,9 +300,7 @@ export const useOrderValidation = ({
|
||||
<span>
|
||||
{t('This market is in auction due to')}{' '}
|
||||
<Tooltip
|
||||
description={
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
}
|
||||
description={<DataGrid grid={compileGridData(market)} />}
|
||||
>
|
||||
<span>{t('high price volatility')}</span>
|
||||
</Tooltip>
|
||||
|
||||
@@ -4,6 +4,7 @@ NX_TENDERMINT_URL=https://n04.d.vega.xyz/tm
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
|
||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -4,6 +4,7 @@ NX_TENDERMINT_URL=https://mainnet-observer-proxy01.ops.vega.xyz/
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
|
||||
NX_VEGA_URL=https://api.vega.xyz/query
|
||||
NX_VEGA_ENV=MAINNET
|
||||
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -4,6 +4,7 @@ NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
|
||||
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -4,6 +4,7 @@ NX_TENDERMINT_URL=https://tm.n07.testnet.vega.xyz/tm
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
|
||||
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# Vega Explorer E2E tests
|
||||
|
||||
To run the UI automation tests with Vega Capsule, run:
|
||||
|
||||
```bash
|
||||
yarn nx run explorer-e2e:e2e
|
||||
```
|
||||
|
||||
To open Cypress and run in interactive mode, run:
|
||||
|
||||
```bash
|
||||
yarn nx run explorer-e2e:e2e --watch
|
||||
```
|
||||
|
||||
## Vega Capsule Setup
|
||||
|
||||
The e2e tests run against a locally running instance of the Vega network, managed and controlled by [Vega Capsule](https://github.com/vegaprotocol/vegacapsule). Vega Capsule will:
|
||||
|
||||
- Bootstrap and start up a Vega network
|
||||
- Start up [Ganache](https://trufflesuite.com/ganache/) for a local Ethereum network
|
||||
- Install the required Vega smart contracts
|
||||
- Set up DataNodes with a running GraphQL and REST APIs.
|
||||
|
||||
Refer to the [Vega Capsule readme](https://github.com/vegaprotocol/vegacapsule#readme) for setting up and running Capsule. You will need [Go 1.19 or later](https://go.dev/doc/install) and [Docker](https://docs.docker.com/get-docker/) installed.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- You may need to run `vegacapsule nodes unsafe-reset-all` to get a clean network state
|
||||
|
||||
## Vega Wallet Setup
|
||||
|
||||
Start by [downloading the Vega wallet software here](https://github.com/vegaprotocol/vega/releases).
|
||||
|
||||
You can then refer to (or run) `vegacapsule/setup-vegawallet.sh`. This will initialise and configure your wallet to have the correct public keys and network config to run against capsule.
|
||||
@@ -52,7 +52,8 @@ context('Blocks page', { tags: '@regression' }, function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Previous button disabled on first block', function () {
|
||||
// Skipping - see https://github.com/vegaprotocol/frontend-monorepo/issues/2494
|
||||
it.skip('Previous button disabled on first block', function () {
|
||||
cy.get('[data-testid="block-input"]').type('1');
|
||||
cy.get('[data-testid="go-submit"]').click();
|
||||
cy.get(previousBlockBtn).find('button').should('be.disabled');
|
||||
@@ -115,7 +116,7 @@ context('Blocks page', { tags: '@regression' }, function () {
|
||||
});
|
||||
|
||||
function waitForBlocksResponse() {
|
||||
cy.contains('Loading...').should('not.exist', { timeout: 18000 });
|
||||
cy.get('[data-testid="loader"]').should('not.exist', { timeout: 18000 });
|
||||
}
|
||||
|
||||
function validateBlocksDisplayed() {
|
||||
|
||||
@@ -20,19 +20,18 @@ context('Home Page', function () {
|
||||
1: 'Height',
|
||||
2: 'Uptime',
|
||||
3: 'Total nodes',
|
||||
4: 'Inactive nodes',
|
||||
5: 'Total staked',
|
||||
6: 'Backlog',
|
||||
7: 'Trades / second',
|
||||
8: 'Orders / block',
|
||||
9: 'Orders / second',
|
||||
10: 'Transactions / block',
|
||||
11: 'Block time',
|
||||
12: 'Time',
|
||||
13: 'App',
|
||||
14: 'Tendermint',
|
||||
15: 'Up since',
|
||||
16: 'Chain ID',
|
||||
4: 'Total staked',
|
||||
5: 'Backlog',
|
||||
6: 'Trades / second',
|
||||
7: 'Orders / block',
|
||||
8: 'Orders / second',
|
||||
9: 'Transactions / block',
|
||||
10: 'Block time',
|
||||
11: 'Time',
|
||||
12: 'App',
|
||||
13: 'Tendermint',
|
||||
14: 'Up since',
|
||||
15: 'Chain ID',
|
||||
};
|
||||
|
||||
cy.get('[data-testid="stats-title"]')
|
||||
@@ -40,7 +39,7 @@ context('Home Page', function () {
|
||||
cy.wrap($list).should('have.text', statTitles[index]);
|
||||
})
|
||||
.then(($list) => {
|
||||
cy.wrap($list).should('have.length', 17);
|
||||
cy.wrap($list).should('have.length', 16);
|
||||
});
|
||||
|
||||
cy.get(statsValue).eq(0).should('have.text', 'CONNECTED');
|
||||
@@ -50,30 +49,29 @@ context('Home Page', function () {
|
||||
.invoke('text')
|
||||
.should('match', /\d+d \d+h \d+m \d+s/i);
|
||||
cy.get(statsValue).eq(3).should('have.text', '2');
|
||||
cy.get(statsValue).eq(4).should('have.text', '2');
|
||||
cy.get(statsValue)
|
||||
.eq(5)
|
||||
.eq(4)
|
||||
.invoke('text')
|
||||
.should('match', /\d+\.\d\d(?!\d)/i);
|
||||
cy.get(statsValue).eq(5).should('have.text', '0');
|
||||
cy.get(statsValue).eq(6).should('have.text', '0');
|
||||
cy.get(statsValue).eq(7).should('have.text', '0');
|
||||
cy.get(statsValue).eq(8).should('have.text', '0');
|
||||
cy.get(statsValue).eq(9).should('have.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).should('not.be.empty');
|
||||
if (Cypress.env('NIGHTLY_RUN') != true) {
|
||||
cy.get(statsValue)
|
||||
.eq(13)
|
||||
.eq(12)
|
||||
.invoke('text')
|
||||
.should('match', /v\d+\.\d+\.\d+/i);
|
||||
}
|
||||
cy.get(statsValue)
|
||||
.eq(14)
|
||||
.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');
|
||||
cy.get(statsValue).eq(16).should('not.be.empty');
|
||||
});
|
||||
|
||||
it('Block height should be updating', function () {
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.62.1/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.65.1/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -59,7 +59,8 @@ describe('Blocks infinite list', () => {
|
||||
error={undefined}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('No items')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('emptylist')).toBeInTheDocument();
|
||||
expect(screen.getByText('This chain has 0 blocks')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('error is displayed at item level', () => {
|
||||
|
||||
@@ -4,6 +4,8 @@ import InfiniteLoader from 'react-window-infinite-loader';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { BlockMeta } from '../../routes/blocks/tendermint-blockchain-response';
|
||||
import { BlockData } from './block-data';
|
||||
import EmptyList from '../empty-list/empty-list';
|
||||
import { Loader } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
interface BlocksInfiniteListProps {
|
||||
hasMoreBlocks: boolean;
|
||||
@@ -31,7 +33,16 @@ export const BlocksInfiniteList = ({
|
||||
className,
|
||||
}: BlocksInfiniteListProps) => {
|
||||
if (!blocks) {
|
||||
return <div>No items</div>;
|
||||
if (!areBlocksLoading) {
|
||||
return (
|
||||
<EmptyList
|
||||
heading={t('This chain has 0 blocks')}
|
||||
label={t('Check back soon')}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <Loader />;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are more items to be loaded then add an extra row to hold a loading indicator.
|
||||
@@ -50,7 +61,7 @@ export const BlocksInfiniteList = ({
|
||||
if (error) {
|
||||
content = t(`${error}`);
|
||||
} else if (!isItemLoaded(index)) {
|
||||
content = t('Loading...');
|
||||
content = <Loader />;
|
||||
} else {
|
||||
content = <BlockData block={blocks[index]} />;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
export type EmptyListProps = {
|
||||
heading?: string;
|
||||
label?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the empty state from github ticket #1463
|
||||
*/
|
||||
const EmptyList = ({ heading, label }: EmptyListProps) => {
|
||||
return (
|
||||
<div
|
||||
className="empty-list w-full items-center h-full align-center"
|
||||
data-testid="emptylist"
|
||||
>
|
||||
<div className="skeleton-list border-dashed border-neutral-800 rounded p-5 w-full border-[1px] grid gap-4 grid-cols-9 grid-rows-1 place-content-around mb-4">
|
||||
<div className="bg-neutral-900 mr-5 h-3 col-span-5"></div>
|
||||
<div className="bg-neutral-900 h-3 col-span-1"></div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4">
|
||||
{heading ? (
|
||||
<h1 className="font-alpha text-xl uppercase text-center leading-relaxed">
|
||||
{heading}
|
||||
</h1>
|
||||
) : null}
|
||||
{label ? (
|
||||
<p className="font-alpha text-gray-500 text-center">{label}</p>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmptyList;
|
||||
@@ -14,8 +14,6 @@ export const methodText: Record<
|
||||
METHOD_NOW: 'Immediate',
|
||||
METHOD_UNSPECIFIED: 'Unspecified',
|
||||
METHOD_AT_END_OF_EPOCH: 'End of epoch',
|
||||
// This will be removed in a future release
|
||||
METHOD_IN_ANGER: 'Immediate',
|
||||
};
|
||||
|
||||
interface TxDetailsUndelegateProps {
|
||||
|
||||
@@ -2,4 +2,3 @@ export { TxList } from './tx-list';
|
||||
export { TxOrderType } from './tx-order-type';
|
||||
export { TxsInfiniteList } from './txs-infinite-list';
|
||||
export { TxsInfiniteListItem } from './txs-infinite-list-item';
|
||||
export { TxsStatsInfo } from './txs-stats-info';
|
||||
|
||||
@@ -46,7 +46,10 @@ describe('Txs infinite list', () => {
|
||||
error={undefined}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('No items')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('emptylist')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('This chain has 0 transactions')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('error is displayed at item level', () => {
|
||||
|
||||
@@ -4,6 +4,8 @@ import InfiniteLoader from 'react-window-infinite-loader';
|
||||
import { t, useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
import { TxsInfiniteListItem } from './txs-infinite-list-item';
|
||||
import type { BlockExplorerTransactionResult } from '../../routes/types/block-explorer-response';
|
||||
import EmptyList from '../empty-list/empty-list';
|
||||
import { Loader } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
interface TxsInfiniteListProps {
|
||||
hasMoreTxs: boolean;
|
||||
@@ -29,7 +31,7 @@ const Item = ({ index, style, isLoading, error }: ItemProps) => {
|
||||
if (error) {
|
||||
content = t(`Cannot fetch transaction: ${error}`);
|
||||
} else if (isLoading) {
|
||||
content = t('Loading...');
|
||||
content = <Loader />;
|
||||
} else {
|
||||
const {
|
||||
hash,
|
||||
@@ -68,7 +70,16 @@ export const TxsInfiniteList = ({
|
||||
const isStacked = ['xs', 'sm', 'md', 'lg'].includes(screenSize);
|
||||
|
||||
if (!txs) {
|
||||
return <div>No items</div>;
|
||||
if (!areTxsLoading) {
|
||||
return (
|
||||
<EmptyList
|
||||
heading={t('This chain has 0 transactions')}
|
||||
label={t('Check back soon')}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <Loader />;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are more items to be loaded then add an extra row to hold a loading indicator.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Routes } from '../../routes/route-names';
|
||||
import { DATA_SOURCES } from '../../config';
|
||||
import { RenderFetched } from '../render-fetched';
|
||||
import { TruncatedLink } from '../truncate/truncated-link';
|
||||
import { TxOrderType } from './tx-order-type';
|
||||
@@ -8,6 +7,9 @@ import { t, useFetch } from '@vegaprotocol/react-helpers';
|
||||
import type { BlockExplorerTransactions } from '../../routes/types/block-explorer-response';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
import { ChainResponseCode } from './details/chain-response-code/chain-reponse.code';
|
||||
import { getTxsDataUrl } from '../../hooks/use-txs-data';
|
||||
import { Loader } from '@vegaprotocol/ui-toolkit';
|
||||
import EmptyList from '../empty-list/empty-list';
|
||||
|
||||
interface TxsPerBlockProps {
|
||||
blockHeight: string;
|
||||
@@ -17,15 +19,11 @@ interface TxsPerBlockProps {
|
||||
const truncateLength = 5;
|
||||
|
||||
export const TxsPerBlock = ({ blockHeight, txCount }: TxsPerBlockProps) => {
|
||||
// TODO after https://github.com/vegaprotocol/vega/pull/6958/files is merged and deployed, use filter
|
||||
// by block height instead
|
||||
const filters = `filters[block.height]=${blockHeight}`;
|
||||
const url = getTxsDataUrl({ limit: txCount.toString(), filters });
|
||||
const {
|
||||
state: { data, loading, error },
|
||||
} = useFetch<BlockExplorerTransactions>(
|
||||
`${
|
||||
DATA_SOURCES.blockExplorerUrl
|
||||
}/transactions?before=${blockHeight.toString()}.0&limit=${txCount}`
|
||||
);
|
||||
} = useFetch<BlockExplorerTransactions>(url);
|
||||
|
||||
return (
|
||||
<RenderFetched error={error} loading={loading} className="text-body-large">
|
||||
@@ -88,10 +86,13 @@ export const TxsPerBlock = ({ blockHeight, txCount }: TxsPerBlockProps) => {
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
) : loading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div className="sr-only">
|
||||
{t(`No transactions in block ${blockHeight}`)}
|
||||
</div>
|
||||
<EmptyList
|
||||
heading={t('No transactions in this block')}
|
||||
label={t('0 transactions')}
|
||||
/>
|
||||
)}
|
||||
</RenderFetched>
|
||||
);
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useEffect } from 'react';
|
||||
import { InfoBlock } from '../../components/info-block';
|
||||
import { Panel } from '../../components/panel';
|
||||
import { useExplorerStatsQuery } from './__generated__/Explorer-stats';
|
||||
import type { ExplorerStatsFieldsFragment } from './__generated__/Explorer-stats';
|
||||
|
||||
interface StatsMap {
|
||||
field: keyof ExplorerStatsFieldsFragment;
|
||||
label: string;
|
||||
info: string;
|
||||
}
|
||||
|
||||
export const TXS_STATS_MAP: StatsMap[] = [
|
||||
{
|
||||
field: 'averageOrdersPerBlock',
|
||||
label: t('Orders per block'),
|
||||
info: t(
|
||||
'Number of new orders processed in the last block. All orders derived from pegged orders and liquidity commitments count as a single order'
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'txPerBlock',
|
||||
label: t('Transactions per block'),
|
||||
info: t('Number of transactions processed in the last block'),
|
||||
},
|
||||
{
|
||||
field: 'tradesPerSecond',
|
||||
label: t('Trades per second'),
|
||||
info: t('Number of trades processed in the last second'),
|
||||
},
|
||||
{
|
||||
field: 'ordersPerSecond',
|
||||
label: t('Order per second'),
|
||||
info: t(
|
||||
'Number of orders processed in the last second. All orders derived from pegged orders and liquidity commitments count as a single order'
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
interface TxsStatsInfoProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const TxsStatsInfo = ({ className }: TxsStatsInfoProps) => {
|
||||
const { data, startPolling, stopPolling } = useExplorerStatsQuery();
|
||||
|
||||
useEffect(() => {
|
||||
startPolling(1000);
|
||||
return () => stopPolling();
|
||||
});
|
||||
|
||||
const gridStyles =
|
||||
'grid grid-rows-2 gap-4 grid-cols-2 xl:gap-8 xl:grid-rows-1 xl:grid-cols-4';
|
||||
|
||||
return (
|
||||
<Panel className={className}>
|
||||
<section className={gridStyles}>
|
||||
{TXS_STATS_MAP.map((field) => {
|
||||
if (!data?.statistics) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Workaround for awkward typing
|
||||
const title = data.statistics[field.field] || '';
|
||||
return (
|
||||
<InfoBlock
|
||||
subtitle={field.label}
|
||||
tooltipInfo={field.info}
|
||||
title={title}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
</Panel>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { render } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import Assets from './index';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { ExplorerAssetDocument } from '../../components/links/asset-link/__generated__/Asset';
|
||||
|
||||
function renderComponent(mock: MockedResponse[]) {
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<MockedProvider mocks={mock}>
|
||||
<Assets />
|
||||
</MockedProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
}
|
||||
|
||||
describe('Assets index', () => {
|
||||
it('Renders loader when loading', async () => {
|
||||
const mock = {
|
||||
request: {
|
||||
query: ExplorerAssetDocument,
|
||||
},
|
||||
result: {
|
||||
data: {},
|
||||
},
|
||||
};
|
||||
const res = render(renderComponent([mock]));
|
||||
expect(await res.findByTestId('loader')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders EmptyList when loading completes and there are no results', async () => {
|
||||
const mock = {
|
||||
request: {
|
||||
query: ExplorerAssetDocument,
|
||||
},
|
||||
result: {
|
||||
data: {},
|
||||
},
|
||||
};
|
||||
const res = render(renderComponent([mock]));
|
||||
expect(await res.findByTestId('emptylist')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -2,14 +2,15 @@ import { getNodes, t } from '@vegaprotocol/react-helpers';
|
||||
import React from 'react';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { SubHeading } from '../../components/sub-heading';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { useExplorerAssetsQuery } from './__generated__/Assets';
|
||||
import type { AssetsFieldsFragment } from './__generated__/Assets';
|
||||
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
import EmptyList from '../../components/empty-list/empty-list';
|
||||
|
||||
const Assets = () => {
|
||||
const { data } = useExplorerAssetsQuery();
|
||||
const { data, loading } = useExplorerAssetsQuery();
|
||||
useDocumentTitle(['Assets']);
|
||||
|
||||
useScrollToLocation();
|
||||
@@ -17,17 +18,25 @@ const Assets = () => {
|
||||
const assets = getNodes<AssetsFieldsFragment>(data?.assetsConnection);
|
||||
|
||||
if (!assets || assets.length === 0) {
|
||||
return <section></section>;
|
||||
if (!loading) {
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle data-testid="assets-header">{t('Assets')}</RouteTitle>
|
||||
<EmptyList
|
||||
heading={t('This chain has no assets')}
|
||||
label={t('0 assets')}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
} else {
|
||||
return <Loader />;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle data-testid="assets-header">{t('Assets')}</RouteTitle>
|
||||
{assets.map((a) => {
|
||||
if (!a) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment key={a.id}>
|
||||
<SubHeading data-testid="asset-header" id={a.id}>
|
||||
|
||||
@@ -18,6 +18,7 @@ import { RenderFetched } from '../../../components/render-fetched';
|
||||
import { t, useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { NodeLink } from '../../../components/links';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
import EmptyList from '../../../components/empty-list/empty-list';
|
||||
|
||||
const Block = () => {
|
||||
const { block } = useParams<{ block: string }>();
|
||||
@@ -112,7 +113,12 @@ const Block = () => {
|
||||
blockHeight={blockData.result.block.header.height}
|
||||
txCount={blockData.result.block.data.txs.length}
|
||||
/>
|
||||
) : null}
|
||||
) : (
|
||||
<EmptyList
|
||||
heading={t('This block is empty')}
|
||||
label={t('0 transactions')}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { t, useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { DATA_SOURCES } from '../../config';
|
||||
import type { TendermintGenesisResponse } from './tendermint-genesis-response';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
@@ -9,11 +9,16 @@ const Genesis = () => {
|
||||
useDocumentTitle(['Genesis']);
|
||||
|
||||
const {
|
||||
state: { data: genesis },
|
||||
state: { data: genesis, loading },
|
||||
} = useFetch<TendermintGenesisResponse>(
|
||||
`${DATA_SOURCES.tendermintUrl}/genesis`
|
||||
);
|
||||
if (!genesis?.result.genesis) return null;
|
||||
if (!genesis?.result.genesis) {
|
||||
if (loading) {
|
||||
return <Loader />;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle data-testid="genesis-header">{t('Genesis')}</RouteTitle>
|
||||
|
||||
@@ -2,19 +2,35 @@ import { t } from '@vegaprotocol/react-helpers';
|
||||
import React from 'react';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { SubHeading } from '../../components/sub-heading';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { useExplorerProposalsQuery } from './__generated__/Proposals';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
import EmptyList from '../../components/empty-list/empty-list';
|
||||
|
||||
const Governance = () => {
|
||||
const { data } = useExplorerProposalsQuery({
|
||||
const { data, loading } = useExplorerProposalsQuery({
|
||||
errorPolicy: 'ignore',
|
||||
});
|
||||
|
||||
useDocumentTitle();
|
||||
|
||||
if (!data || !data.proposalsConnection || !data.proposalsConnection.edges) {
|
||||
return <section></section>;
|
||||
if (!loading) {
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle data-testid="governance-header">
|
||||
{t('Governance Proposals')}
|
||||
</RouteTitle>
|
||||
|
||||
<EmptyList
|
||||
heading={t('This chain has no proposals')}
|
||||
label={t('0 proposals')}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
} else {
|
||||
return <Loader />;
|
||||
}
|
||||
}
|
||||
|
||||
const proposals = data?.proposalsConnection?.edges.map((e) => {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { render } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import Markets from './index';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { ExplorerMarketsDocument } from './__generated__/Markets';
|
||||
|
||||
function renderComponent(mock: MockedResponse[]) {
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<MockedProvider mocks={mock}>
|
||||
<Markets />
|
||||
</MockedProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
}
|
||||
|
||||
describe('Markets index', () => {
|
||||
it('Renders loader when loading', async () => {
|
||||
const mock = {
|
||||
request: {
|
||||
query: ExplorerMarketsDocument,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
marketsConnection: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
const res = render(renderComponent([mock]));
|
||||
expect(await res.findByTestId('loader')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders EmptyList when loading completes and there are no results', async () => {
|
||||
const mock = {
|
||||
request: {
|
||||
query: ExplorerMarketsDocument,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
marketsConnection: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
const res = render(renderComponent([mock]));
|
||||
expect(await res.findByTestId('emptylist')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,15 @@
|
||||
import React from 'react';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { SubHeading } from '../../components/sub-heading';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useExplorerMarketsQuery } from './__generated__/Markets';
|
||||
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
import EmptyList from '../../components/empty-list/empty-list';
|
||||
|
||||
const Markets = () => {
|
||||
const { data } = useExplorerMarketsQuery();
|
||||
const { data, loading } = useExplorerMarketsQuery();
|
||||
|
||||
useScrollToLocation();
|
||||
useDocumentTitle(['Markets']);
|
||||
@@ -19,16 +20,23 @@ const Markets = () => {
|
||||
<section key="markets">
|
||||
<RouteTitle data-testid="markets-heading">{t('Markets')}</RouteTitle>
|
||||
|
||||
{m
|
||||
? m.map((e) => (
|
||||
<React.Fragment key={e.node.id}>
|
||||
<SubHeading data-testid="markets-header" id={e.node.id}>
|
||||
{e.node.tradableInstrument.instrument.name}
|
||||
</SubHeading>
|
||||
<SyntaxHighlighter data={e.node} />
|
||||
</React.Fragment>
|
||||
))
|
||||
: null}
|
||||
{m ? (
|
||||
m.map((e) => (
|
||||
<React.Fragment key={e.node.id}>
|
||||
<SubHeading data-testid="markets-header" id={e.node.id}>
|
||||
{e.node.tradableInstrument.instrument.name}
|
||||
</SubHeading>
|
||||
<SyntaxHighlighter data={e.node} />
|
||||
</React.Fragment>
|
||||
))
|
||||
) : loading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<EmptyList
|
||||
heading={t('This chain has no markets')}
|
||||
label={t('0 markets')}
|
||||
/>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { RouteTitle } from '../../../components/route-title';
|
||||
import { BlocksRefetch } from '../../../components/blocks';
|
||||
import { TxsInfiniteList, TxsStatsInfo } from '../../../components/txs';
|
||||
import { TxsInfiniteList } from '../../../components/txs';
|
||||
import { useTxsData } from '../../../hooks/use-txs-data';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
|
||||
@@ -16,7 +16,6 @@ export const TxsList = () => {
|
||||
<section className="md:p-2 lg:p-4 xl:p-6">
|
||||
<RouteTitle>{t('Transactions')}</RouteTitle>
|
||||
<BlocksRefetch refetch={refreshTxs} />
|
||||
<TxsStatsInfo className="!my-12 py-8" />
|
||||
<TxsInfiniteList
|
||||
hasMoreTxs={hasMoreTxs}
|
||||
areTxsLoading={loading}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import React from 'react';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { SubHeading } from '../../components/sub-heading';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { DATA_SOURCES } from '../../config';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import type { TendermintValidatorsResponse } from './tendermint-validator-response';
|
||||
@@ -28,7 +27,9 @@ const Validators = () => {
|
||||
<SubHeading data-testid="vega-header">{t('Vega data')}</SubHeading>
|
||||
<SyntaxHighlighter data-testid="vega-data" data={data} />
|
||||
</>
|
||||
) : null}
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
{validators ? (
|
||||
<>
|
||||
<SubHeading data-testid="tendermint-header">
|
||||
@@ -36,7 +37,9 @@ const Validators = () => {
|
||||
</SubHeading>
|
||||
<SyntaxHighlighter data-testid="tendermint-data" data={validators} />
|
||||
</>
|
||||
) : null}
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
+73
-26
@@ -14,9 +14,17 @@ type OneOf<T extends any[]> = T extends [infer Only]
|
||||
: T extends [infer A, infer B, ...infer Rest]
|
||||
? OneOf<[XOR<A, B>, ...Rest]>
|
||||
: never;
|
||||
/* typescript-eslint:enable no-explicit-any */
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
|
||||
export interface paths {
|
||||
'/info': {
|
||||
/**
|
||||
* Info
|
||||
* @description Retrieves information about the block explorer.
|
||||
* Response contains a semver formatted version of the data node and the commit hash, from which the block explorer was built,
|
||||
*/
|
||||
get: operations['BlockExplorer_Info'];
|
||||
};
|
||||
'/transactions': {
|
||||
/**
|
||||
* List transactions
|
||||
@@ -100,8 +108,7 @@ export interface components {
|
||||
readonly UndelegateSubmissionMethod:
|
||||
| 'METHOD_UNSPECIFIED'
|
||||
| 'METHOD_NOW'
|
||||
| 'METHOD_AT_END_OF_EPOCH'
|
||||
| 'METHOD_IN_ANGER';
|
||||
| 'METHOD_AT_END_OF_EPOCH';
|
||||
readonly blockexplorerapiv1Transaction: {
|
||||
/**
|
||||
* The height of the block the transaction was found in
|
||||
@@ -117,6 +124,11 @@ export interface components {
|
||||
readonly command?: components['schemas']['v1InputData'];
|
||||
/** The cursor for this transaction (in the page, used for paginated results) */
|
||||
readonly cursor?: string;
|
||||
/**
|
||||
* An optional error happening when processing / checking the transaction
|
||||
* Should be set if error code is not 0
|
||||
*/
|
||||
readonly error?: string;
|
||||
/** The hash of the transaction */
|
||||
readonly hash?: string;
|
||||
/**
|
||||
@@ -124,6 +136,8 @@ export interface components {
|
||||
* Format: int64
|
||||
*/
|
||||
readonly index?: number;
|
||||
/** Submitter's signature of transaction */
|
||||
readonly signature?: components['schemas']['v1Signature'];
|
||||
/** The submitter of the transaction (Vega public key) */
|
||||
readonly submitter?: string;
|
||||
/** The type of transaction */
|
||||
@@ -159,7 +173,7 @@ export interface components {
|
||||
readonly '@type'?: string;
|
||||
[key: string]: unknown | undefined;
|
||||
};
|
||||
/** Used announce a node as a new potential validator */
|
||||
/** Used announce a node as a new pending validator */
|
||||
readonly v1AnnounceNode: {
|
||||
/** AvatarURL of the validator */
|
||||
readonly avatarUrl?: string;
|
||||
@@ -192,7 +206,7 @@ export interface components {
|
||||
* Format: int64
|
||||
*/
|
||||
readonly vegaPubKeyIndex?: number;
|
||||
/** Signature from the validator made using the vega wallet */
|
||||
/** Signature from the validator made using the Vega wallet */
|
||||
readonly vegaSignature?: components['schemas']['v1Signature'];
|
||||
};
|
||||
/**
|
||||
@@ -287,6 +301,12 @@ export interface components {
|
||||
/** The transaction corresponding to the hash */
|
||||
readonly transaction?: components['schemas']['blockexplorerapiv1Transaction'];
|
||||
};
|
||||
readonly v1InfoResponse: {
|
||||
/** The commit hash from which the data-node was built */
|
||||
readonly commitHash?: string;
|
||||
/** A semver formatted version of the data node */
|
||||
readonly version?: string;
|
||||
};
|
||||
readonly v1InputData: {
|
||||
readonly announceNode?: components['schemas']['v1AnnounceNode'];
|
||||
readonly batchMarketInstructions?: components['schemas']['v1BatchMarketInstructions'];
|
||||
@@ -351,7 +371,7 @@ export interface components {
|
||||
/** The ID of the node that will be signed in or out of the smartcontract */
|
||||
readonly validatorNodeId?: string;
|
||||
};
|
||||
/** A transaction to allow validator to rotate their vega keys */
|
||||
/** A transaction to allow validator to rotate their Vega keys */
|
||||
readonly v1KeyRotateSubmission: {
|
||||
/** Hash of currently used public key */
|
||||
readonly currentPubKeyHash?: string;
|
||||
@@ -414,7 +434,7 @@ export interface components {
|
||||
readonly sig?: string;
|
||||
};
|
||||
/**
|
||||
* The kind of the signature created by a node, for example, allow-listing a new asset, withdrawal etc
|
||||
* The kind of signature created by a node, for example, allow-listing a new asset, withdrawal etc
|
||||
* @description - NODE_SIGNATURE_KIND_UNSPECIFIED: Represents an unspecified or missing value from the input
|
||||
* - NODE_SIGNATURE_KIND_ASSET_NEW: Represents a signature for a new asset allow-listing
|
||||
* - NODE_SIGNATURE_KIND_ASSET_WITHDRAWAL: Represents a signature for an asset withdrawal
|
||||
@@ -432,7 +452,7 @@ export interface components {
|
||||
| 'NODE_SIGNATURE_KIND_ERC20_MULTISIG_SIGNER_REMOVED'
|
||||
| 'NODE_SIGNATURE_KIND_ASSET_UPDATE';
|
||||
/**
|
||||
* Used when a node votes for validating a given resource exists or is valid,
|
||||
* Used when a node votes for validating that a given resource exists or is valid,
|
||||
* for example, an ERC20 deposit is valid and exists on ethereum
|
||||
*/
|
||||
readonly v1NodeVote: {
|
||||
@@ -553,6 +573,12 @@ export interface components {
|
||||
readonly v1PropertyKey: {
|
||||
/** @description name is the name of the property. */
|
||||
readonly name?: string;
|
||||
/**
|
||||
* An optional decimal place to be be applied on the provided value
|
||||
* valid only for PropertyType of type DECIMAL and INTEGER
|
||||
* Format: uint64
|
||||
*/
|
||||
readonly numberDecimalPlaces?: string;
|
||||
/** @description type is the type of the property. */
|
||||
readonly type?: components['schemas']['v1PropertyKeyType'];
|
||||
};
|
||||
@@ -596,7 +622,7 @@ export interface components {
|
||||
* Format: uint64
|
||||
*/
|
||||
readonly upgradeBlockHeight?: string;
|
||||
/** the release tag for the vega binary */
|
||||
/** the release tag for the Vega binary */
|
||||
readonly vegaReleaseTag?: string;
|
||||
};
|
||||
/**
|
||||
@@ -659,8 +685,8 @@ export interface components {
|
||||
readonly nodeId?: string;
|
||||
};
|
||||
/**
|
||||
* A message from a validator signaling they are still online and validating blocks
|
||||
* or ready to validate block when they are till a potential validator
|
||||
* A message from a validator signalling they are still online and validating blocks
|
||||
* or ready to validate blocks when they are still a pending validator
|
||||
*/
|
||||
readonly v1ValidatorHeartbeat: {
|
||||
/** Signature from the validator made using the ethereum wallet */
|
||||
@@ -1061,11 +1087,6 @@ export interface components {
|
||||
readonly quoteName?: string;
|
||||
/** Asset ID for the product's settlement asset */
|
||||
readonly settlementAsset?: string;
|
||||
/**
|
||||
* The number of decimal places implied by the settlement data (such as price) emitted by the settlement data source
|
||||
* Format: int64
|
||||
*/
|
||||
readonly settlementDataDecimals?: number;
|
||||
};
|
||||
/** Instrument configuration */
|
||||
readonly vegaInstrumentConfiguration: {
|
||||
@@ -1111,17 +1132,17 @@ export interface components {
|
||||
/** Risk model parameters for log normal */
|
||||
readonly vegaLogNormalModelParams: {
|
||||
/**
|
||||
* Mu param
|
||||
* Mu parameter, annualised growth rate of the underlying asset
|
||||
* Format: double
|
||||
*/
|
||||
readonly mu?: number;
|
||||
/**
|
||||
* R param
|
||||
* R parameter, annualised growth rate of the risk-free asset, used for discounting of future cash flows, can be any real number
|
||||
* Format: double
|
||||
*/
|
||||
readonly r?: number;
|
||||
/**
|
||||
* Sigma param
|
||||
* Sigma parameter, annualised volatility of the underlying asset, must be a strictly non-negative real number
|
||||
* Format: double
|
||||
*/
|
||||
readonly sigma?: number;
|
||||
@@ -1136,7 +1157,7 @@ export interface components {
|
||||
*/
|
||||
readonly riskAversionParameter?: number;
|
||||
/**
|
||||
* Tau
|
||||
* Tau parameter of the risk model, projection horizon measured as a year fraction used in the expected shortfall calculation to obtain the maintenance margin, must be a strictly non-negative real number
|
||||
* Format: double
|
||||
*/
|
||||
readonly tau?: number;
|
||||
@@ -1180,6 +1201,11 @@ export interface components {
|
||||
readonly liquidityMonitoringParameters?: components['schemas']['vegaLiquidityMonitoringParameters'];
|
||||
/** Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected */
|
||||
readonly logNormal?: components['schemas']['vegaLogNormalRiskModel'];
|
||||
/**
|
||||
* Percentage move up and down from the mid price which specifies the range of
|
||||
* price levels over which automated liquidity provision orders will be deployed
|
||||
*/
|
||||
readonly lpPriceRange?: string;
|
||||
/** Optional new market meta data, tags */
|
||||
readonly metadata?: readonly string[];
|
||||
/**
|
||||
@@ -1239,7 +1265,7 @@ export interface components {
|
||||
readonly vegaPriceMonitoringTrigger: {
|
||||
/**
|
||||
* Price monitoring auction extension duration in seconds should the price
|
||||
* breach it's theoretical level over the specified horizon at the specified
|
||||
* breach its theoretical level over the specified horizon at the specified
|
||||
* probability level
|
||||
* Format: int64
|
||||
*/
|
||||
@@ -1436,11 +1462,6 @@ export interface components {
|
||||
readonly dataSourceSpecForTradingTermination?: components['schemas']['vegaDataSourceDefinition'];
|
||||
/** Human-readable name/abbreviation of the quote name */
|
||||
readonly quoteName?: string;
|
||||
/**
|
||||
* The number of decimal places implied by the settlement data (such as price) emitted by the settlement external data source
|
||||
* Format: int64
|
||||
*/
|
||||
readonly settlementDataDecimals?: number;
|
||||
};
|
||||
/** Instrument configuration */
|
||||
readonly vegaUpdateInstrumentConfiguration: {
|
||||
@@ -1464,6 +1485,11 @@ export interface components {
|
||||
readonly liquidityMonitoringParameters?: components['schemas']['vegaLiquidityMonitoringParameters'];
|
||||
/** Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected */
|
||||
readonly logNormal?: components['schemas']['vegaLogNormalRiskModel'];
|
||||
/**
|
||||
* Percentage move up and down from the mid price which specifies the range of
|
||||
* price levels over which automated liquidity provision orders will be deployed
|
||||
*/
|
||||
readonly lpPriceRange?: string;
|
||||
/** Optional market metadata, tags */
|
||||
readonly metadata?: readonly string[];
|
||||
/** Price monitoring parameters */
|
||||
@@ -1504,6 +1530,27 @@ export interface components {
|
||||
export type external = Record<string, never>;
|
||||
|
||||
export interface operations {
|
||||
BlockExplorer_Info: {
|
||||
/**
|
||||
* Info
|
||||
* @description Retrieves information about the block explorer.
|
||||
* Response contains a semver formatted version of the data node and the commit hash, from which the block explorer was built,
|
||||
*/
|
||||
responses: {
|
||||
/** @description A successful response. */
|
||||
200: {
|
||||
content: {
|
||||
readonly 'application/json': components['schemas']['v1InfoResponse'];
|
||||
};
|
||||
};
|
||||
/** @description An unexpected error response. */
|
||||
default: {
|
||||
content: {
|
||||
readonly 'application/json': components['schemas']['googlerpcStatus'];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
BlockExplorer_ListTransactions: {
|
||||
/**
|
||||
* List transactions
|
||||
|
||||
@@ -1,4 +1,70 @@
|
||||
[
|
||||
{
|
||||
"tranche_id": 47,
|
||||
"tranche_start": "2023-12-01T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-01T00:00:00.000Z",
|
||||
"total_added": "3000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "3000",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
"user": "0xD18ffAa4a1d16f9eD9d3BE4078738Eeda3f160FD",
|
||||
"tx": "0xd4db7b194e49ecf5c65e6a64f34d43b8caf51a49be0a6c2744fa4b45667969bb"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"users": [
|
||||
{
|
||||
"address": "0xD18ffAa4a1d16f9eD9d3BE4078738Eeda3f160FD",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
"user": "0xD18ffAa4a1d16f9eD9d3BE4078738Eeda3f160FD",
|
||||
"tranche_id": 47,
|
||||
"tx": "0xd4db7b194e49ecf5c65e6a64f34d43b8caf51a49be0a6c2744fa4b45667969bb"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "3000",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "3000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tranche_id": 48,
|
||||
"tranche_start": "2022-12-01T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-01T00:00:00.000Z",
|
||||
"total_added": "2500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "2043.19101037851025",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
"user": "0xc704dA0E96a6b910fFA8d3F9f667d3D35Db8e5a1",
|
||||
"tx": "0xd4db7b194e49ecf5c65e6a64f34d43b8caf51a49be0a6c2744fa4b45667969bb"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"users": [
|
||||
{
|
||||
"address": "0xc704dA0E96a6b910fFA8d3F9f667d3D35Db8e5a1",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
"user": "0xc704dA0E96a6b910fFA8d3F9f667d3D35Db8e5a1",
|
||||
"tranche_id": 48,
|
||||
"tx": "0xd4db7b194e49ecf5c65e6a64f34d43b8caf51a49be0a6c2744fa4b45667969bb"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "2500",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "2500"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tranche_id": 45,
|
||||
"tranche_start": "2023-05-01T00:00:00.000Z",
|
||||
@@ -351,7 +417,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "81189.00181109020553229",
|
||||
"locked_amount": "79647.034786230230584755",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -417,7 +483,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "52600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "35918.4961123794978",
|
||||
"locked_amount": "34981.7821156773254",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2600",
|
||||
@@ -590,7 +656,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "3606.086536022324",
|
||||
"locked_amount": "3517.045281582953",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -801,7 +867,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "97499.58",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "22861.0493019706346484468",
|
||||
"locked_amount": "21348.523291308670112277",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "97499.58",
|
||||
@@ -834,7 +900,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "135173.4239508",
|
||||
"total_removed": "98230.390980249184455396",
|
||||
"locked_amount": "31247.107600282979940660298716",
|
||||
"locked_amount": "29179.74567043023283483559034",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "135173.4239508",
|
||||
@@ -880,7 +946,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "32499.86",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "9617.248652134231053772",
|
||||
"locked_amount": "8980.9550793758355841078",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "32499.86",
|
||||
@@ -913,7 +979,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "10833.29",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "3130.321112697780704066",
|
||||
"locked_amount": "2923.2137292116017801724",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10833.29",
|
||||
@@ -946,7 +1012,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "22749.93",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "11701.839463857984444507",
|
||||
"locked_amount": "10927.6258077879577238421",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "6500",
|
||||
@@ -1084,8 +1150,8 @@
|
||||
"tranche_start": "2022-11-01T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-01T00:00:00.000Z",
|
||||
"total_added": "22500",
|
||||
"total_removed": "2310.007577475",
|
||||
"locked_amount": "15444.7355547882135",
|
||||
"total_removed": "2596.339299375",
|
||||
"locked_amount": "14636.723066298342",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -1099,6 +1165,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "286.3317219",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x10e5b28647f6b294aa78f22603fd0f14475ec055e6b718f656d1739cf80b9cd6"
|
||||
},
|
||||
{
|
||||
"amount": "321.357044175",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -1137,6 +1208,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "286.3317219",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 33,
|
||||
"tx": "0x10e5b28647f6b294aa78f22603fd0f14475ec055e6b718f656d1739cf80b9cd6"
|
||||
},
|
||||
{
|
||||
"amount": "321.357044175",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -1169,8 +1246,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "7500",
|
||||
"withdrawn_tokens": "2310.007577475",
|
||||
"remaining_tokens": "5189.992422525"
|
||||
"withdrawn_tokens": "2596.339299375",
|
||||
"remaining_tokens": "4903.660700625"
|
||||
},
|
||||
{
|
||||
"address": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1",
|
||||
@@ -1195,7 +1272,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "928642.9598472029154",
|
||||
"locked_amount": "830418.589078051136755202",
|
||||
"locked_amount": "795871.857782503778305406",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -1546,8 +1623,8 @@
|
||||
"tranche_start": "2022-08-01T00:00:00.000Z",
|
||||
"tranche_end": "2023-02-01T00:00:00.000Z",
|
||||
"total_added": "42500",
|
||||
"total_removed": "22452.0135114",
|
||||
"locked_amount": "8140.6710761372795",
|
||||
"total_removed": "24434.0787288",
|
||||
"locked_amount": "6639.30970712560515",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "12500",
|
||||
@@ -1561,6 +1638,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1982.0652174",
|
||||
"user": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
|
||||
"tx": "0x46af57ef687e51b40874f6bbe7c462d756e58ec8194c7b2959b64c270242c0c2"
|
||||
},
|
||||
{
|
||||
"amount": "3425.611413",
|
||||
"user": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
|
||||
@@ -1604,6 +1686,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1982.0652174",
|
||||
"user": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
|
||||
"tranche_id": 17,
|
||||
"tx": "0x46af57ef687e51b40874f6bbe7c462d756e58ec8194c7b2959b64c270242c0c2"
|
||||
},
|
||||
{
|
||||
"amount": "3425.611413",
|
||||
"user": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
|
||||
@@ -1624,8 +1712,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "30000",
|
||||
"withdrawn_tokens": "22452.0135114",
|
||||
"remaining_tokens": "7547.9864886"
|
||||
"withdrawn_tokens": "24434.0787288",
|
||||
"remaining_tokens": "5565.9212712"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -31989,8 +32077,8 @@
|
||||
"tranche_start": "2022-03-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "428705.3729302523069",
|
||||
"locked_amount": "1300565.575097378439837757406",
|
||||
"total_removed": "433100.0722424088769",
|
||||
"locked_amount": "1247479.27699046564127813325",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -32159,6 +32247,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1906.7742941475005",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tx": "0x56e8c87befc060e0db542dc01543eed90530e83917cc782d946f882388bff61f"
|
||||
},
|
||||
{
|
||||
"amount": "1282.7401064380345",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -32169,6 +32262,11 @@
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tx": "0x96a49630063ce14e1e24e9878715d3c31d189d6dd107e01ebfceba8aa62971ba"
|
||||
},
|
||||
{
|
||||
"amount": "2487.9250180090695",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tx": "0x0c3a288c3e20316720b836d75c64f406519618b51e36592eee09ef9bb2cd6033"
|
||||
},
|
||||
{
|
||||
"amount": "835.5431693861975",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -32478,6 +32576,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1906.7742941475005",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tranche_id": 1,
|
||||
"tx": "0x56e8c87befc060e0db542dc01543eed90530e83917cc782d946f882388bff61f"
|
||||
},
|
||||
{
|
||||
"amount": "1282.7401064380345",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -32490,6 +32594,12 @@
|
||||
"tranche_id": 1,
|
||||
"tx": "0x96a49630063ce14e1e24e9878715d3c31d189d6dd107e01ebfceba8aa62971ba"
|
||||
},
|
||||
{
|
||||
"amount": "2487.9250180090695",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tranche_id": 1,
|
||||
"tx": "0x0c3a288c3e20316720b836d75c64f406519618b51e36592eee09ef9bb2cd6033"
|
||||
},
|
||||
{
|
||||
"amount": "835.5431693861975",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -32708,8 +32818,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "187637.95",
|
||||
"withdrawn_tokens": "120247.6705774890865",
|
||||
"remaining_tokens": "67390.2794225109135"
|
||||
"withdrawn_tokens": "124642.3698896456565",
|
||||
"remaining_tokens": "62995.5801103543435"
|
||||
},
|
||||
{
|
||||
"address": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
|
||||
@@ -33215,8 +33325,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "511218.93522350218767952",
|
||||
"locked_amount": "9911409.6106449879859047601650237654190322",
|
||||
"total_removed": "519717.09856019865947452",
|
||||
"locked_amount": "9723169.0060239913054124494026183204298459",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -33720,6 +33830,36 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "434.254023685890375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xcd3061658585189b7db32710ccbd22291d875124025834e2ed9fd1fd2dc0a813"
|
||||
},
|
||||
{
|
||||
"amount": "533.097878746431625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xdcddb180c5a97188736586ed09475d4354cdf6e8b0b041f26693b3371384da97"
|
||||
},
|
||||
{
|
||||
"amount": "1573.9558",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tx": "0x9d2918dd3feec63a8e6f8b777f5e570cd449d0e1c64921f0cd760fb05031c781"
|
||||
},
|
||||
{
|
||||
"amount": "1253.72073256229405",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tx": "0x8600dfffc88429840fddb3360b8b357708c7f6bcabd2bd8c804ee21ace11c416"
|
||||
},
|
||||
{
|
||||
"amount": "104.762232778042",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tx": "0x0cd78918910f5f36fed14545073e91c6f1c6082c5b1c226068f258d7552a04df"
|
||||
},
|
||||
{
|
||||
"amount": "469.508333637476375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xa040dfd6234c14a5bc91119f062756fbfde5945c03025ce785a9a089229e1949"
|
||||
},
|
||||
{
|
||||
"amount": "1269.616788",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
@@ -33790,6 +33930,36 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x1e3efba0c9a6b7f9653f0fb5f9b24ae9c13ec801d00cf7f9333689f7432914c0"
|
||||
},
|
||||
{
|
||||
"amount": "488.552248551145625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x2e647a56ae1d573955783dfae447261e5dbabf2f61557f2cf9a4f19cdfa9e0ed"
|
||||
},
|
||||
{
|
||||
"amount": "1052.55764205514812",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tx": "0xc48a7a49f743af0eb01f86880d6588e6feaca2f4799b8152785beda0cc344ce3"
|
||||
},
|
||||
{
|
||||
"amount": "1097.830494",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tx": "0x5d349afe6cec5ee1fb67bac724a75edf970d1004a8bd2ea8a6972a5a01319d09"
|
||||
},
|
||||
{
|
||||
"amount": "136.685622803434",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tx": "0xdbd515fed722081d9e1b03b6930f017f1df6de1cdc738a89a45716448dd708ad"
|
||||
},
|
||||
{
|
||||
"amount": "0",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x77f7f390d59f8c85b75ad1db9dabd6dacdaf04b937f8a9e03520fdc3346857e2"
|
||||
},
|
||||
{
|
||||
"amount": "1353.238327876609625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x40012432e4e417e6fb47f2c698fdb157e248ce34242bfa3a48e3755d0015a21d"
|
||||
},
|
||||
{
|
||||
"amount": "930.302108",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
@@ -35048,6 +35218,24 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "434.254023685890375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xcd3061658585189b7db32710ccbd22291d875124025834e2ed9fd1fd2dc0a813"
|
||||
},
|
||||
{
|
||||
"amount": "533.097878746431625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xdcddb180c5a97188736586ed09475d4354cdf6e8b0b041f26693b3371384da97"
|
||||
},
|
||||
{
|
||||
"amount": "469.508333637476375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xa040dfd6234c14a5bc91119f062756fbfde5945c03025ce785a9a089229e1949"
|
||||
},
|
||||
{
|
||||
"amount": "946.199315941372625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -35090,6 +35278,18 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0x1e3efba0c9a6b7f9653f0fb5f9b24ae9c13ec801d00cf7f9333689f7432914c0"
|
||||
},
|
||||
{
|
||||
"amount": "488.552248551145625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x2e647a56ae1d573955783dfae447261e5dbabf2f61557f2cf9a4f19cdfa9e0ed"
|
||||
},
|
||||
{
|
||||
"amount": "1353.238327876609625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x40012432e4e417e6fb47f2c698fdb157e248ce34242bfa3a48e3755d0015a21d"
|
||||
},
|
||||
{
|
||||
"amount": "2074.139541638025125",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -35980,8 +36180,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "259998.8875",
|
||||
"withdrawn_tokens": "97142.685093016968625",
|
||||
"remaining_tokens": "162856.202406983031375"
|
||||
"withdrawn_tokens": "100421.33590551452225",
|
||||
"remaining_tokens": "159577.55159448547775"
|
||||
},
|
||||
{
|
||||
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
||||
@@ -36202,6 +36402,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1253.72073256229405",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x8600dfffc88429840fddb3360b8b357708c7f6bcabd2bd8c804ee21ace11c416"
|
||||
},
|
||||
{
|
||||
"amount": "1168.32562674918194",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
@@ -36214,6 +36420,12 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0x06a5b5862308d83bda5de42c3ce7f692d528d61da7d77e7698488ece926e8e53"
|
||||
},
|
||||
{
|
||||
"amount": "1052.55764205514812",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xc48a7a49f743af0eb01f86880d6588e6feaca2f4799b8152785beda0cc344ce3"
|
||||
},
|
||||
{
|
||||
"amount": "1055.19046635722995",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
@@ -36354,8 +36566,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "150551.801",
|
||||
"withdrawn_tokens": "55659.48147836883658",
|
||||
"remaining_tokens": "94892.31952163116342"
|
||||
"withdrawn_tokens": "57965.75985298627875",
|
||||
"remaining_tokens": "92586.04114701372125"
|
||||
},
|
||||
{
|
||||
"address": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148",
|
||||
@@ -36557,6 +36769,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1573.9558",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x9d2918dd3feec63a8e6f8b777f5e570cd449d0e1c64921f0cd760fb05031c781"
|
||||
},
|
||||
{
|
||||
"amount": "1269.616788",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
@@ -36575,6 +36793,12 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0xaa6324943437bf4c7cfd5e768371d0f23b2e9e4a93e3f0be5a790607524b3a77"
|
||||
},
|
||||
{
|
||||
"amount": "1097.830494",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x5d349afe6cec5ee1fb67bac724a75edf970d1004a8bd2ea8a6972a5a01319d09"
|
||||
},
|
||||
{
|
||||
"amount": "930.302108",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
@@ -36679,8 +36903,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200000",
|
||||
"withdrawn_tokens": "74243.91305",
|
||||
"remaining_tokens": "125756.08695"
|
||||
"withdrawn_tokens": "76915.699344",
|
||||
"remaining_tokens": "123084.300656"
|
||||
},
|
||||
{
|
||||
"address": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01",
|
||||
@@ -37140,6 +37364,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "104.762232778042",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x0cd78918910f5f36fed14545073e91c6f1c6082c5b1c226068f258d7552a04df"
|
||||
},
|
||||
{
|
||||
"amount": "70.476468101423",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -37152,6 +37382,12 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0xd71183e476407ae537b585fa4e77b683a565390d7e4625025ff03314b417553a"
|
||||
},
|
||||
{
|
||||
"amount": "136.685622803434",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xdbd515fed722081d9e1b03b6930f017f1df6de1cdc738a89a45716448dd708ad"
|
||||
},
|
||||
{
|
||||
"amount": "45.922183357104",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -37352,8 +37588,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "12362.05",
|
||||
"withdrawn_tokens": "4531.2976364530895",
|
||||
"remaining_tokens": "7830.7523635469105"
|
||||
"withdrawn_tokens": "4772.7454920345655",
|
||||
"remaining_tokens": "7589.3045079654345"
|
||||
},
|
||||
{
|
||||
"address": "0xb091D456d0dFCB94dcba6f355379056C5bb995fC",
|
||||
@@ -37984,8 +38220,8 @@
|
||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "3489401.90950082536320653",
|
||||
"locked_amount": "3428704.84130926731572974432005816",
|
||||
"total_removed": "3525064.14530621309980811",
|
||||
"locked_amount": "3254922.317050771115686132956842142",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@@ -38194,6 +38430,36 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "12758.73908063512839093",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
"tx": "0x41db06e3a05adf4be2d61eab5929825225a23051f0aaa5aca1ddd5760e188fa4"
|
||||
},
|
||||
{
|
||||
"amount": "3671.528996246291985",
|
||||
"user": "0xcc2cf726A84e71301f9079FC177BA946aa98A694",
|
||||
"tx": "0xbdb207cce4094c7372c7a99f7e851c5d781883d24898fa285ae19eda27b50840"
|
||||
},
|
||||
{
|
||||
"amount": "14686.9255071873432384",
|
||||
"user": "0x47FbE34Fd93416c63d35544dEE6c6f442Db8513d",
|
||||
"tx": "0xeda94e6e1582e8045c91d54b11d240bb9e1f49467bd16ae4e89727b5de9b9a82"
|
||||
},
|
||||
{
|
||||
"amount": "762.7902369187144135",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x1fd0d4536451cf9f0b80832a66c6d8f4ca2a05f1c96f84f4679c94fd319fb4cb"
|
||||
},
|
||||
{
|
||||
"amount": "738.21651322227936725",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x5edbba4195383ca3e47fe551b0579ddba8ce13cc93d455f8d678f6c315a5b297"
|
||||
},
|
||||
{
|
||||
"amount": "651.52334632511886825",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x8cd254b49b91faf7c6ddb6ed35a8a86ffb35afd2d3e6ea663f66d6864a116072"
|
||||
},
|
||||
{
|
||||
"amount": "1289.16117292541627425",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -38239,6 +38505,16 @@
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x617ff95943d9685aaf9763e3fb4ca1f81e8dd04fd013d1a64b59e52b78b25b81"
|
||||
},
|
||||
{
|
||||
"amount": "678.47222286845557075",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x40dc4dbfbf26c199c7cf1be4b281d553d470a830423ff678795585588d1c5cd0"
|
||||
},
|
||||
{
|
||||
"amount": "1714.0399019844047675",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x4139309b9927ce8486e61491dd9ba7a31f36cc112dd6446c3d33ad897f14264c"
|
||||
},
|
||||
{
|
||||
"amount": "9158.56255453299474378",
|
||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
@@ -40805,6 +41081,24 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "762.7902369187144135",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x1fd0d4536451cf9f0b80832a66c6d8f4ca2a05f1c96f84f4679c94fd319fb4cb"
|
||||
},
|
||||
{
|
||||
"amount": "738.21651322227936725",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x5edbba4195383ca3e47fe551b0579ddba8ce13cc93d455f8d678f6c315a5b297"
|
||||
},
|
||||
{
|
||||
"amount": "651.52334632511886825",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x8cd254b49b91faf7c6ddb6ed35a8a86ffb35afd2d3e6ea663f66d6864a116072"
|
||||
},
|
||||
{
|
||||
"amount": "1289.16117292541627425",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -40853,6 +41147,18 @@
|
||||
"tranche_id": 3,
|
||||
"tx": "0x617ff95943d9685aaf9763e3fb4ca1f81e8dd04fd013d1a64b59e52b78b25b81"
|
||||
},
|
||||
{
|
||||
"amount": "678.47222286845557075",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x40dc4dbfbf26c199c7cf1be4b281d553d470a830423ff678795585588d1c5cd0"
|
||||
},
|
||||
{
|
||||
"amount": "1714.0399019844047675",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x4139309b9927ce8486e61491dd9ba7a31f36cc112dd6446c3d33ad897f14264c"
|
||||
},
|
||||
{
|
||||
"amount": "2874.6686339993457875",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -43033,8 +43339,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "359123.469575",
|
||||
"withdrawn_tokens": "274108.98298493707152025",
|
||||
"remaining_tokens": "85014.48659006292847975"
|
||||
"withdrawn_tokens": "278654.0252062560445075",
|
||||
"remaining_tokens": "80469.4443687439554925"
|
||||
},
|
||||
{
|
||||
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
||||
@@ -43193,6 +43499,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "3671.528996246291985",
|
||||
"user": "0xcc2cf726A84e71301f9079FC177BA946aa98A694",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xbdb207cce4094c7372c7a99f7e851c5d781883d24898fa285ae19eda27b50840"
|
||||
},
|
||||
{
|
||||
"amount": "7412.8453939926209526",
|
||||
"user": "0xcc2cf726A84e71301f9079FC177BA946aa98A694",
|
||||
@@ -43237,8 +43549,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "66299.71746",
|
||||
"withdrawn_tokens": "47451.9402242768950194",
|
||||
"remaining_tokens": "18847.7772357231049806"
|
||||
"withdrawn_tokens": "51123.4692205231870044",
|
||||
"remaining_tokens": "15176.2482394768129956"
|
||||
},
|
||||
{
|
||||
"address": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
@@ -43639,6 +43951,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "14686.9255071873432384",
|
||||
"user": "0x47FbE34Fd93416c63d35544dEE6c6f442Db8513d",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xeda94e6e1582e8045c91d54b11d240bb9e1f49467bd16ae4e89727b5de9b9a82"
|
||||
},
|
||||
{
|
||||
"amount": "29651.7863357455771104",
|
||||
"user": "0x47FbE34Fd93416c63d35544dEE6c6f442Db8513d",
|
||||
@@ -43683,8 +44001,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "265198.86984",
|
||||
"withdrawn_tokens": "189807.4910572575178776",
|
||||
"remaining_tokens": "75391.3787827424821224"
|
||||
"withdrawn_tokens": "204494.416564444861116",
|
||||
"remaining_tokens": "60704.453275555138884"
|
||||
},
|
||||
{
|
||||
"address": "0x35022e6c85B50F4904C7BC7e692A9F3bbEE8D2CE",
|
||||
@@ -43861,6 +44179,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "12758.73908063512839093",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x41db06e3a05adf4be2d61eab5929825225a23051f0aaa5aca1ddd5760e188fa4"
|
||||
},
|
||||
{
|
||||
"amount": "25760.51683291284616209",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
@@ -43899,8 +44223,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "230391.5181735",
|
||||
"withdrawn_tokens": "164894.67179756811481554",
|
||||
"remaining_tokens": "65496.84637593188518446"
|
||||
"withdrawn_tokens": "177653.41087820324320647",
|
||||
"remaining_tokens": "52738.10729529675679353"
|
||||
},
|
||||
{
|
||||
"address": "0xC6b2864fbCD2A8dEC8DEfD1D421bC1E450C370AD",
|
||||
@@ -44277,8 +44601,8 @@
|
||||
"tranche_start": "2021-10-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "2479228.813551817124120168",
|
||||
"locked_amount": "1037798.493633229255945123020263576",
|
||||
"total_removed": "2496865.348122913927782668",
|
||||
"locked_amount": "969136.089532856996988710902601838",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "552496.6455",
|
||||
@@ -44422,6 +44746,16 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "9162.0421945609117395",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
"tx": "0xb3ccc6e824ffee15c67e8a0779dac9758deec01360025608c616a78f2670ad15"
|
||||
},
|
||||
{
|
||||
"amount": "8474.492376535891923",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
"tx": "0xc4b5ead74193a1938f4e90bac21c84351fb1439cf63d2572f50d78cf34f8af05"
|
||||
},
|
||||
{
|
||||
"amount": "4206.439644984274503",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
@@ -45106,6 +45440,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "9162.0421945609117395",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
"tranche_id": 4,
|
||||
"tx": "0xb3ccc6e824ffee15c67e8a0779dac9758deec01360025608c616a78f2670ad15"
|
||||
},
|
||||
{
|
||||
"amount": "18498.907302984077175",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
@@ -45144,8 +45484,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "165749.29365",
|
||||
"withdrawn_tokens": "127806.068231543554428",
|
||||
"remaining_tokens": "37943.225418456445572"
|
||||
"withdrawn_tokens": "136968.1104261044661675",
|
||||
"remaining_tokens": "28781.1832238955338325"
|
||||
},
|
||||
{
|
||||
"address": "0x72e7BB93E73b2885a22CA29c34759361399a5C0e",
|
||||
@@ -45771,6 +46111,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "8474.492376535891923",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
"tranche_id": 4,
|
||||
"tx": "0xc4b5ead74193a1938f4e90bac21c84351fb1439cf63d2572f50d78cf34f8af05"
|
||||
},
|
||||
{
|
||||
"amount": "4206.439644984274503",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
@@ -45977,8 +46323,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "331498.5873",
|
||||
"withdrawn_tokens": "267033.619629234885375",
|
||||
"remaining_tokens": "64464.967670765114625"
|
||||
"withdrawn_tokens": "275508.112005770777298",
|
||||
"remaining_tokens": "55990.475294229222702"
|
||||
},
|
||||
{
|
||||
"address": "0x16da609341ed67750A8BCC5AAa2005471006Cd77",
|
||||
@@ -46073,8 +46419,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "27238.3679206278963",
|
||||
"locked_amount": "206082.034745654336161635141856908",
|
||||
"total_removed": "27768.7412941819005",
|
||||
"locked_amount": "197670.222334695392780953013089824",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@@ -52693,6 +53039,16 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "229.648541348",
|
||||
"user": "0x65C13724928ea0AfA68e09c7b70449bB8f6f3Fc8",
|
||||
"tx": "0x9e93ae11a21aaa47b37494eb70d38c3b56117d894244398f33ba495006e785fd"
|
||||
},
|
||||
{
|
||||
"amount": "115.710343734",
|
||||
"user": "0x57d7881125E8057B0e8D90B7A2Cc8dACC72F8659",
|
||||
"tx": "0x9b16067ba1c2dfbb487fb60690c377cd8a500211c2d6d354daadab71d706b381"
|
||||
},
|
||||
{
|
||||
"amount": "20.707914768",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
@@ -52748,6 +53104,21 @@
|
||||
"user": "0xeE2C02Cd75dcEacD16614feB126a1cD2637646d0",
|
||||
"tx": "0x81181699f4cae02ba8761ccf126f88141644a318f8f5bfd67f3d4a4f870b59e9"
|
||||
},
|
||||
{
|
||||
"amount": "97.792503807",
|
||||
"user": "0xdc040917f80aC350460e55467e4B6c52Fc5e220E",
|
||||
"tx": "0x1f8e5bff5b6390c9de0c33a77494fda9ce1876e11e39400d9fe1d7ef4da9e679"
|
||||
},
|
||||
{
|
||||
"amount": "58.7576011050042",
|
||||
"user": "0x91Ff7FADb80385D2E25E12F92d211688a550A06C",
|
||||
"tx": "0x87ae337c9809d80018c3f2c3b90df597bea0b3ac865fb58f8471ff92ebcbadd8"
|
||||
},
|
||||
{
|
||||
"amount": "28.46438356",
|
||||
"user": "0x7C8D2D8BcFffcD48dBcb65C5Bb7588B66dcD22bb",
|
||||
"tx": "0x8148604cfba3cabb5229c19cd857c8c47255c1502bddc9871c01b05cf569c691"
|
||||
},
|
||||
{
|
||||
"amount": "199.140778792",
|
||||
"user": "0x2827B97046558f044ab07c3De0159632f8956472",
|
||||
@@ -66261,6 +66632,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "28.46438356",
|
||||
"user": "0x7C8D2D8BcFffcD48dBcb65C5Bb7588B66dcD22bb",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x8148604cfba3cabb5229c19cd857c8c47255c1502bddc9871c01b05cf569c691"
|
||||
},
|
||||
{
|
||||
"amount": "35.005327244",
|
||||
"user": "0x7C8D2D8BcFffcD48dBcb65C5Bb7588B66dcD22bb",
|
||||
@@ -66281,8 +66658,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "199.913685944",
|
||||
"remaining_tokens": "200.086314056"
|
||||
"withdrawn_tokens": "228.378069504",
|
||||
"remaining_tokens": "171.621930496"
|
||||
},
|
||||
{
|
||||
"address": "0xc56F9f1d5f124655FA9CB8f85C7701E13a2fBF4D",
|
||||
@@ -71574,10 +71951,17 @@
|
||||
"tx": "0xc8541da6a57f410b6faba47a5e5184bae700193b7bd042914fffc562114d92f5"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "58.7576011050042",
|
||||
"user": "0x91Ff7FADb80385D2E25E12F92d211688a550A06C",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x87ae337c9809d80018c3f2c3b90df597bea0b3ac865fb58f8471ff92ebcbadd8"
|
||||
}
|
||||
],
|
||||
"total_tokens": "103.38",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "103.38"
|
||||
"withdrawn_tokens": "58.7576011050042",
|
||||
"remaining_tokens": "44.6223988949958"
|
||||
},
|
||||
{
|
||||
"address": "0x942e32E60f465f5DCDc071840E9D9D6a3D619dE7",
|
||||
@@ -71707,10 +72091,17 @@
|
||||
"tx": "0xc8541da6a57f410b6faba47a5e5184bae700193b7bd042914fffc562114d92f5"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "229.648541348",
|
||||
"user": "0x65C13724928ea0AfA68e09c7b70449bB8f6f3Fc8",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x9e93ae11a21aaa47b37494eb70d38c3b56117d894244398f33ba495006e785fd"
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "400"
|
||||
"withdrawn_tokens": "229.648541348",
|
||||
"remaining_tokens": "170.351458652"
|
||||
},
|
||||
{
|
||||
"address": "0x4FF4255c498e844cE78F9F9aD46913A20A1642b4",
|
||||
@@ -72665,6 +73056,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "97.792503807",
|
||||
"user": "0xdc040917f80aC350460e55467e4B6c52Fc5e220E",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x1f8e5bff5b6390c9de0c33a77494fda9ce1876e11e39400d9fe1d7ef4da9e679"
|
||||
},
|
||||
{
|
||||
"amount": "29.694815448",
|
||||
"user": "0xdc040917f80aC350460e55467e4B6c52Fc5e220E",
|
||||
@@ -72679,8 +73076,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "300",
|
||||
"withdrawn_tokens": "72.631687593",
|
||||
"remaining_tokens": "227.368312407"
|
||||
"withdrawn_tokens": "170.4241914",
|
||||
"remaining_tokens": "129.5758086"
|
||||
},
|
||||
{
|
||||
"address": "0x8D01053B4f4857Ff453CAeDBf8387Cd57a5a2A2b",
|
||||
@@ -73657,10 +74054,17 @@
|
||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "115.710343734",
|
||||
"user": "0x57d7881125E8057B0e8D90B7A2Cc8dACC72F8659",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x9b16067ba1c2dfbb487fb60690c377cd8a500211c2d6d354daadab71d706b381"
|
||||
}
|
||||
],
|
||||
"total_tokens": "200",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "200"
|
||||
"withdrawn_tokens": "115.710343734",
|
||||
"remaining_tokens": "84.289656266"
|
||||
},
|
||||
{
|
||||
"address": "0x89F3Db3ce23E58A3C416D5930d7E806d80E4F1FF",
|
||||
@@ -74117,7 +74521,7 @@
|
||||
"tranche_start": "2021-12-05T00:00:00.000Z",
|
||||
"tranche_end": "2022-06-05T00:00:00.000Z",
|
||||
"total_added": "171288.42",
|
||||
"total_removed": "60641.2093106172989",
|
||||
"total_removed": "60849.0699829322989",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -78372,6 +78776,16 @@
|
||||
"user": "0x667B436A05523B8D80483b030f559f034753DD74",
|
||||
"tx": "0x48d6761a237f75fa95ff67082e4f0b5538586a58a7a677943f1c4260f3abb860"
|
||||
},
|
||||
{
|
||||
"amount": "150",
|
||||
"user": "0x300E9b1628eE5949365B7f6c08690C2B9ae2043A",
|
||||
"tx": "0x3873e5c2e039043676e6e705feedd49a367c85d9e69aef64d695472bce689908"
|
||||
},
|
||||
{
|
||||
"amount": "57.860672315",
|
||||
"user": "0x0Fa5387417ce5030a259b48f1bde2001a100D27B",
|
||||
"tx": "0x41b8c1181cf49b5d873bf94d03d3932b38705d6cbb5bc147026910ffcc480c0b"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x3E1CECDc3d15Cb03e91a60470C4453f4fBFc75F9",
|
||||
@@ -81085,6 +81499,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "57.860672315",
|
||||
"user": "0x0Fa5387417ce5030a259b48f1bde2001a100D27B",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x41b8c1181cf49b5d873bf94d03d3932b38705d6cbb5bc147026910ffcc480c0b"
|
||||
},
|
||||
{
|
||||
"amount": "192.139327685",
|
||||
"user": "0x0Fa5387417ce5030a259b48f1bde2001a100D27B",
|
||||
@@ -81093,8 +81513,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "192.139327685",
|
||||
"remaining_tokens": "57.860672315"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x643E4ea2718eFA5897F5eB655D767E4193695987",
|
||||
@@ -89926,10 +90346,17 @@
|
||||
"tx": "0x716a7be06da5a7a3d8038907974887a31805ea8eeab5d130cba528e4d2094d9f"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "150",
|
||||
"user": "0x300E9b1628eE5949365B7f6c08690C2B9ae2043A",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x3873e5c2e039043676e6e705feedd49a367c85d9e69aef64d695472bce689908"
|
||||
}
|
||||
],
|
||||
"total_tokens": "150",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "150"
|
||||
"withdrawn_tokens": "150",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x2074924ebfD97Ff2351659CB00e259eBd6451aA5",
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# Vega token website E2E tests
|
||||
|
||||
To run the UI automation tests with Vega Capsule, run:
|
||||
|
||||
```bash
|
||||
yarn nx run token-e2e:e2e
|
||||
```
|
||||
|
||||
To open Cypress and run in interactive mode, run:
|
||||
|
||||
```bash
|
||||
yarn nx run token-e2e:e2e --watch
|
||||
```
|
||||
|
||||
## Vega Capsule Setup
|
||||
|
||||
The e2e tests run against a locally running instance of the Vega network, managed and controlled by [Vega Capsule](https://github.com/vegaprotocol/vegacapsule). Vega Capsule will:
|
||||
|
||||
- Bootstrap and start up a Vega network
|
||||
- Start up [Ganache](https://trufflesuite.com/ganache/) for a local Ethereum network
|
||||
- Install the required Vega smart contracts
|
||||
- Set up DataNodes with a running GraphQL and REST APIs.
|
||||
|
||||
Refer to the [Vega Capsule readme](https://github.com/vegaprotocol/vegacapsule#readme) for setting up and running Capsule. You will need [Go 1.19 or later](https://go.dev/doc/install) and [Docker](https://docs.docker.com/get-docker/) installed.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- You may need to run `vegacapsule nodes unsafe-reset-all` to get a clean network state
|
||||
|
||||
## Vega Wallet Setup
|
||||
|
||||
Start by [downloading the Vega wallet software here](https://github.com/vegaprotocol/vega/releases).
|
||||
|
||||
You can then refer to (or run) `vegacapsule/setup-vegawallet.sh`. This will initialise and configure your wallet to have the correct public keys and network config to run against capsule.
|
||||
@@ -133,6 +133,7 @@ describe('Navbar', { tags: '@smoke' }, () => {
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/');
|
||||
cy.wait('@Market');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
});
|
||||
|
||||
|
||||
@@ -224,4 +224,34 @@ describe('home', { tags: '@regression' }, () => {
|
||||
.should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('redirect should take last visited market into consideration', () => {
|
||||
beforeEach(() => {
|
||||
cy.window().then((window) => {
|
||||
window.localStorage.removeItem('marketId');
|
||||
});
|
||||
});
|
||||
it('marketId comes from existing market', () => {
|
||||
cy.window().then((window) => {
|
||||
window.localStorage.setItem('marketId', 'market-1');
|
||||
cy.visit('/');
|
||||
cy.wait('@Market');
|
||||
cy.location('hash').should('equal', '#/markets/market-1');
|
||||
cy.get('[role="dialog"]').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('marketId comes from not-existing market', () => {
|
||||
cy.window().then((window) => {
|
||||
window.localStorage.setItem('marketId', 'market-not-existing');
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'Market', null);
|
||||
});
|
||||
cy.visit('/');
|
||||
cy.wait('@Market');
|
||||
cy.location('hash').should('equal', '#/markets/market-not-existing');
|
||||
cy.get('[role="dialog"]').should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,11 +30,20 @@ const displayTomorrow = () => {
|
||||
|
||||
describe('time in force default values', () => {
|
||||
before(() => {
|
||||
cy.window().then((win) => {
|
||||
win.localStorage.setItem(
|
||||
'vega_wallet_config',
|
||||
JSON.stringify({
|
||||
token: Cypress.env('VEGA_WALLET_API_TOKEN'),
|
||||
connector: 'jsonRpc',
|
||||
url: 'http://localhost:1789',
|
||||
})
|
||||
);
|
||||
});
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.connectVegaWallet();
|
||||
});
|
||||
|
||||
it('must have market order set up to IOC by default', function () {
|
||||
@@ -59,20 +68,15 @@ describe('time in force default values', () => {
|
||||
describe('must submit order', { tags: '@smoke' }, () => {
|
||||
// 7002-SORD-039
|
||||
before(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.connectVegaWallet();
|
||||
cy.window().then(function (window) {
|
||||
cy.wrap(window.localStorage.getItem('vega_wallet_config')).as('cfg');
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.window().then(function (window) {
|
||||
window.localStorage.setItem('vega_wallet_config', this.cfg);
|
||||
});
|
||||
setVegaConfig();
|
||||
});
|
||||
|
||||
it('successfully places market buy order', () => {
|
||||
@@ -158,6 +162,7 @@ describe(
|
||||
{ tags: '@regression' },
|
||||
() => {
|
||||
before(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage(
|
||||
Schema.MarketState.STATE_SUSPENDED,
|
||||
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
|
||||
@@ -166,16 +171,10 @@ describe(
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.connectVegaWallet();
|
||||
cy.window().then(function (window) {
|
||||
cy.wrap(window.localStorage.getItem('vega_wallet_config')).as('cfg');
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.window().then(function (window) {
|
||||
window.localStorage.setItem('vega_wallet_config', this.cfg);
|
||||
});
|
||||
setVegaConfig();
|
||||
});
|
||||
|
||||
it('successfully places limit buy order', () => {
|
||||
@@ -232,6 +231,7 @@ describe(
|
||||
{ tags: '@regression' },
|
||||
() => {
|
||||
before(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage(
|
||||
Schema.MarketState.STATE_SUSPENDED,
|
||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
||||
@@ -240,16 +240,10 @@ describe(
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.connectVegaWallet();
|
||||
cy.window().then(function (window) {
|
||||
cy.wrap(window.localStorage.getItem('vega_wallet_config')).as('cfg');
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.window().then(function (window) {
|
||||
window.localStorage.setItem('vega_wallet_config', this.cfg);
|
||||
});
|
||||
setVegaConfig();
|
||||
});
|
||||
|
||||
it('successfully places limit buy order', () => {
|
||||
@@ -306,6 +300,7 @@ describe(
|
||||
{ tags: '@regression' },
|
||||
() => {
|
||||
before(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage(
|
||||
Schema.MarketState.STATE_SUSPENDED,
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
@@ -314,16 +309,10 @@ describe(
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.connectVegaWallet();
|
||||
cy.window().then(function (window) {
|
||||
cy.wrap(window.localStorage.getItem('vega_wallet_config')).as('cfg');
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.window().then(function (window) {
|
||||
window.localStorage.setItem('vega_wallet_config', this.cfg);
|
||||
});
|
||||
setVegaConfig();
|
||||
});
|
||||
|
||||
it('successfully places limit buy order', () => {
|
||||
@@ -421,10 +410,10 @@ describe('deal ticket validation', { tags: '@smoke' }, () => {
|
||||
|
||||
describe('deal ticket size validation', { tags: '@smoke' }, function () {
|
||||
beforeEach(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.connectVegaWallet();
|
||||
});
|
||||
|
||||
it('must warn if order size input has too many digits after the decimal place', function () {
|
||||
@@ -455,14 +444,18 @@ describe('deal ticket size validation', { tags: '@smoke' }, function () {
|
||||
|
||||
describe('limit order validations', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.connectVegaWallet();
|
||||
cy.wait('@Market');
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setVegaConfig();
|
||||
});
|
||||
|
||||
it('must see the price unit', function () {
|
||||
//7002-SORD-018
|
||||
cy.getByTestId(orderPriceField)
|
||||
@@ -544,11 +537,17 @@ describe('limit order validations', { tags: '@smoke' }, () => {
|
||||
|
||||
describe('market order validations', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setVegaConfig();
|
||||
});
|
||||
|
||||
it('must not see the price unit', function () {
|
||||
//7002-SORD-019
|
||||
cy.getByTestId(orderPriceField).should('not.exist');
|
||||
@@ -587,6 +586,7 @@ describe('market order validations', { tags: '@smoke' }, () => {
|
||||
|
||||
describe('suspended market validation', { tags: '@regression' }, () => {
|
||||
before(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage(
|
||||
Schema.MarketState.STATE_SUSPENDED,
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
@@ -595,7 +595,10 @@ describe('suspended market validation', { tags: '@regression' }, () => {
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.connectVegaWallet();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setVegaConfig();
|
||||
});
|
||||
|
||||
it('should show warning for market order', function () {
|
||||
@@ -608,6 +611,7 @@ describe('suspended market validation', { tags: '@regression' }, () => {
|
||||
'This market is in auction until it reaches sufficient liquidity. Only limit orders are permitted when market is in auction'
|
||||
);
|
||||
});
|
||||
|
||||
it('should show info for allowed TIF', function () {
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
cy.getByTestId(orderPriceField).clear().type('0.1');
|
||||
@@ -635,6 +639,7 @@ describe('suspended market validation', { tags: '@regression' }, () => {
|
||||
describe('account validation', { tags: '@regression' }, () => {
|
||||
describe('zero balance error', () => {
|
||||
beforeEach(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage();
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(
|
||||
@@ -663,7 +668,6 @@ describe('account validation', { tags: '@regression' }, () => {
|
||||
});
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.connectVegaWallet();
|
||||
cy.wait('@Market');
|
||||
});
|
||||
|
||||
@@ -682,6 +686,7 @@ describe('account validation', { tags: '@regression' }, () => {
|
||||
|
||||
describe('not enough balance warning', () => {
|
||||
beforeEach(() => {
|
||||
setVegaConfig();
|
||||
cy.mockTradingPage();
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(
|
||||
@@ -699,9 +704,9 @@ describe('account validation', { tags: '@regression' }, () => {
|
||||
});
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.connectVegaWallet();
|
||||
cy.wait('@Market');
|
||||
});
|
||||
|
||||
it('should display info and button for deposit', () => {
|
||||
//7002-SORD-003
|
||||
// warning should show immediately
|
||||
@@ -740,3 +745,16 @@ const createOrder = (order: OrderSubmission): void => {
|
||||
}
|
||||
cy.getByTestId(placeOrderBtn).click();
|
||||
};
|
||||
|
||||
const setVegaConfig = () => {
|
||||
cy.window().then((win) => {
|
||||
win.localStorage.setItem(
|
||||
'vega_wallet_config',
|
||||
JSON.stringify({
|
||||
token: Cypress.env('VEGA_WALLET_API_TOKEN'),
|
||||
connector: 'jsonRpc',
|
||||
url: 'http://localhost:1789',
|
||||
})
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -423,4 +423,9 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
|
||||
testOrderCancellation(order);
|
||||
});
|
||||
});
|
||||
it.skip('tbd for 7003-MORD', () => {
|
||||
// NOT COVERED: must see the reference, offset and direction for each part pegged order - waiting for clarification
|
||||
// NOT COVERED: must see the reference, offset and direction for each part liquidity order order - waiting for clarification
|
||||
// NOT COVERED: must be warned (pre-submit) if the input price has too many digits after the decimal place for the market - issues/2486
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { ethers } from 'ethers';
|
||||
import type { Transaction } from '@vegaprotocol/wallet';
|
||||
|
||||
/**
|
||||
* Base64 encode a transaction object
|
||||
*/
|
||||
export const encodeTransaction = (tx: Transaction): string => {
|
||||
return ethers.utils.base64.encode(
|
||||
ethers.utils.toUtf8Bytes(JSON.stringify(tx))
|
||||
);
|
||||
};
|
||||
@@ -7,7 +7,6 @@ import type {
|
||||
OrderSubmissionBody,
|
||||
Transaction,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { encodeTransaction } from './encode-transaction';
|
||||
|
||||
export const testOrderSubmission = (
|
||||
order: OrderSubmission,
|
||||
@@ -18,9 +17,6 @@ export const testOrderSubmission = (
|
||||
...expected,
|
||||
};
|
||||
|
||||
expectedOrder.expiresAt = expectedOrder.expiresAt || undefined;
|
||||
expectedOrder.price = expectedOrder.price || undefined;
|
||||
|
||||
const transaction: OrderSubmissionBody = {
|
||||
orderSubmission: expectedOrder,
|
||||
};
|
||||
@@ -36,9 +32,6 @@ export const testOrderAmendment = (
|
||||
...expected,
|
||||
};
|
||||
|
||||
expectedOrder.expiresAt = expectedOrder.expiresAt || undefined;
|
||||
expectedOrder.price = expectedOrder.price || undefined;
|
||||
|
||||
const transaction: OrderAmendmentBody = {
|
||||
orderAmendment: expectedOrder,
|
||||
};
|
||||
@@ -70,7 +63,7 @@ const vegaWalletTransaction = (transaction: Transaction) => {
|
||||
?.token,
|
||||
publicKey: Cypress.env('VEGA_PUBLIC_KEY2'),
|
||||
sendingMode: 'TYPE_SYNC',
|
||||
encodedTransaction: encodeTransaction(transaction),
|
||||
transaction,
|
||||
});
|
||||
cy.getByTestId(dialogTitle).should(
|
||||
'have.text',
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { marketsWithDataProvider } from '@vegaprotocol/market-list';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
titlefy,
|
||||
useDataProvider,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useGlobalStore, usePageTitleStore } from '../../stores';
|
||||
import { marketsWithDataProvider } from '@vegaprotocol/market-list';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
|
||||
export const Home = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -17,40 +13,26 @@ export const Home = () => {
|
||||
const { data, error, loading } = useDataProvider({
|
||||
dataProvider: marketsWithDataProvider,
|
||||
});
|
||||
const { update } = useGlobalStore((store) => ({
|
||||
update: store.update,
|
||||
}));
|
||||
|
||||
const { pageTitle, updateTitle } = usePageTitleStore((store) => ({
|
||||
pageTitle: store.pageTitle,
|
||||
updateTitle: store.updateTitle,
|
||||
}));
|
||||
const update = useGlobalStore((store) => store.update);
|
||||
const marketId = useGlobalStore((store) => store.marketId);
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
const marketId = data[0]?.id;
|
||||
const marketName = data[0]?.tradableInstrument.instrument.name;
|
||||
const marketPrice = data[0]?.data?.markPrice
|
||||
? addDecimalsFormatNumber(
|
||||
data[0]?.data?.markPrice,
|
||||
data[0]?.decimalPlaces
|
||||
)
|
||||
: null;
|
||||
const newPageTitle = titlefy([marketName, marketPrice]);
|
||||
|
||||
if (marketId) {
|
||||
navigate(Links[Routes.MARKET](marketId), {
|
||||
if (marketId) {
|
||||
navigate(Links[Routes.MARKET](marketId), {
|
||||
replace: true,
|
||||
});
|
||||
} else if (data) {
|
||||
const marketDataId = data[0]?.id;
|
||||
if (marketDataId) {
|
||||
navigate(Links[Routes.MARKET](marketDataId), {
|
||||
replace: true,
|
||||
});
|
||||
update({ marketId });
|
||||
if (pageTitle !== newPageTitle) {
|
||||
updateTitle(newPageTitle);
|
||||
}
|
||||
} else {
|
||||
navigate(Links[Routes.MARKET]());
|
||||
}
|
||||
update({ shouldDisplayWelcomeDialog: true });
|
||||
}
|
||||
}, [data, navigate, update, pageTitle, updateTitle]);
|
||||
}, [marketId, data, navigate, update]);
|
||||
|
||||
return (
|
||||
<AsyncRenderer data={data} loading={loading} error={error}>
|
||||
|
||||
@@ -32,29 +32,23 @@ export interface SingleMarketData extends SingleMarketFieldsFragment {
|
||||
}
|
||||
|
||||
export const Market = () => {
|
||||
const params = useParams();
|
||||
const { marketId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const marketId = params.marketId;
|
||||
|
||||
const { w } = useWindowSize();
|
||||
const { update } = useGlobalStore((store) => ({
|
||||
update: store.update,
|
||||
}));
|
||||
const update = useGlobalStore((store) => store.update);
|
||||
const lastMarketId = useGlobalStore((store) => store.marketId);
|
||||
|
||||
const { pageTitle, updateTitle } = usePageTitleStore((store) => ({
|
||||
pageTitle: store.pageTitle,
|
||||
updateTitle: store.updateTitle,
|
||||
}));
|
||||
const pageTitle = usePageTitleStore((store) => store.pageTitle);
|
||||
const updateTitle = usePageTitleStore((store) => store.updateTitle);
|
||||
|
||||
const onSelect = useCallback(
|
||||
(id: string) => {
|
||||
if (id && id !== marketId) {
|
||||
update({ marketId: id });
|
||||
navigate(Links[Routes.MARKET](id));
|
||||
}
|
||||
},
|
||||
[marketId, update, navigate]
|
||||
[marketId, navigate]
|
||||
);
|
||||
|
||||
const variables = useMemo(
|
||||
@@ -64,12 +58,22 @@ export const Market = () => {
|
||||
[marketId]
|
||||
);
|
||||
|
||||
const updateMarketId = useCallback(
|
||||
({ data }: { data: { id?: string } | null }) => {
|
||||
if (data?.id && data.id !== lastMarketId) {
|
||||
update({ marketId: data.id });
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[update, lastMarketId]
|
||||
);
|
||||
const { data, error, loading } = useDataProvider<
|
||||
SingleMarketFieldsFragment,
|
||||
never
|
||||
>({
|
||||
dataProvider: marketProvider,
|
||||
variables,
|
||||
update: updateMarketId,
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
@@ -104,11 +108,10 @@ export const Market = () => {
|
||||
}
|
||||
return <TradePanels market={data} onSelect={onSelect} />;
|
||||
}, [w, data, onSelect]);
|
||||
|
||||
if (!data && marketId) {
|
||||
return (
|
||||
<Splash>
|
||||
<p>{t('Not found')}</p>
|
||||
<p>{t('Market not found')}</p>
|
||||
</Splash>
|
||||
);
|
||||
}
|
||||
@@ -119,13 +122,9 @@ export const Market = () => {
|
||||
error={error}
|
||||
data={data || undefined}
|
||||
noDataCondition={(data) => false}
|
||||
render={(data) => {
|
||||
if (!data && marketId) {
|
||||
return <Splash>{t('Market not found')}</Splash>;
|
||||
}
|
||||
return <>{tradeView}</>;
|
||||
}}
|
||||
/>
|
||||
>
|
||||
{tradeView}
|
||||
</AsyncRenderer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Last24hPriceChange } from '../../components/last-24h-price-change';
|
||||
import { Last24hVolume } from '../../components/last-24h-volume';
|
||||
import { MarketState } from '../../components/market-state';
|
||||
import { MarketTradingMode } from '../../components/market-trading-mode';
|
||||
import { MarketLiquiditySupplied } from '../../components/liquidity-supplied';
|
||||
|
||||
interface TradeMarketHeaderProps {
|
||||
market: SingleMarketFieldsFragment | null;
|
||||
@@ -96,6 +97,10 @@ export const TradeMarketHeader = ({
|
||||
</HeaderStat>
|
||||
) : null}
|
||||
<MarketProposalNotification marketId={market?.id} />
|
||||
<MarketLiquiditySupplied
|
||||
marketId={market?.id}
|
||||
assetDecimals={asset?.decimals || 0}
|
||||
/>
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import { useCallback } from 'react';
|
||||
import { MarketsContainer } from '@vegaprotocol/market-list';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
|
||||
export const Markets = () => {
|
||||
const navigate = useNavigate();
|
||||
const { update } = useGlobalStore((store) => ({ update: store.update }));
|
||||
const handleOnSelect = useCallback(
|
||||
(marketId: string) => {
|
||||
update({ marketId });
|
||||
navigate(Links[Routes.MARKET](marketId));
|
||||
},
|
||||
[update, navigate]
|
||||
[navigate]
|
||||
);
|
||||
|
||||
return <MarketsContainer onSelect={handleOnSelect} />;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './liquidity-supplied';
|
||||
@@ -0,0 +1,130 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
formatNumberPercentage,
|
||||
NetworkParams,
|
||||
t,
|
||||
useDataProvider,
|
||||
useNetworkParams,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
MarketData,
|
||||
MarketDataUpdateFieldsFragment,
|
||||
SingleMarketFieldsFragment,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||
import { HeaderStat } from '../header';
|
||||
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { useCheckLiquidityStatus } from '@vegaprotocol/liquidity';
|
||||
import { DataGrid } from '@vegaprotocol/react-helpers';
|
||||
|
||||
interface Props {
|
||||
marketId?: string;
|
||||
noUpdate?: boolean;
|
||||
assetDecimals: number;
|
||||
}
|
||||
|
||||
export const MarketLiquiditySupplied = ({
|
||||
marketId,
|
||||
assetDecimals,
|
||||
noUpdate = false,
|
||||
}: Props) => {
|
||||
const [market, setMarket] = useState<MarketData>();
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.market_liquidity_stakeToCcySiskas,
|
||||
NetworkParams.market_liquidity_targetstake_triggering_ratio,
|
||||
]);
|
||||
|
||||
const stakeToCcyVolume = Number(params.market_liquidity_stakeToCcySiskas);
|
||||
const triggeringRatio = Number(
|
||||
params.market_liquidity_targetstake_triggering_ratio
|
||||
);
|
||||
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId,
|
||||
}),
|
||||
[marketId]
|
||||
);
|
||||
|
||||
const { data } = useDataProvider<SingleMarketFieldsFragment, never>({
|
||||
dataProvider: marketProvider,
|
||||
variables,
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
const update = useCallback(
|
||||
({ data: marketData }: { data: MarketData | null }) => {
|
||||
if (!noUpdate && marketData) {
|
||||
setMarket(marketData);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[noUpdate]
|
||||
);
|
||||
|
||||
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
|
||||
dataProvider: marketDataProvider,
|
||||
update,
|
||||
variables,
|
||||
skip: noUpdate || !marketId || !data,
|
||||
});
|
||||
|
||||
const supplied = market?.suppliedStake
|
||||
? addDecimalsFormatNumber(
|
||||
new BigNumber(market?.suppliedStake)
|
||||
.multipliedBy(stakeToCcyVolume || 1)
|
||||
.toString(),
|
||||
assetDecimals
|
||||
)
|
||||
: '-';
|
||||
|
||||
const { percentage } = useCheckLiquidityStatus({
|
||||
suppliedStake: market?.suppliedStake || 0,
|
||||
targetStake: market?.targetStake || 0,
|
||||
triggeringRatio,
|
||||
});
|
||||
|
||||
const compiledGrid = [
|
||||
{
|
||||
label: t('Supplied stake'),
|
||||
value: market?.suppliedStake
|
||||
? addDecimalsFormatNumber(
|
||||
new BigNumber(market?.suppliedStake).toString(),
|
||||
assetDecimals
|
||||
)
|
||||
: '-',
|
||||
},
|
||||
{
|
||||
label: t('Target stake'),
|
||||
value: market?.targetStake
|
||||
? addDecimalsFormatNumber(
|
||||
new BigNumber(market?.targetStake).toString(),
|
||||
assetDecimals
|
||||
)
|
||||
: '-',
|
||||
},
|
||||
];
|
||||
|
||||
const description = (
|
||||
<section>
|
||||
{compiledGrid && <DataGrid grid={compiledGrid} />}
|
||||
<br />
|
||||
<Link href={`/#/liquidity/${marketId}`} data-testid="view-liquidity-link">
|
||||
{t('View liquidity provision table')}
|
||||
</Link>
|
||||
</section>
|
||||
);
|
||||
|
||||
return (
|
||||
<HeaderStat
|
||||
heading={t('Liquidity supplied')}
|
||||
description={description}
|
||||
testId="liquidity-supplied"
|
||||
>
|
||||
{/* <Indicator variant={status} /> */}
|
||||
{supplied} ({formatNumberPercentage(percentage, 2)})
|
||||
</HeaderStat>
|
||||
);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState, useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Dialog } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
@@ -12,59 +12,50 @@ import * as constants from '../constants';
|
||||
import { RiskNoticeDialog } from './risk-notice-dialog';
|
||||
import { WelcomeNoticeDialog } from './welcome-notice-dialog';
|
||||
import { WelcomeLandingDialog } from './welcome-landing-dialog';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
|
||||
interface DialogConfig {
|
||||
open?: boolean;
|
||||
content: React.ReactNode;
|
||||
title?: string;
|
||||
size?: 'small' | 'medium';
|
||||
onClose: () => void;
|
||||
}
|
||||
export const WelcomeDialog = () => {
|
||||
const { pathname } = useLocation();
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
const [dialog, setDialog] = useState<DialogConfig | null>(null);
|
||||
const onClose = useCallback(() => {
|
||||
setDialog(null);
|
||||
}, [setDialog]);
|
||||
let dialogContent: React.ReactNode = null;
|
||||
let title = '';
|
||||
let size: 'small' | 'medium' = 'small';
|
||||
const [riskAccepted] = useLocalStorage(constants.RISK_ACCEPTED_KEY);
|
||||
|
||||
const { data } = useDataProvider({
|
||||
dataProvider: activeMarketsProvider,
|
||||
});
|
||||
|
||||
useMemo(() => {
|
||||
switch (true) {
|
||||
case riskAccepted !== 'true' && VEGA_ENV === Networks.MAINNET:
|
||||
setDialog({
|
||||
content: <RiskNoticeDialog onClose={onClose} />,
|
||||
title: t('WARNING'),
|
||||
size: 'medium',
|
||||
onClose,
|
||||
});
|
||||
break;
|
||||
case pathname === '/' && data?.length === 0:
|
||||
setDialog({
|
||||
content: <WelcomeNoticeDialog />,
|
||||
onClose,
|
||||
});
|
||||
break;
|
||||
case pathname === '/' && (data?.length || 0) > 0:
|
||||
setDialog({
|
||||
content: <WelcomeLandingDialog onClose={onClose} />,
|
||||
onClose,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}, [onClose, data?.length, riskAccepted, pathname, VEGA_ENV, setDialog]);
|
||||
return dialog ? (
|
||||
const { update, shouldDisplayWelcomeDialog } = useGlobalStore((store) => ({
|
||||
update: store.update,
|
||||
shouldDisplayWelcomeDialog: store.shouldDisplayWelcomeDialog,
|
||||
}));
|
||||
const isRiskDialogNeeded =
|
||||
riskAccepted !== 'true' && VEGA_ENV === Networks.MAINNET;
|
||||
const isWelcomeDialogNeeded = pathname === '/' || shouldDisplayWelcomeDialog;
|
||||
const onClose = useCallback(() => {
|
||||
update({ shouldDisplayWelcomeDialog: isRiskDialogNeeded });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
dialogContent = null;
|
||||
}, [update, isRiskDialogNeeded]);
|
||||
|
||||
if (isRiskDialogNeeded) {
|
||||
dialogContent = <RiskNoticeDialog onClose={onClose} />;
|
||||
title = t('WARNING');
|
||||
size = 'medium';
|
||||
} else if (isWelcomeDialogNeeded && data?.length === 0) {
|
||||
dialogContent = <WelcomeNoticeDialog />;
|
||||
} else if (isWelcomeDialogNeeded && (data?.length || 0) > 0) {
|
||||
dialogContent = <WelcomeLandingDialog onClose={onClose} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={Boolean(dialog.content)}
|
||||
title={dialog.title}
|
||||
size={dialog.size}
|
||||
onChange={dialog.onClose}
|
||||
open={Boolean(dialogContent)}
|
||||
title={title}
|
||||
size={size}
|
||||
onChange={onClose}
|
||||
>
|
||||
{dialog.content}
|
||||
{dialogContent}
|
||||
</Dialog>
|
||||
) : null;
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
} from '../select-market';
|
||||
import { WelcomeDialogHeader } from './welcome-dialog-header';
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
import { ProposedMarkets } from './proposed-markets';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
|
||||
@@ -27,18 +26,13 @@ export const SelectMarketLandingTable = ({
|
||||
const navigate = useNavigate();
|
||||
const marketId = params.marketId;
|
||||
|
||||
const { update } = useGlobalStore((store) => ({
|
||||
update: store.update,
|
||||
}));
|
||||
|
||||
const onSelect = useCallback(
|
||||
(id: string) => {
|
||||
if (id && id !== marketId) {
|
||||
update({ marketId: id });
|
||||
navigate(Links[Routes.MARKET](id));
|
||||
}
|
||||
},
|
||||
[marketId, update, navigate]
|
||||
[marketId, navigate]
|
||||
);
|
||||
|
||||
const onSelectMarket = useCallback(
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { RouteObject } from 'react-router-dom';
|
||||
import { useRoutes } from 'react-router-dom';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import trimEnd from 'lodash/trimEnd';
|
||||
|
||||
const LazyHome = dynamic(() => import('../client-pages/home'), {
|
||||
@@ -91,7 +91,7 @@ export const ClientRouter = () => {
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="w-full h-full flex justify-center items-center">
|
||||
{t('Loading...')}
|
||||
<Loader />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { LocalStorage } from '@vegaprotocol/react-helpers';
|
||||
import create from 'zustand';
|
||||
import produce from 'immer';
|
||||
|
||||
interface GlobalStore {
|
||||
networkSwitcherDialog: boolean;
|
||||
marketId: string | null;
|
||||
update: (store: Partial<Omit<GlobalStore, 'update'>>) => void;
|
||||
shouldDisplayWelcomeDialog: boolean;
|
||||
}
|
||||
|
||||
interface PageTitleStore {
|
||||
@@ -15,10 +17,15 @@ interface PageTitleStore {
|
||||
export const useGlobalStore = create<GlobalStore>((set) => ({
|
||||
networkSwitcherDialog: false,
|
||||
marketId: LocalStorage.getItem('marketId') || null,
|
||||
update: (state) => {
|
||||
set(state);
|
||||
if (state.marketId) {
|
||||
LocalStorage.setItem('marketId', state.marketId);
|
||||
shouldDisplayWelcomeDialog: false,
|
||||
update: (newState) => {
|
||||
set(
|
||||
produce((state: GlobalStore) => {
|
||||
Object.assign(state, newState);
|
||||
})
|
||||
);
|
||||
if (newState.marketId) {
|
||||
LocalStorage.setItem('marketId', newState.marketId);
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -6,10 +6,10 @@ import {
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { DataGrid, t } from '@vegaprotocol/react-helpers';
|
||||
import { timeInForceLabel } from '@vegaprotocol/orders';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { compileGridData, MarketDataGrid } from '../trading-mode-tooltip';
|
||||
import { compileGridData } from '../trading-mode-tooltip';
|
||||
import { MarketModeValidationType } from '../../constants';
|
||||
|
||||
interface TimeInForceSelectorProps {
|
||||
@@ -78,9 +78,7 @@ export const TimeInForceSelector = ({
|
||||
return (
|
||||
<span>
|
||||
{t('This market is in auction until it reaches')}{' '}
|
||||
<Tooltip
|
||||
description={<MarketDataGrid grid={compileGridData(market)} />}
|
||||
>
|
||||
<Tooltip description={<DataGrid grid={compileGridData(market)} />}>
|
||||
<span>{t('sufficient liquidity')}</span>
|
||||
</Tooltip>
|
||||
{'. '}
|
||||
@@ -95,9 +93,7 @@ export const TimeInForceSelector = ({
|
||||
return (
|
||||
<span>
|
||||
{t('This market is in auction due to')}{' '}
|
||||
<Tooltip
|
||||
description={<MarketDataGrid grid={compileGridData(market)} />}
|
||||
>
|
||||
<Tooltip description={<DataGrid grid={compileGridData(market)} />}>
|
||||
<span>{t('high price volatility')}</span>
|
||||
</Tooltip>
|
||||
{'. '}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { FormGroup, InputError, Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { DataGrid, t } from '@vegaprotocol/react-helpers';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { Toggle } from '@vegaprotocol/ui-toolkit';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { compileGridData, MarketDataGrid } from '../trading-mode-tooltip';
|
||||
import { compileGridData } from '../trading-mode-tooltip';
|
||||
import { MarketModeValidationType } from '../../constants';
|
||||
|
||||
interface TypeSelectorProps {
|
||||
@@ -33,9 +33,7 @@ export const TypeSelector = ({
|
||||
return (
|
||||
<span>
|
||||
{t('This market is in auction until it reaches')}{' '}
|
||||
<Tooltip
|
||||
description={<MarketDataGrid grid={compileGridData(market)} />}
|
||||
>
|
||||
<Tooltip description={<DataGrid grid={compileGridData(market)} />}>
|
||||
<span>{t('sufficient liquidity')}</span>
|
||||
</Tooltip>
|
||||
{'. '}
|
||||
@@ -48,9 +46,7 @@ export const TypeSelector = ({
|
||||
return (
|
||||
<span>
|
||||
{t('This market is in auction due to')}{' '}
|
||||
<Tooltip
|
||||
description={<MarketDataGrid grid={compileGridData(market)} />}
|
||||
>
|
||||
<Tooltip description={<DataGrid grid={compileGridData(market)} />}>
|
||||
<span>{t('high price volatility')}</span>
|
||||
</Tooltip>
|
||||
{'. '}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { DataGridProps } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
t,
|
||||
getDateTimeFormat,
|
||||
@@ -6,7 +7,6 @@ import {
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { Link as UILink } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { MarketDataGridProps } from './market-data-grid';
|
||||
import { Link } from 'react-router-dom';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
@@ -14,7 +14,7 @@ export const compileGridData = (
|
||||
market: MarketDealTicket,
|
||||
onSelect?: (id: string) => void
|
||||
): { label: ReactNode; value?: ReactNode }[] => {
|
||||
const grid: MarketDataGridProps['grid'] = [];
|
||||
const grid: DataGridProps['grid'] = [];
|
||||
const isLiquidityMonitoringAuction =
|
||||
market.data.marketTradingMode ===
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from './market-data-grid';
|
||||
export * from './trading-mode-tooltip';
|
||||
export * from './compile-grid-data';
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { DataGrid, t } from '@vegaprotocol/react-helpers';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { createDocsLinks } from '@vegaprotocol/react-helpers';
|
||||
import { MarketDataGrid } from './market-data-grid';
|
||||
|
||||
type TradingModeTooltipProps = {
|
||||
tradingMode: Schema.MarketTradingMode | null;
|
||||
@@ -46,7 +45,7 @@ export const TradingModeTooltip = ({
|
||||
</ExternalLink>
|
||||
)}
|
||||
</p>
|
||||
{compiledGrid && <MarketDataGrid grid={compiledGrid} />}
|
||||
{compiledGrid && <DataGrid grid={compiledGrid} />}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -72,7 +71,7 @@ export const TradingModeTooltip = ({
|
||||
</ExternalLink>
|
||||
)}
|
||||
</p>
|
||||
{compiledGrid && <MarketDataGrid grid={compiledGrid} />}
|
||||
{compiledGrid && <DataGrid grid={compiledGrid} />}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -94,7 +93,7 @@ export const TradingModeTooltip = ({
|
||||
</ExternalLink>
|
||||
)}
|
||||
</p>
|
||||
{compiledGrid && <MarketDataGrid grid={compiledGrid} />}
|
||||
{compiledGrid && <DataGrid grid={compiledGrid} />}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {
|
||||
formatWithAsset,
|
||||
sumLiquidityCommitted,
|
||||
@@ -6,6 +9,7 @@ import {
|
||||
getCandle24hAgo,
|
||||
getChange,
|
||||
EMPTY_VALUE,
|
||||
useCheckLiquidityStatus,
|
||||
} from './liquidity-utils';
|
||||
|
||||
const CANDLES_1 = [
|
||||
@@ -118,3 +122,50 @@ describe('getChange', () => {
|
||||
expect(result).toEqual(EMPTY_VALUE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useCheckLiquidityStatus', () => {
|
||||
it('should return amber if liquidity is enough', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useCheckLiquidityStatus({
|
||||
suppliedStake: '60',
|
||||
targetStake: '100',
|
||||
triggeringRatio: '0.5',
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
status: Intent.Warning,
|
||||
percentage: new BigNumber('60'),
|
||||
});
|
||||
});
|
||||
|
||||
it('should return red if liquidity is not enough', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useCheckLiquidityStatus({
|
||||
suppliedStake: '60',
|
||||
targetStake: '100',
|
||||
triggeringRatio: '1',
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
status: Intent.Danger,
|
||||
percentage: new BigNumber('60'),
|
||||
});
|
||||
});
|
||||
|
||||
it('should return green if liquidity is enough', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useCheckLiquidityStatus({
|
||||
suppliedStake: '101',
|
||||
targetStake: '100',
|
||||
triggeringRatio: '1',
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
status: Intent.Success,
|
||||
percentage: new BigNumber('101'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import BigNumber from 'bignumber.js';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
|
||||
|
||||
import type { MarketNodeFragment } from './../__generated__/MarketsLiquidity';
|
||||
import { Intent } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
export type LiquidityProvisionMarket = MarketNodeFragment;
|
||||
|
||||
@@ -117,3 +118,46 @@ export const getTargetStake = (
|
||||
) => {
|
||||
return markets.find((m) => m.id === marketId)?.data?.targetStake || '0';
|
||||
};
|
||||
|
||||
export const useCheckLiquidityStatus = ({
|
||||
suppliedStake,
|
||||
targetStake,
|
||||
triggeringRatio,
|
||||
}: {
|
||||
suppliedStake: string | number;
|
||||
targetStake: string | number;
|
||||
triggeringRatio: string | number;
|
||||
}): {
|
||||
status: Intent;
|
||||
percentage: BigNumber;
|
||||
} => {
|
||||
// percentage supplied
|
||||
const percentage = new BigNumber(suppliedStake)
|
||||
.dividedBy(targetStake)
|
||||
.multipliedBy(100);
|
||||
// IF supplied_stake >= target_stake THEN
|
||||
if (new BigNumber(suppliedStake).gte(new BigNumber(targetStake))) {
|
||||
// show a green status, e.g. "🟢 $13,666,999 liquidity supplied"
|
||||
return {
|
||||
status: Intent.Success,
|
||||
percentage,
|
||||
};
|
||||
// ELSE IF supplied_stake > NETPARAM[market.liquidity.targetstake.triggering.ratio] * target_stake THEN
|
||||
} else if (
|
||||
new BigNumber(suppliedStake).gte(
|
||||
new BigNumber(targetStake).multipliedBy(triggeringRatio)
|
||||
)
|
||||
) {
|
||||
// show an amber status, e.g. "🟠 $3,456,123 liquidity supplied"
|
||||
return {
|
||||
status: Intent.Warning,
|
||||
percentage,
|
||||
};
|
||||
// ELSE show a red status, e.g. "🔴 $600,002 liquidity supplied"
|
||||
} else {
|
||||
return {
|
||||
status: Intent.Danger,
|
||||
percentage,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
+4
-2
@@ -3,14 +3,14 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type MarketDataUpdateFieldsFragment = { __typename?: 'ObservableMarketData', marketId: string, bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string };
|
||||
export type MarketDataUpdateFieldsFragment = { __typename?: 'ObservableMarketData', marketId: string, bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null };
|
||||
|
||||
export type MarketDataUpdateSubscriptionVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type MarketDataUpdateSubscription = { __typename?: 'Subscription', marketsData: Array<{ __typename?: 'ObservableMarketData', marketId: string, bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string }> };
|
||||
export type MarketDataUpdateSubscription = { __typename?: 'Subscription', marketsData: Array<{ __typename?: 'ObservableMarketData', marketId: string, bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null }> };
|
||||
|
||||
export type MarketDataFieldsFragment = { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, market: { __typename?: 'Market', id: string } };
|
||||
|
||||
@@ -35,6 +35,8 @@ export const MarketDataUpdateFieldsFragmentDoc = gql`
|
||||
indicativePrice
|
||||
bestStaticBidPrice
|
||||
bestStaticOfferPrice
|
||||
targetStake
|
||||
suppliedStake
|
||||
}
|
||||
`;
|
||||
export const MarketDataFieldsFragmentDoc = gql`
|
||||
|
||||
@@ -11,6 +11,8 @@ fragment MarketDataUpdateFields on ObservableMarketData {
|
||||
indicativePrice
|
||||
bestStaticBidPrice
|
||||
bestStaticOfferPrice
|
||||
targetStake
|
||||
suppliedStake
|
||||
}
|
||||
|
||||
subscription MarketDataUpdate($marketId: ID!) {
|
||||
|
||||
@@ -31,7 +31,7 @@ const compileData = (data?: StatsQuery) => {
|
||||
value.forEach((x) => {
|
||||
const stat = {
|
||||
...x,
|
||||
value: statData,
|
||||
value: statData || '-',
|
||||
};
|
||||
|
||||
stat.promoted ? acc.promoted.push(stat) : acc.table.push(stat);
|
||||
@@ -75,7 +75,7 @@ export const StatsManager = ({ className }: StatsManagerProps) => {
|
||||
return (
|
||||
<PromotedStatsItem
|
||||
title={stat.title}
|
||||
value={stat.value}
|
||||
value={stat.value || '-'}
|
||||
formatter={stat.formatter}
|
||||
goodThreshold={stat.goodThreshold}
|
||||
description={stat.description}
|
||||
@@ -92,7 +92,7 @@ export const StatsManager = ({ className }: StatsManagerProps) => {
|
||||
return (
|
||||
<TableRow
|
||||
title={stat.title}
|
||||
value={stat.value}
|
||||
value={stat.value || '-'}
|
||||
formatter={stat.formatter}
|
||||
goodThreshold={stat.goodThreshold}
|
||||
description={stat.description}
|
||||
|
||||
@@ -48,13 +48,7 @@ export const statsFields: { [key in keyof Stats]: StatFields[] } = {
|
||||
description: t('The total number of nodes registered on the network'),
|
||||
},
|
||||
],
|
||||
inactiveNodes: [
|
||||
{
|
||||
title: t('Inactive nodes'),
|
||||
goodThreshold: (totalInactive: number) => totalInactive < 1,
|
||||
description: t('Nodes that are registered but not validating'),
|
||||
},
|
||||
],
|
||||
inactiveNodes: [],
|
||||
stakedTotal: [
|
||||
{
|
||||
title: t('Total staked'),
|
||||
@@ -174,11 +168,11 @@ export const statsFields: { [key in keyof Stats]: StatFields[] } = {
|
||||
title: t('Uptime'),
|
||||
formatter: (t: string) => {
|
||||
if (!t) {
|
||||
return;
|
||||
return '-';
|
||||
}
|
||||
const date = new Date(t);
|
||||
if (!isValidDate(date)) {
|
||||
return;
|
||||
return '-';
|
||||
}
|
||||
const secSinceStart = (new Date().getTime() - date.getTime()) / 1000;
|
||||
const days = Math.floor(secSinceStart / 60 / 60 / 24);
|
||||
@@ -194,13 +188,13 @@ export const statsFields: { [key in keyof Stats]: StatFields[] } = {
|
||||
title: t('Up since'),
|
||||
formatter: (t: string) => {
|
||||
if (!t) {
|
||||
return;
|
||||
return '-';
|
||||
}
|
||||
const date = new Date(t);
|
||||
if (!isValidDate(date)) {
|
||||
return;
|
||||
return '-';
|
||||
}
|
||||
return getDateTimeFormat().format(date);
|
||||
return getDateTimeFormat().format(date) || '-';
|
||||
},
|
||||
description: t('Genesis'),
|
||||
},
|
||||
|
||||
@@ -102,6 +102,9 @@ export const NetworkParams = {
|
||||
spam_protection_voting_min_tokens: 'spam_protection_voting_min_tokens',
|
||||
spam_protection_proposal_min_tokens: 'spam_protection_proposal_min_tokens',
|
||||
market_liquidity_stakeToCcySiskas: 'market_liquidity_stakeToCcySiskas',
|
||||
market_liquidity_stakeToCcyVolume: 'market_liquidity_stakeToCcyVolume',
|
||||
market_liquidity_targetstake_triggering_ratio:
|
||||
'market_liquidity_targetstake_triggering_ratio',
|
||||
} as const;
|
||||
|
||||
type Params = typeof NetworkParams;
|
||||
|
||||
@@ -9,6 +9,8 @@ const Themes = {
|
||||
|
||||
type Theme = typeof Themes[keyof typeof Themes];
|
||||
|
||||
const isBrowser = typeof window !== 'undefined';
|
||||
|
||||
const validateTheme = (theme: string): theme is Theme => {
|
||||
if (Object.values(Themes).includes(theme as Theme)) return true;
|
||||
LocalStorage.removeItem(THEME_STORAGE_KEY);
|
||||
@@ -16,7 +18,7 @@ const validateTheme = (theme: string): theme is Theme => {
|
||||
};
|
||||
|
||||
const setThemeClassName = (theme: Theme) => {
|
||||
if (typeof window !== 'undefined') {
|
||||
if (isBrowser) {
|
||||
if (theme === Themes.DARK) {
|
||||
document.documentElement.classList.add(Themes.DARK);
|
||||
} else {
|
||||
@@ -26,6 +28,13 @@ const setThemeClassName = (theme: Theme) => {
|
||||
};
|
||||
|
||||
const getCurrentTheme = () => {
|
||||
// If an app is only dark theme then the page will be rendered with
|
||||
// the dark class already applied. In this case return early with state
|
||||
// set to dark
|
||||
if (isBrowser && document.documentElement.classList.contains(Themes.DARK)) {
|
||||
return Themes.DARK;
|
||||
}
|
||||
|
||||
const storedTheme = LocalStorage.getItem(THEME_STORAGE_KEY);
|
||||
|
||||
if (storedTheme && validateTheme(storedTheme)) {
|
||||
@@ -34,7 +43,7 @@ const getCurrentTheme = () => {
|
||||
}
|
||||
|
||||
const theme =
|
||||
typeof window !== 'undefined' &&
|
||||
isBrowser &&
|
||||
typeof window.matchMedia === 'function' && // jest test environment matchMedia is undefined
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? Themes.DARK
|
||||
|
||||
@@ -14,3 +14,4 @@ export * from './lib/links';
|
||||
export * from './lib/is-asset-erc20';
|
||||
export * from './lib/remove-pagination-wrapper';
|
||||
export * from './lib/__generated__/ChainId';
|
||||
export * from './lib/data-grid';
|
||||
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export type MarketDataGridProps = {
|
||||
export type DataGridProps = {
|
||||
grid: {
|
||||
label: string | ReactNode;
|
||||
value?: ReactNode;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const MarketDataGrid = ({ grid }: MarketDataGridProps) => {
|
||||
export const DataGrid = ({ grid }: DataGridProps) => {
|
||||
return (
|
||||
<>
|
||||
{grid.map(
|
||||
@@ -0,0 +1 @@
|
||||
export * from './data-grid';
|
||||
@@ -11,3 +11,4 @@ export * from './remove-0x';
|
||||
export * from './time';
|
||||
export * from './links';
|
||||
export * from './remove-pagination-wrapper';
|
||||
export * from './data-grid';
|
||||
|
||||
@@ -1,74 +1,11 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { z } from 'zod';
|
||||
import { WalletClient } from '@vegaprotocol/wallet-client';
|
||||
import { clearConfig, getConfig, setConfig } from '../storage';
|
||||
import { encodeTransaction } from '../utils';
|
||||
import type { Transaction, VegaConnector } from './vega-connector';
|
||||
import { WalletError } from './vega-connector';
|
||||
|
||||
const VERSION = 'v2';
|
||||
|
||||
enum Methods {
|
||||
ConnectWallet = 'client.connect_wallet',
|
||||
DisconnectWallet = 'client.disconnect_wallet',
|
||||
ListKeys = 'client.list_keys',
|
||||
SendTransaction = 'client.send_transaction',
|
||||
GetChainId = 'client.get_chain_id',
|
||||
}
|
||||
|
||||
const BaseSchema = z.object({
|
||||
id: z.string(),
|
||||
jsonrpc: z.literal('2.0'),
|
||||
});
|
||||
|
||||
const ConnectWalletSchema = BaseSchema.extend({
|
||||
result: z.object({
|
||||
token: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
const ListKeysSchema = BaseSchema.extend({
|
||||
result: z.object({
|
||||
keys: z.array(
|
||||
z.object({
|
||||
publicKey: z.string(),
|
||||
name: z.string(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
const GetChainIdSchema = BaseSchema.extend({
|
||||
result: z.object({
|
||||
chainID: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
const SendTransactionSchema = BaseSchema.extend({
|
||||
result: z.object({
|
||||
receivedAt: z.string(),
|
||||
sentAt: z.string(),
|
||||
transactionHash: z.string(),
|
||||
transaction: z.object({
|
||||
signature: z.object({
|
||||
value: z.string(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
type JsonRpcError = {
|
||||
message: string;
|
||||
code: number;
|
||||
data?: string;
|
||||
};
|
||||
|
||||
type Response =
|
||||
| z.infer<typeof ConnectWalletSchema>
|
||||
| z.infer<typeof ListKeysSchema>
|
||||
| z.infer<typeof GetChainIdSchema>
|
||||
| z.infer<typeof SendTransactionSchema>
|
||||
| { error: JsonRpcError };
|
||||
|
||||
export const ClientErrors = {
|
||||
NO_SERVICE: new WalletError(t('No service'), 100),
|
||||
NO_TOKEN: new WalletError(t('No token'), 101),
|
||||
@@ -86,51 +23,69 @@ export const ClientErrors = {
|
||||
),
|
||||
} as const;
|
||||
|
||||
class NoClientError extends Error {
|
||||
constructor() {
|
||||
super(
|
||||
t('No client found. The connector needs to be initialized with a url.')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class JsonRpcConnector implements VegaConnector {
|
||||
version = VERSION;
|
||||
url: string | null = null;
|
||||
private _url: string | null = null;
|
||||
token: string | null = null;
|
||||
reqId = 0;
|
||||
client?: WalletClient;
|
||||
|
||||
constructor() {
|
||||
const cfg = getConfig();
|
||||
if (cfg) {
|
||||
this.token = cfg.token;
|
||||
|
||||
this.token = cfg?.token ?? null;
|
||||
|
||||
if (cfg && cfg.url) {
|
||||
this.url = cfg.url;
|
||||
this.client = new WalletClient({
|
||||
address: cfg.url,
|
||||
token: cfg.token ?? undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
set url(url: string) {
|
||||
this._url = url;
|
||||
this.client = new WalletClient({
|
||||
address: url,
|
||||
token: this.token ?? undefined,
|
||||
});
|
||||
}
|
||||
|
||||
async getChainId() {
|
||||
const result = await this.request(Methods.GetChainId);
|
||||
if ('error' in result) {
|
||||
throw this.wrapError(result.error);
|
||||
if (!this.client) {
|
||||
throw new NoClientError();
|
||||
}
|
||||
const parseResult = GetChainIdSchema.safeParse(result);
|
||||
if (parseResult.success) {
|
||||
return parseResult.data.result;
|
||||
} else {
|
||||
try {
|
||||
const { result } = await this.client.GetChainId();
|
||||
return result;
|
||||
} catch (err) {
|
||||
throw ClientErrors.INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
async connectWallet() {
|
||||
const result = await this.request(Methods.ConnectWallet, {
|
||||
hostname: window.location.host,
|
||||
});
|
||||
if ('error' in result) {
|
||||
throw this.wrapError(result.error);
|
||||
if (!this.client) {
|
||||
throw new NoClientError();
|
||||
}
|
||||
const parseResult = ConnectWalletSchema.safeParse(result);
|
||||
|
||||
if (parseResult.success) {
|
||||
// store token and other config for eager connect and subsequent requests
|
||||
try {
|
||||
const { result } = await this.client.ConnectWallet();
|
||||
setConfig({
|
||||
token: parseResult.data.result.token,
|
||||
token: result.token,
|
||||
connector: 'jsonRpc',
|
||||
url: this.url,
|
||||
});
|
||||
return parseResult.data.result;
|
||||
} else {
|
||||
return result;
|
||||
} catch (err) {
|
||||
throw ClientErrors.INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
@@ -138,80 +93,57 @@ export class JsonRpcConnector implements VegaConnector {
|
||||
// connect actually calling list_keys here, not to be confused with connect_wallet
|
||||
// which retrieves the session token
|
||||
async connect() {
|
||||
const cfg = getConfig();
|
||||
if (!cfg?.token) {
|
||||
throw ClientErrors.NO_TOKEN;
|
||||
if (!this.client) {
|
||||
throw new NoClientError();
|
||||
}
|
||||
const result = await this.request(Methods.ListKeys, {
|
||||
token: cfg.token,
|
||||
});
|
||||
if ('error' in result) {
|
||||
throw this.wrapError(result.error);
|
||||
}
|
||||
const parseResult = ListKeysSchema.safeParse(result);
|
||||
if (parseResult.success) {
|
||||
return parseResult.data.result.keys;
|
||||
} else {
|
||||
|
||||
try {
|
||||
const { result } = await this.client.ListKeys();
|
||||
return result.keys;
|
||||
} catch (err) {
|
||||
throw ClientErrors.INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
const cfg = getConfig();
|
||||
|
||||
if (cfg?.token) {
|
||||
await this.request(Methods.DisconnectWallet, {
|
||||
token: cfg.token,
|
||||
});
|
||||
if (!this.client) {
|
||||
throw new NoClientError();
|
||||
}
|
||||
|
||||
await this.client.DisconnectWallet();
|
||||
clearConfig();
|
||||
}
|
||||
|
||||
async sendTx(pubKey: string, transaction: Transaction) {
|
||||
const cfg = getConfig();
|
||||
if (!cfg?.token) {
|
||||
throw ClientErrors.NO_TOKEN;
|
||||
if (!this.client) {
|
||||
throw new NoClientError();
|
||||
}
|
||||
|
||||
const result = await this.request(Methods.SendTransaction, {
|
||||
token: cfg.token,
|
||||
publicKey: pubKey,
|
||||
sendingMode: 'TYPE_SYNC',
|
||||
encodedTransaction: encodeTransaction(transaction),
|
||||
});
|
||||
try {
|
||||
const { result } = await this.client.SendTransaction({
|
||||
publicKey: pubKey,
|
||||
sendingMode: 'TYPE_SYNC',
|
||||
transaction,
|
||||
});
|
||||
|
||||
if ('error' in result) {
|
||||
// In the case of sending a tx, error code 3001 indicates that the
|
||||
// user rejected the tx. Returning null will allow the dialog to close immediately
|
||||
if (result.error.code === 3001) {
|
||||
return null;
|
||||
} else {
|
||||
throw this.wrapError(result.error);
|
||||
}
|
||||
}
|
||||
|
||||
const parsedResult = SendTransactionSchema.safeParse(result);
|
||||
|
||||
if (parsedResult.success) {
|
||||
return {
|
||||
transactionHash: parsedResult.data.result.transactionHash,
|
||||
sentAt: parsedResult.data.result.sentAt,
|
||||
receivedAt: parsedResult.data.result.receivedAt,
|
||||
signature: parsedResult.data.result.transaction.signature.value,
|
||||
transactionHash: result.transactionHash,
|
||||
sentAt: result.sentAt,
|
||||
receivedAt: result.receivedAt,
|
||||
signature: result.transaction.signature.value,
|
||||
};
|
||||
} else {
|
||||
} catch (err) {
|
||||
throw ClientErrors.INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
async checkCompat() {
|
||||
try {
|
||||
const result = await fetch(`${this.url}/api/${this.version}/methods`);
|
||||
const result = await fetch(`${this._url}/api/${this.version}/methods`);
|
||||
if (!result.ok) {
|
||||
const err = ClientErrors.INVALID_WALLET;
|
||||
err.data = t(
|
||||
`The wallet running at ${this.url} is not supported. Required version is ${this.version}`
|
||||
`The wallet running at ${this._url} is not supported. Required version is ${this.version}`
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
@@ -224,29 +156,4 @@ export class JsonRpcConnector implements VegaConnector {
|
||||
throw ClientErrors.NO_SERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
private async request(method: Methods, params?: object): Promise<Response> {
|
||||
try {
|
||||
const result = await fetch(`${this.url}/api/${this.version}/requests`, {
|
||||
method: 'post',
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method,
|
||||
params,
|
||||
id: `${this.reqId++}`,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
const json = await result.json();
|
||||
return json;
|
||||
} catch (err) {
|
||||
throw ClientErrors.NO_SERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
private wrapError(error: JsonRpcError) {
|
||||
return new WalletError(error.message, error.code, error.data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,13 +76,13 @@ interface ProposalNewMarketTerms {
|
||||
changes: {
|
||||
decimalPlaces: string;
|
||||
positionDecimalPlaces: string;
|
||||
lpPriceRange: string;
|
||||
instrument: {
|
||||
name: string;
|
||||
code: string;
|
||||
future: {
|
||||
settlementAsset: string;
|
||||
quoteName: string;
|
||||
settlementPriceDecimals: number;
|
||||
dataSourceSpecForSettlementData: DataSourceSpec;
|
||||
dataSourceSpecForTradingTermination: DataSourceSpec;
|
||||
dataSourceSpecBinding: DataSourceSpecBinding;
|
||||
@@ -100,12 +100,6 @@ interface ProposalNewMarketTerms {
|
||||
};
|
||||
logNormal: LogNormal;
|
||||
};
|
||||
liquidityCommitment: {
|
||||
commitmentAmount: string;
|
||||
fee: string;
|
||||
buys: Buy[];
|
||||
sells: Buy[];
|
||||
};
|
||||
};
|
||||
closingTimestamp: number;
|
||||
enactmentTimestamp: number;
|
||||
@@ -184,35 +178,66 @@ interface ProposalUpdateAssetTerms {
|
||||
}
|
||||
|
||||
interface DataSourceSpecBinding {
|
||||
settlementPriceProperty: string;
|
||||
settlementDataProperty: string;
|
||||
tradingTerminationProperty: string;
|
||||
}
|
||||
|
||||
interface DataSourceSpec {
|
||||
config: {
|
||||
signers: Signer[];
|
||||
filters: Filter[];
|
||||
interface InternalDataSourceSpec {
|
||||
internal: {
|
||||
time: {
|
||||
conditions: Condition[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
interface ExternalDataSourceSpec {
|
||||
external: {
|
||||
oracle: {
|
||||
signers: Signer[];
|
||||
filters: Filter[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
type DataSourceSpec = InternalDataSourceSpec | ExternalDataSourceSpec;
|
||||
|
||||
type Signer =
|
||||
| {
|
||||
address: string;
|
||||
ethAddress: {
|
||||
address: string;
|
||||
};
|
||||
}
|
||||
| {
|
||||
key: string;
|
||||
pubKey: {
|
||||
key: string;
|
||||
};
|
||||
};
|
||||
|
||||
interface Filter {
|
||||
key: {
|
||||
name: string;
|
||||
type: string;
|
||||
};
|
||||
key: DefaultFilterKey | IntegerFilterKey;
|
||||
conditions?: Condition[];
|
||||
}
|
||||
|
||||
interface DefaultFilterKey {
|
||||
name: string;
|
||||
type: 'TYPE_DECIMAL' | 'TYPE_BOOLEAN' | 'TYPE_TIMESTAMP' | 'TYPE_STRING';
|
||||
}
|
||||
|
||||
interface IntegerFilterKey {
|
||||
name: string;
|
||||
type: 'TYPE_INTEGER';
|
||||
numberDecimalPlaces: string;
|
||||
}
|
||||
|
||||
type ConditionOperator =
|
||||
| 'OPERATOR_EQUALS'
|
||||
| 'OPERATOR_GREATER_THAN'
|
||||
| 'OPERATOR_GREATER_THAN_OR_EQUAL'
|
||||
| 'OPERATOR_LESS_THAN'
|
||||
| 'OPERATOR_LESS_THAN_OR_EQUAL';
|
||||
|
||||
interface Condition {
|
||||
operator: string;
|
||||
operator: ConditionOperator;
|
||||
value: string;
|
||||
}
|
||||
|
||||
@@ -236,12 +261,6 @@ interface Trigger {
|
||||
auctionExtension: string;
|
||||
}
|
||||
|
||||
interface Buy {
|
||||
offset: string;
|
||||
proportion: number;
|
||||
reference: string;
|
||||
}
|
||||
|
||||
export interface ProposalSubmission {
|
||||
rationale: {
|
||||
description: string;
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface VegaWalletContextShape {
|
||||
connect: (connector: VegaConnector) => Promise<PubKey[] | null>;
|
||||
|
||||
/** Disconnects from the connector and clears public key state */
|
||||
disconnect: () => Promise<boolean>;
|
||||
disconnect: () => Promise<void>;
|
||||
|
||||
/** Sets the current selected public key */
|
||||
selectPubKey: (pubKey: string) => void;
|
||||
|
||||
@@ -59,23 +59,19 @@ export const VegaWalletProvider = ({ children }: VegaWalletProviderProps) => {
|
||||
}, []);
|
||||
|
||||
const disconnect = useCallback(async () => {
|
||||
// always clear state after attempted disconnection.. this
|
||||
// is because long lived token sessions (used in tests)
|
||||
// cannot be cleared. Clearing state will force user to reconnect
|
||||
// again as expected
|
||||
setPubKeys(null);
|
||||
setPubKey(null);
|
||||
LocalStorage.removeItem(WALLET_KEY);
|
||||
try {
|
||||
await connector.current?.disconnect();
|
||||
setPubKeys(null);
|
||||
setPubKey(null);
|
||||
connector.current = null;
|
||||
LocalStorage.removeItem(WALLET_KEY);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (err instanceof WalletError && err.code === 100) {
|
||||
setPubKeys(null);
|
||||
setPubKey(null);
|
||||
connector.current = null;
|
||||
LocalStorage.removeItem(WALLET_KEY);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
connector.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"@sentry/nextjs": "^6.19.3",
|
||||
"@sentry/react": "^6.19.2",
|
||||
"@sentry/tracing": "^6.19.2",
|
||||
"@vegaprotocol/wallet-client": "0.1.4",
|
||||
"@walletconnect/ethereum-provider": "^1.7.5",
|
||||
"@web3-react/core": "8.0.20-beta.0",
|
||||
"@web3-react/metamask": "8.0.16-beta.0",
|
||||
|
||||
@@ -7559,6 +7559,15 @@
|
||||
"@typescript-eslint/types" "5.40.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@vegaprotocol/wallet-client@0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@vegaprotocol/wallet-client/-/wallet-client-0.1.4.tgz#202fa1a84dbef57199810383f2887a7ee0afd64c"
|
||||
integrity sha512-uGEbusoi3lwyl7Nn9ovBg9YHrfcH/Rl33KUcLfdMeTX8FZO+n7BVm3ejd00e5RsM/PJlqJ1oW4qkiq7kervxng==
|
||||
dependencies:
|
||||
express "4.18.2"
|
||||
nanoid "3.3.4"
|
||||
node-fetch "2.6.7"
|
||||
|
||||
"@walletconnect/browser-utils@^1.8.0":
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@walletconnect/browser-utils/-/browser-utils-1.8.0.tgz#33c10e777aa6be86c713095b5206d63d32df0951"
|
||||
@@ -12798,7 +12807,7 @@ expect@^29.0.0:
|
||||
jest-message-util "^29.1.2"
|
||||
jest-util "^29.1.2"
|
||||
|
||||
express@^4.17.1, express@^4.17.3:
|
||||
express@4.18.2, express@^4.17.1, express@^4.17.3:
|
||||
version "4.18.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
|
||||
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
|
||||
@@ -17333,7 +17342,7 @@ nan@^2.12.1:
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
|
||||
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
|
||||
|
||||
nanoid@^3.3.1, nanoid@^3.3.4:
|
||||
nanoid@3.3.4, nanoid@^3.3.1, nanoid@^3.3.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
||||
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
|
||||
|
||||
Reference in New Issue
Block a user