Compare commits
30
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0270b16af6 | ||
|
|
849a59e533 | ||
|
|
33857177d2 | ||
|
|
c1796cf028 | ||
|
|
b76f8d7d18 | ||
|
|
c77ee96ed9 | ||
|
|
9150a4fdf8 | ||
|
|
3f6f53b3a7 | ||
|
|
c06918c3e7 | ||
|
|
1551bdf9c3 | ||
|
|
d8dfece956 | ||
|
|
c0673898a8 | ||
|
|
6e294a2c17 | ||
|
|
157934ff3d | ||
|
|
09b3514383 | ||
|
|
7a319d28d6 | ||
|
|
7555762711 | ||
|
|
1ad557ad5a | ||
|
|
d1b50eb22b | ||
|
|
b6dff98c75 | ||
|
|
af83957821 | ||
|
|
abcd4a3ff4 | ||
|
|
d454e69a89 | ||
|
|
aa4b733b4c | ||
|
|
b59c9cf2ad | ||
|
|
5d246a6c23 | ||
|
|
16b09c1ff9 | ||
|
|
e235f05c43 | ||
|
|
fc134edd96 | ||
|
|
08b735be8b |
+1
-2
@@ -73,8 +73,7 @@
|
||||
"error",
|
||||
{
|
||||
"prefer": "type-imports",
|
||||
"disallowTypeAnnotations": true,
|
||||
"fixStyle": "inline-type-imports"
|
||||
"disallowTypeAnnotations": true
|
||||
}
|
||||
],
|
||||
"curly": ["error", "multi-line"]
|
||||
|
||||
+1
-4
@@ -9,7 +9,4 @@ apps/static/src/assets/devnet-tranches.json
|
||||
apps/static/src/assets/mainnet-tranches.json
|
||||
apps/static/src/assets/testnet-tranches.json
|
||||
|
||||
/apps/**/cypress/reports/
|
||||
/apps/**/cypress/downloads/
|
||||
|
||||
/.nx/cache
|
||||
/.nx/cache
|
||||
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"plugins": ["prettier-plugin-tailwindcss"],
|
||||
"singleQuote": true
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useAssetDataProvider } from '@vegaprotocol/assets';
|
||||
import { addDecimalsFixedFormatNumber } from '@vegaprotocol/utils';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { AssetLink } from '../links';
|
||||
|
||||
export type AssetBalanceProps = {
|
||||
@@ -23,12 +23,12 @@ const AssetBalance = ({
|
||||
|
||||
const label =
|
||||
!loading && asset && asset.decimals
|
||||
? addDecimalsFixedFormatNumber(price, asset.decimals)
|
||||
? addDecimalsFormatNumber(price, asset.decimals)
|
||||
: price;
|
||||
|
||||
return (
|
||||
<div className="inline-block">
|
||||
<span className="font-mono">{label}</span>{' '}
|
||||
<span>{label}</span>{' '}
|
||||
{showAssetLink && asset?.id ? (
|
||||
<AssetLink showAssetSymbol={showAssetSymbol} assetId={assetId} />
|
||||
) : null}
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
useAssetTypeMapping,
|
||||
useAssetStatusMapping,
|
||||
type AssetFieldsFragment,
|
||||
} from '@vegaprotocol/assets';
|
||||
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
|
||||
import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { type VegaICellRendererParams } from '@vegaprotocol/datagrid';
|
||||
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
|
||||
import { useRef, useLayoutEffect } from 'react';
|
||||
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { type RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||
|
||||
type AssetsTableProps = {
|
||||
data: AssetFieldsFragment[] | null;
|
||||
};
|
||||
export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
const assetTypeMapping = useAssetTypeMapping();
|
||||
const assetStatusMapping = useAssetStatusMapping();
|
||||
const navigate = useNavigate();
|
||||
const ref = useRef<AgGridReact>(null);
|
||||
const showColumnsOnDesktop = () => {
|
||||
@@ -52,14 +47,14 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
field: 'source.__typename',
|
||||
hide: window.innerWidth < BREAKPOINT_MD,
|
||||
valueFormatter: ({ value }: { value?: string }) =>
|
||||
value ? assetTypeMapping[value].value : '',
|
||||
value ? AssetTypeMapping[value].value : '',
|
||||
},
|
||||
{
|
||||
headerName: t('Status'),
|
||||
field: 'status',
|
||||
hide: window.innerWidth < BREAKPOINT_MD,
|
||||
valueFormatter: ({ value }: { value?: string }) =>
|
||||
value ? assetStatusMapping[value].value : '',
|
||||
value ? AssetStatusMapping[value].value : '',
|
||||
},
|
||||
{
|
||||
colId: 'actions',
|
||||
@@ -74,7 +69,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
}: VegaICellRendererParams<AssetFieldsFragment, 'id'>) =>
|
||||
value ? (
|
||||
<ButtonLink
|
||||
onClick={() => {
|
||||
onClick={(e) => {
|
||||
navigate(value);
|
||||
}}
|
||||
>
|
||||
@@ -85,7 +80,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
),
|
||||
},
|
||||
],
|
||||
[navigate, assetStatusMapping, assetTypeMapping]
|
||||
[navigate]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,18 +2,18 @@ import { useMemo } from 'react';
|
||||
import { getAsset, type MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import { type ColDef } from 'ag-grid-community';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
type VegaICellRendererParams,
|
||||
type VegaValueGetterParams,
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueGetterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { useRef, useLayoutEffect } from 'react';
|
||||
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
||||
import { MarketStateMapping } from '@vegaprotocol/types';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import { type RowClickedEvent } from 'ag-grid-community';
|
||||
import type { RowClickedEvent } from 'ag-grid-community';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
|
||||
type MarketsTableProps = {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { type ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { VoteProgress } from '@vegaprotocol/proposals';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
type VegaICellRendererParams,
|
||||
type VegaValueFormatterParams,
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { type RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
@@ -105,7 +105,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
? new BigNumber(0)
|
||||
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center pt-2 uppercase">
|
||||
<div className="flex items-center justify-center h-full pt-2 uppercase">
|
||||
<VoteProgress
|
||||
threshold={requiredMajorityPercentage}
|
||||
progress={yesPercentage}
|
||||
|
||||
@@ -15,7 +15,6 @@ import isUndefined from 'lodash/isUndefined';
|
||||
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
|
||||
import { TxDetailsChainEventWithdrawal } from './tx-erc20-withdrawal';
|
||||
import { TxDetailsChainEventErc20AssetDelist } from './tx-erc20-asset-delist';
|
||||
import { TxDetailsContractCall } from './tx-contract-call';
|
||||
|
||||
interface ChainEventProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@@ -39,7 +38,7 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { builtin, erc20, erc20Multisig, stakingEvent, contractCall } =
|
||||
const { builtin, erc20, erc20Multisig, stakingEvent } =
|
||||
txData.command.chainEvent;
|
||||
|
||||
// Builtin Asset events
|
||||
@@ -141,10 +140,6 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (contractCall) {
|
||||
return <TxDetailsContractCall contractCall={contractCall} />;
|
||||
}
|
||||
|
||||
// If we hit this return, tx-shared-details should give a basic overview
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { decodeEthCallResult } from './tx-contract-call';
|
||||
import { base64 } from 'ethers/lib/utils';
|
||||
import { defaultAbiCoder } from '@ethersproject/abi';
|
||||
import { BigNumber } from '@ethersproject/bignumber';
|
||||
|
||||
describe('decodeEthCallResult', () => {
|
||||
it('should decode contractData correctly (mocked)', () => {
|
||||
const mockContractData = base64.encode(
|
||||
defaultAbiCoder.encode(['int256'], [BigNumber.from(123)])
|
||||
);
|
||||
const result = decodeEthCallResult(mockContractData);
|
||||
expect(result).toBe('123');
|
||||
});
|
||||
|
||||
it('should decode contractData correctly (known data)', () => {
|
||||
const mockContractData = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADH8cueyY=';
|
||||
const result = decodeEthCallResult(mockContractData);
|
||||
expect(result).toBe('3435020581670');
|
||||
});
|
||||
|
||||
it('should return "-" when an error occurs', () => {
|
||||
const mockContractData = 'invalid_data';
|
||||
const result = decodeEthCallResult(mockContractData);
|
||||
expect(result).toBe('-');
|
||||
});
|
||||
});
|
||||
@@ -1,88 +0,0 @@
|
||||
import { TableCell, TableRow } from '../../../table';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { defaultAbiCoder, base64 } from 'ethers/lib/utils';
|
||||
import { BigNumber } from 'ethers';
|
||||
import OracleLink from '../../../links/oracle-link/oracle-link';
|
||||
import { useExplorerOracleSpecByIdQuery } from '../../../../routes/oracles/__generated__/Oracles';
|
||||
import { OracleEthSource } from '../../../../routes/oracles/components/oracle-eth-source';
|
||||
|
||||
/**
|
||||
* Decodes the b64/ABIcoded result from an eth cal
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export function decodeEthCallResult(contractData: string): string {
|
||||
try {
|
||||
const rawResult = defaultAbiCoder.decode(
|
||||
['int256'],
|
||||
base64.decode(contractData)
|
||||
);
|
||||
|
||||
// Finally, convert the resulting BigNumber in to a string
|
||||
const res = BigNumber.from(rawResult[0]).toString();
|
||||
return res;
|
||||
} catch (e) {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
|
||||
interface TxDetailsContractCallProps {
|
||||
contractCall: components['schemas']['vegaEthContractCallEvent'];
|
||||
}
|
||||
|
||||
export const TxDetailsContractCall = ({
|
||||
contractCall,
|
||||
}: TxDetailsContractCallProps) => {
|
||||
const { data } = useExplorerOracleSpecByIdQuery({
|
||||
variables: {
|
||||
id: contractCall.specId || '1',
|
||||
},
|
||||
});
|
||||
|
||||
if (!contractCall || !contractCall.result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{contractCall.specId && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Oracle')}</TableCell>
|
||||
<TableCell>
|
||||
<OracleLink
|
||||
id={contractCall.specId}
|
||||
hasSeenOracleReports={true}
|
||||
status={data?.oracleSpec?.dataSourceSpec.spec.status || '-'}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{contractCall.blockHeight && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('ETH block')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
id={contractCall.blockHeight}
|
||||
type={EthExplorerLinkTypes.block}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{data?.oracleSpec?.dataSourceSpec && (
|
||||
<OracleEthSource
|
||||
sourceType={data.oracleSpec.dataSourceSpec.spec.data.sourceType}
|
||||
/>
|
||||
)}
|
||||
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Result')}</TableCell>
|
||||
<TableCell>{decodeEthCallResult(contractCall.result)}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,11 +1,51 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
import { TableWithTbody } from '../../table';
|
||||
import { defaultAbiCoder, base64 } from 'ethers/lib/utils';
|
||||
import { ChainEvent } from './chain-events';
|
||||
import { BigNumber } from 'ethers';
|
||||
|
||||
import type { AbiType } from '../../../lib/encoders/abis/abi-types';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
|
||||
interface AbiOutput {
|
||||
type: AbiType;
|
||||
internalType: AbiType;
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the b64/ABIcoded result from an eth cal
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export function decodeEthCallResult(
|
||||
data: BlockExplorerTransactionResult
|
||||
): string {
|
||||
const ethResult = data.command.chainEvent?.contractCall.result;
|
||||
|
||||
try {
|
||||
// Decode the result string: base64 => uint8array
|
||||
const data = base64.decode(ethResult);
|
||||
|
||||
// Parse the escaped ABI in to an object
|
||||
const abi = JSON.parse(
|
||||
'[{"inputs":[],"name":"latestAnswer","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"}]'
|
||||
);
|
||||
// Pull the expected types out of the Oracles ABI
|
||||
const types: AbiType[] = abi[0].outputs.map((o: AbiOutput) => o.type);
|
||||
|
||||
const rawResult = defaultAbiCoder.decode(types, data);
|
||||
|
||||
// Finally, convert the resulting BigNumber in to a string
|
||||
const res = BigNumber.from(rawResult[0]).toString();
|
||||
return res;
|
||||
} catch (e) {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
|
||||
interface TxDetailsChainEventProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
pubKey: string | undefined;
|
||||
|
||||
@@ -3,8 +3,8 @@ import { DATA_SOURCES } from '../../../config';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { TxDetailsOrder } from './tx-order';
|
||||
import { type BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import { type TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsHeartbeat } from './tx-hearbeat';
|
||||
import { TxDetailsGeneric } from './tx-generic';
|
||||
import { TxDetailsBatch } from './tx-batch';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Table, TableRow } from '../table';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { type BlockExplorerTransactions } from '../../routes/types/block-explorer-response';
|
||||
import type { BlockExplorerTransactions } from '../../routes/types/block-explorer-response';
|
||||
import { getTxsDataUrl } from '../../hooks/get-txs-data-url';
|
||||
import { AsyncRenderer, Loader } from '@vegaprotocol/ui-toolkit';
|
||||
import EmptyList from '../empty-list/empty-list';
|
||||
@@ -22,7 +22,7 @@ export const TxsPerBlock = ({ blockHeight, txCount }: TxsPerBlockProps) => {
|
||||
return (
|
||||
<AsyncRenderer data={data} error={error} loading={!!loading}>
|
||||
{data && data.transactions.length > 0 ? (
|
||||
<div className="mb-28 overflow-x-auto whitespace-nowrap">
|
||||
<div className="overflow-x-auto whitespace-nowrap mb-28">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow modifier="bordered" className="font-mono">
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { type URLSearchParamsInit } from 'react-router-dom';
|
||||
import type { URLSearchParamsInit } from 'react-router-dom';
|
||||
import { useCallback } from 'react';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
type BlockExplorerTransactionResult,
|
||||
type BlockExplorerTransactions,
|
||||
import type {
|
||||
BlockExplorerTransactionResult,
|
||||
BlockExplorerTransactions,
|
||||
} from '../routes/types/block-explorer-response';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
import { AllFilterOptions } from '../components/txs/tx-filter';
|
||||
import { type FilterOption } from '../components/txs/tx-filter';
|
||||
import type { FilterOption } from '../components/txs/tx-filter';
|
||||
import { BE_TXS_PER_REQUEST, getTxsDataUrl } from './get-txs-data-url';
|
||||
|
||||
export function getTypeFilters(filters?: Set<FilterOption>) {
|
||||
|
||||
@@ -9,13 +9,11 @@ import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
|
||||
import { useState } from 'react';
|
||||
import { PageTitle } from '../../components/page-helpers/page-title';
|
||||
|
||||
type Params = { assetId: string };
|
||||
|
||||
export const AssetPage = () => {
|
||||
useDocumentTitle(['Assets']);
|
||||
useScrollToLocation();
|
||||
|
||||
const { assetId } = useParams<Params>();
|
||||
const { assetId } = useParams<{ assetId: string }>();
|
||||
const { data, loading, error } = useAssetDataProvider(assetId || '');
|
||||
|
||||
const title = data ? data.name : error ? t('Asset not found') : '';
|
||||
@@ -43,7 +41,7 @@ export const AssetPage = () => {
|
||||
loading={loading}
|
||||
error={error}
|
||||
>
|
||||
<div className="relative h-full">
|
||||
<div className="h-full relative">
|
||||
<AssetDetailsTable asset={data as AssetFieldsFragment} />
|
||||
</div>
|
||||
</AsyncRenderer>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import {
|
||||
type BlockMeta,
|
||||
type TendermintBlockchainResponse,
|
||||
import type {
|
||||
BlockMeta,
|
||||
TendermintBlockchainResponse,
|
||||
} from '../tendermint-blockchain-response';
|
||||
import { RouteTitle } from '../../../components/route-title';
|
||||
import { BlocksRefetch } from '../../../components/blocks';
|
||||
|
||||
@@ -17,10 +17,8 @@ import { NodeLink } from '../../../components/links';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
import EmptyList from '../../../components/empty-list/empty-list';
|
||||
|
||||
type Params = { block: string };
|
||||
|
||||
const Block = () => {
|
||||
const { block } = useParams<Params>();
|
||||
const { block } = useParams<{ block: string }>();
|
||||
useDocumentTitle(['Blocks', `Block #${block}`]);
|
||||
const {
|
||||
state: { data: blockData, loading, error },
|
||||
@@ -31,7 +29,7 @@ const Block = () => {
|
||||
<RouteTitle data-testid="block-header">{t(`BLOCK ${block}`)}</RouteTitle>
|
||||
<AsyncRenderer data={blockData} error={error} loading={!!loading}>
|
||||
<>
|
||||
<div className="mb-8 grid grid-cols-2 gap-2">
|
||||
<div className="grid grid-cols-2 gap-2 mb-8">
|
||||
<Link
|
||||
data-testid="previous-block"
|
||||
to={`/${Routes.BLOCKS}/${Number(block) - 1}`}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { AsyncRenderer, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { DATA_SOURCES } from '../../config';
|
||||
import { type TendermintGenesisResponse } from './tendermint-genesis-response';
|
||||
import type { TendermintGenesisResponse } from './tendermint-genesis-response';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
|
||||
const Genesis = () => {
|
||||
|
||||
@@ -11,12 +11,10 @@ import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
|
||||
import { marketInfoWithDataProvider } from '@vegaprotocol/markets';
|
||||
import { PageTitle } from '../../components/page-helpers/page-title';
|
||||
|
||||
type Params = { marketId: string };
|
||||
|
||||
export const MarketPage = () => {
|
||||
useScrollToLocation();
|
||||
|
||||
const { marketId } = useParams<Params>();
|
||||
const { marketId } = useParams<{ marketId: string }>();
|
||||
|
||||
const { data, loading, error } = useDataProvider({
|
||||
dataProvider: marketInfoWithDataProvider,
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { getNodes } from '@vegaprotocol/utils';
|
||||
import { MarketLink } from '../../../components/links';
|
||||
import { TableRow, TableCell, TableHeader } from '../../../components/table';
|
||||
import {
|
||||
useExplorerOracleFormMarketsQuery,
|
||||
type ExplorerOracleForMarketsMarketFragment,
|
||||
} from '../__generated__/OraclesForMarkets';
|
||||
import type { ExplorerOracleForMarketsMarketFragment } from '../__generated__/OraclesForMarkets';
|
||||
import { useExplorerOracleFormMarketsQuery } from '../__generated__/OraclesForMarkets';
|
||||
|
||||
interface OracleMarketsProps {
|
||||
id: string;
|
||||
|
||||
@@ -9,10 +9,8 @@ import { AsyncRenderer, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import filter from 'recursive-key-filter';
|
||||
import { TruncateInline } from '../../../components/truncate/truncate';
|
||||
|
||||
type Params = { id: string };
|
||||
|
||||
export const Oracle = () => {
|
||||
const { id } = useParams<Params>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
useDocumentTitle(['Oracle', `Oracle #${truncateByChars(id || '1', 5, 5)}`]);
|
||||
|
||||
|
||||
@@ -6,10 +6,8 @@ import { useDocumentTitle } from '../../../../hooks/use-document-title';
|
||||
|
||||
import { PartyAccounts } from '../components/party-accounts';
|
||||
|
||||
type Params = { party: string };
|
||||
|
||||
const PartyAccountsByAsset = () => {
|
||||
const { party } = useParams<Params>();
|
||||
const { party } = useParams<{ party: string }>();
|
||||
|
||||
useDocumentTitle(['Public keys', party || '-']);
|
||||
const partyId = toNonHex(party ? party : '');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useExplorerPartyAssetsQuery } from '../__generated__/Party-assets';
|
||||
import { AssetLink, MarketLink } from '../../../../components/links';
|
||||
import AssetBalance from '../../../../components/asset-balance/asset-balance';
|
||||
import { AccountTypeMapping } from '@vegaprotocol/types';
|
||||
import { AccountManager } from '@vegaprotocol/accounts';
|
||||
import { useCallback } from 'react';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
interface PartyAccountsProps {
|
||||
partyId: string;
|
||||
@@ -13,71 +12,21 @@ interface PartyAccountsProps {
|
||||
* appearing first and... tbd
|
||||
*/
|
||||
export const PartyAccounts = ({ partyId }: PartyAccountsProps) => {
|
||||
const { data } = useExplorerPartyAssetsQuery({
|
||||
variables: { partyId },
|
||||
});
|
||||
|
||||
const party = data?.partiesConnection?.edges[0]?.node;
|
||||
const accounts =
|
||||
party?.accountsConnection?.edges?.filter((edge) => edge?.node) || [];
|
||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||
const onClickAsset = useCallback(
|
||||
(assetId?: string) => {
|
||||
assetId && openAssetDetailsDialog(assetId);
|
||||
},
|
||||
[openAssetDetailsDialog]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="block min-h-44 h-60 4 w-full border-red-800 relative">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-right px-4">Balance</th>
|
||||
<th className="text-left px-4">Type</th>
|
||||
<th className="text-left px-4">Market</th>
|
||||
<th className="text-left px-4">Asset</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{accounts
|
||||
.sort((a, b) => {
|
||||
// Sort by asset id, then market id, with general accounts first
|
||||
if (!a) {
|
||||
return 1;
|
||||
}
|
||||
if (!b) {
|
||||
return -1;
|
||||
}
|
||||
if (a.node.asset.id !== b.node.asset.id) {
|
||||
return a.node.asset.id.localeCompare(b.node.asset.id);
|
||||
}
|
||||
if (a.node.type === 'ACCOUNT_TYPE_GENERAL') return -1;
|
||||
if (b.node.type === 'ACCOUNT_TYPE_GENERAL') return 1;
|
||||
if (a.node.market && b.node.market) {
|
||||
return a.node.market.id.localeCompare(b.node.market.id);
|
||||
} else {
|
||||
return a.node.type.localeCompare(b.node.type);
|
||||
}
|
||||
})
|
||||
.map((e) => {
|
||||
if (!e) return null;
|
||||
const { type, asset, balance, market } = e.node;
|
||||
|
||||
return (
|
||||
<tr className="border-t border-neutral-300 dark:border-neutral-600">
|
||||
<td className="px-4 text-right">
|
||||
<AssetBalance
|
||||
assetId={asset.id}
|
||||
price={balance}
|
||||
showAssetSymbol={true}
|
||||
/>
|
||||
</td>
|
||||
<td className="px-4">{AccountTypeMapping[type]}</td>
|
||||
<td className="px-4">
|
||||
{market?.id ? <MarketLink id={market.id} /> : '-'}
|
||||
</td>
|
||||
<td className="px-4">
|
||||
<AssetLink assetId={asset.id} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<AccountManager
|
||||
partyId={partyId}
|
||||
onClickAsset={onClickAsset}
|
||||
isReadOnly={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,13 +19,11 @@ import type { FilterOption } from '../../../components/txs/tx-filter';
|
||||
import { AllFilterOptions, TxsFilter } from '../../../components/txs/tx-filter';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
type Params = { party: string };
|
||||
|
||||
const Party = () => {
|
||||
const [params] = useSearchParams();
|
||||
|
||||
const [filters, setFilters] = useState(new Set(AllFilterOptions));
|
||||
const { party } = useParams<Params>();
|
||||
const { party } = useParams<{ party: string }>();
|
||||
|
||||
useDocumentTitle(['Public keys', party || '-']);
|
||||
const navigate = useNavigate();
|
||||
@@ -62,7 +60,7 @@ const Party = () => {
|
||||
|
||||
if (!isValidPartyId(partyId)) {
|
||||
return (
|
||||
<div className="mx-auto max-w-sm">
|
||||
<div className="max-w-sm mx-auto">
|
||||
<Notification
|
||||
message={t('Invalid party ID')}
|
||||
intent={Intent.Danger}
|
||||
@@ -86,7 +84,7 @@ const Party = () => {
|
||||
truncateEnd={visibleChars}
|
||||
/>
|
||||
|
||||
<div className="grid w-full grid-flow-row grid-cols-1 md:grid-flow-col md:grid-cols-2 md:space-x-4">
|
||||
<div className="grid md:grid-flow-col grid-flow-row md:space-x-4 grid-cols-1 md:grid-cols-2 w-full">
|
||||
<PartyBlockAccounts
|
||||
accountError={AccountError}
|
||||
accountLoading={AccountLoading}
|
||||
|
||||
@@ -4,15 +4,13 @@ import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import { RenderFetched } from '../../../components/render-fetched';
|
||||
import { TxDetails } from './tx-details';
|
||||
import { type BlockExplorerTransaction } from '../../../routes/types/block-explorer-response';
|
||||
import type { BlockExplorerTransaction } from '../../../routes/types/block-explorer-response';
|
||||
import { toNonHex } from '../../../components/search/detect-search';
|
||||
import { PageHeader } from '../../../components/page-header';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
|
||||
type Params = { txHash: string };
|
||||
|
||||
const Tx = () => {
|
||||
const { txHash } = useParams<Params>();
|
||||
const { txHash } = useParams<{ txHash: string }>();
|
||||
const hash = txHash ? toNonHex(txHash) : '';
|
||||
let errorMessage: string | undefined = undefined;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"extends": ["plugin:cypress/recommended", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "cypress"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
switchVegaWalletPubKey,
|
||||
vegaWalletSetSpecifiedApprovalAmount,
|
||||
} from '../../support/wallet-functions';
|
||||
import { type testFreeformProposal } from '../../support/common-interfaces';
|
||||
import type { testFreeformProposal } from '../../support/common-interfaces';
|
||||
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
|
||||
import {
|
||||
createGovernanceTransferProposalTxBody,
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
vegaWalletTeardown,
|
||||
} from '../../support/wallet-functions';
|
||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||
import { type testFreeformProposal } from '../../support/common-interfaces';
|
||||
import type { testFreeformProposal } from '../../support/common-interfaces';
|
||||
|
||||
const vegaWalletStakedBalances = 'vega-wallet-balance-staked-validators';
|
||||
const vegaWalletAssociatedBalance = 'associated-amount';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { type testFreeformProposal } from '../../support/common-interfaces';
|
||||
import type { testFreeformProposal } from '../../support/common-interfaces';
|
||||
import {
|
||||
navigateTo,
|
||||
navigation,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet, useEagerConnect } from '@vegaprotocol/wallet';
|
||||
import { FLAGS, useEnvironment } from '@vegaprotocol/environment';
|
||||
import { useWeb3React } from '@web3-react/core';
|
||||
import React, { Suspense } from 'react';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SplashError } from './components/splash-error';
|
||||
@@ -164,14 +164,13 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
|
||||
);
|
||||
}
|
||||
|
||||
const loading = (
|
||||
<Splash>
|
||||
<SplashLoader />
|
||||
</Splash>
|
||||
);
|
||||
|
||||
if (!loaded) {
|
||||
return loading;
|
||||
return (
|
||||
<Splash>
|
||||
<SplashLoader />
|
||||
</Splash>
|
||||
);
|
||||
}
|
||||
return <Suspense fallback={loading}>{children}</Suspense>;
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
@@ -42,7 +42,6 @@ import {
|
||||
useNodeSwitcherStore,
|
||||
DocsLinks,
|
||||
NodeFailure,
|
||||
AppLoader as Loader,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { ENV } from './config';
|
||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||
@@ -353,11 +352,9 @@ function App() {
|
||||
useInitializeEnv();
|
||||
|
||||
return (
|
||||
<React.Suspense fallback={<Loader />}>
|
||||
<NetworkLoader cache={cache}>
|
||||
<AppContainer />
|
||||
</NetworkLoader>
|
||||
</React.Suspense>
|
||||
<NetworkLoader cache={cache}>
|
||||
<AppContainer />
|
||||
</NetworkLoader>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../../libs/i18n/src/locales
|
||||
@@ -10,7 +10,7 @@ import noIcon from '../../images/token-no-icon.png';
|
||||
import vegaBlack from '../../images/vega_black.png';
|
||||
import vegaVesting from '../../images/vega_vesting.png';
|
||||
import { BigNumber } from '../../lib/bignumber';
|
||||
import { type WalletCardAssetProps } from '../wallet-card';
|
||||
import type { WalletCardAssetProps } from '../wallet-card';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
@@ -21,12 +21,12 @@ import {
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { useAppState } from '../../contexts/app-state/app-state-context';
|
||||
import {
|
||||
DelegationsDocument,
|
||||
type DelegationsQuery,
|
||||
type DelegationsQueryVariables,
|
||||
type WalletDelegationFieldsFragment,
|
||||
import type {
|
||||
DelegationsQuery,
|
||||
DelegationsQueryVariables,
|
||||
WalletDelegationFieldsFragment,
|
||||
} from './__generated__/Delegations';
|
||||
import { DelegationsDocument } from './__generated__/Delegations';
|
||||
import { isPartyNotFoundError } from '../../lib/party';
|
||||
|
||||
export const usePollForDelegations = () => {
|
||||
@@ -44,7 +44,6 @@ export const usePollForDelegations = () => {
|
||||
const [delegatedNodes, setDelegatedNodes] = React.useState<
|
||||
{
|
||||
nodeId: string;
|
||||
// eslint-disable-next-line
|
||||
name: string;
|
||||
hasStakePending: boolean;
|
||||
currentEpochStake?: BigNumber;
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useWeb3React } from '@web3-react/core';
|
||||
import React from 'react';
|
||||
|
||||
import { SplashLoader } from '../../components/splash-loader';
|
||||
import { type ContractsContextShape } from './contracts-context';
|
||||
import type { ContractsContextShape } from './contracts-context';
|
||||
import { ContractsContext } from './contracts-context';
|
||||
import { createDefaultProvider } from '../../lib/web3-connectors';
|
||||
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||
|
||||
@@ -1,41 +1,29 @@
|
||||
import type { Module } from 'i18next';
|
||||
import i18n from 'i18next';
|
||||
import HttpBackend from 'i18next-http-backend';
|
||||
import LocizeBackend from 'i18next-locize-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
const isInDev = process.env.NODE_ENV === 'development';
|
||||
const useLocize = isInDev && !!process.env.NX_USE_LOCIZE;
|
||||
|
||||
const backend = useLocize
|
||||
? {
|
||||
projectId: '96ac1231-4bdd-455a-b9d7-f5322a2e7430',
|
||||
apiKey: process.env.NX_LOCIZE_API_KEY,
|
||||
referenceLng: 'en',
|
||||
}
|
||||
: {
|
||||
loadPath: '/assets/locales/{{lng}}/{{ns}}.json',
|
||||
};
|
||||
|
||||
const Backend: Module = useLocize ? LocizeBackend : HttpBackend;
|
||||
import dev from './translations/dev.json';
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: 'en',
|
||||
// we init with resources
|
||||
resources: {
|
||||
en: {
|
||||
translations: {
|
||||
...dev,
|
||||
},
|
||||
},
|
||||
},
|
||||
lng: undefined,
|
||||
fallbackLng: 'en',
|
||||
supportedLngs: ['en'],
|
||||
load: 'languageOnly',
|
||||
debug: isInDev,
|
||||
debug: true,
|
||||
// have a common namespace used around the full app
|
||||
ns: ['governance'],
|
||||
defaultNS: 'governance',
|
||||
ns: ['translations'],
|
||||
defaultNS: 'translations',
|
||||
keySeparator: false, // we use content as keys
|
||||
backend,
|
||||
saveMissing: useLocize && !!process.env.NX_LOCIZE_API_KEY,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
|
||||
+924
-924
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
import { type CollateralBridge } from '@vegaprotocol/smart-contracts';
|
||||
import type { CollateralBridge } from '@vegaprotocol/smart-contracts';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { useBridgeContract, useEthereumTransaction } from '@vegaprotocol/web3';
|
||||
@@ -88,7 +88,7 @@ export const ListAsset = ({
|
||||
assetData.erc20ListAssetBundle;
|
||||
return (
|
||||
<div className="mb-8">
|
||||
<h3 className="mb-2 text-xl">{t('ListAsset')}</h3>
|
||||
<h3 className="text-xl mb-2">{t('ListAsset')}</h3>
|
||||
<p className="pr-8">{t('ListAssetDescription')}</p>
|
||||
<EthWalletContainer>
|
||||
<Button
|
||||
|
||||
@@ -4,7 +4,7 @@ import { VoteValue } from '@vegaprotocol/types';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useUserVoteQuery } from './__generated__/Vote';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { type FinalizedVote } from '@vegaprotocol/proposals';
|
||||
import type { FinalizedVote } from '@vegaprotocol/proposals';
|
||||
|
||||
export enum VoteState {
|
||||
NotCast = 'NotCast',
|
||||
|
||||
@@ -5,17 +5,15 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SplashLoader } from '../../../components/splash-loader';
|
||||
import { ProposalsList } from '../components/proposals-list';
|
||||
import { useProposalsQuery } from './__generated__/Proposals';
|
||||
import { getNodes, removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import {
|
||||
ProposalState,
|
||||
ProtocolUpgradeProposalStatus,
|
||||
} from '@vegaprotocol/types';
|
||||
import { type NodeConnection, type NodeEdge } from '@vegaprotocol/utils';
|
||||
import {
|
||||
useProposalsQuery,
|
||||
type ProposalFieldsFragment,
|
||||
} from './__generated__/Proposals';
|
||||
import { type ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import type { NodeConnection, NodeEdge } from '@vegaprotocol/utils';
|
||||
import type { ProposalFieldsFragment } from './__generated__/Proposals';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import * as faker from 'faker';
|
||||
import isArray from 'lodash/isArray';
|
||||
import mergeWith from 'lodash/mergeWith';
|
||||
|
||||
import { type PartialDeep } from 'type-fest';
|
||||
import { type ProposalQuery } from '../proposal/__generated__/Proposal';
|
||||
import { type ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { ProposalQuery } from '../proposal/__generated__/Proposal';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
|
||||
export function generateProtocolUpgradeProposal(
|
||||
override: PartialDeep<ProtocolUpgradeProposalFieldsFragment> = {}
|
||||
|
||||
@@ -22,13 +22,11 @@ interface UserBalances {
|
||||
balance: BigNumber;
|
||||
}
|
||||
|
||||
type Params = { address: string };
|
||||
|
||||
export const RedemptionInformation = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const tranches = useTranches((state) => state.tranches);
|
||||
const { address } = useParams<Params>();
|
||||
const { address } = useParams<{ address: string }>();
|
||||
const [userBalances, setUserBalances] = useState<null | UserBalances>();
|
||||
const getUsersBalances = useGetUserBalances(address);
|
||||
useEffect(() => {
|
||||
@@ -86,7 +84,7 @@ export const RedemptionInformation = () => {
|
||||
i18nKey="noVestingTokens"
|
||||
components={{
|
||||
tranchesLink: (
|
||||
<Link className="text-white underline" to={Routes.SUPPLY} />
|
||||
<Link className="underline text-white" to={Routes.SUPPLY} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
@@ -162,7 +160,7 @@ export const RedemptionInformation = () => {
|
||||
intent={Intent.Warning}
|
||||
>
|
||||
<p>{t('Find out more about Staking.')}</p>
|
||||
<Link to={Routes.VALIDATORS} className="text-white underline">
|
||||
<Link to={Routes.VALIDATORS} className="underline text-white">
|
||||
{t('Stake VEGA tokens')}
|
||||
</Link>
|
||||
</Callout>
|
||||
|
||||
@@ -21,10 +21,9 @@ import RoutesConfig from '../routes';
|
||||
interface FormFields {
|
||||
address: string;
|
||||
}
|
||||
type Params = { address: string };
|
||||
|
||||
const RedemptionRouter = () => {
|
||||
const { address } = useParams<Params>();
|
||||
const { address } = useParams<{ address: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
const validatePubkey = useCallback(
|
||||
@@ -90,7 +89,7 @@ const RedemptionRouter = () => {
|
||||
{t('View connected Eth Wallet')}
|
||||
</Button>
|
||||
)}
|
||||
<p className="flex justify-center py-4">{t('OR')}</p>
|
||||
<p className="py-4 flex justify-center">{t('OR')}</p>
|
||||
<form
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
data-testid="view-connector-form"
|
||||
|
||||
@@ -21,8 +21,6 @@ import { EthConnectPrompt } from '../../../components/eth-connect-prompt';
|
||||
import { useUserTrancheBalances } from '../hooks';
|
||||
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
||||
|
||||
type Params = { id: string };
|
||||
|
||||
export const RedeemFromTranche = () => {
|
||||
const { account: address } = useWeb3React();
|
||||
const { vesting } = useContracts();
|
||||
@@ -36,7 +34,7 @@ export const RedeemFromTranche = () => {
|
||||
tranches: state.tranches,
|
||||
getTranches: state.getTranches,
|
||||
}));
|
||||
const { id } = useParams<Params>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const numberId = Number(id);
|
||||
const tranche = React.useMemo(
|
||||
() => tranches?.find(({ tranche_id }) => tranche_id === numberId) || null,
|
||||
@@ -88,7 +86,7 @@ export const RedeemFromTranche = () => {
|
||||
i18nKey="noVestingTokens"
|
||||
components={{
|
||||
tranchesLink: (
|
||||
<Link className="text-white underline" to={Routes.SUPPLY} />
|
||||
<Link className="underline text-white" to={Routes.SUPPLY} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
@@ -130,13 +128,13 @@ export const RedeemFromTranche = () => {
|
||||
components={{
|
||||
stakingLink: (
|
||||
<Link
|
||||
className="text-white underline"
|
||||
className="underline text-white"
|
||||
to={Routes.VALIDATORS}
|
||||
/>
|
||||
),
|
||||
governanceLink: (
|
||||
<Link
|
||||
className="text-white underline"
|
||||
className="underline text-white"
|
||||
to={Routes.PROPOSALS}
|
||||
/>
|
||||
),
|
||||
|
||||
@@ -11,12 +11,12 @@ import { useTransaction } from '../../../hooks/use-transaction';
|
||||
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
||||
import { removeDecimal, removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
PartyStakeLinkingsDocument,
|
||||
type LinkingsFieldsFragment,
|
||||
type PartyStakeLinkingsQuery,
|
||||
type PartyStakeLinkingsQueryVariables,
|
||||
import type {
|
||||
LinkingsFieldsFragment,
|
||||
PartyStakeLinkingsQuery,
|
||||
PartyStakeLinkingsQueryVariables,
|
||||
} from './__generated__/PartyStakeLinkings';
|
||||
import { PartyStakeLinkingsDocument } from './__generated__/PartyStakeLinkings';
|
||||
|
||||
export const useAddStake = (
|
||||
address: string,
|
||||
|
||||
+7
-7
@@ -26,9 +26,9 @@ import {
|
||||
ValidatorRenderer,
|
||||
VotingPowerRenderer,
|
||||
} from './shared';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import { type ColDef, type RowHeightParams } from 'ag-grid-community';
|
||||
import { type ValidatorsTableProps } from './shared';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { ColDef, RowHeightParams } from 'ag-grid-community';
|
||||
import type { ValidatorsTableProps } from './shared';
|
||||
import {
|
||||
formatNumber,
|
||||
formatNumberPercentage,
|
||||
@@ -83,19 +83,19 @@ const TopThirdCellRenderer = (
|
||||
e.preventDefault();
|
||||
setHideTopThird(false);
|
||||
}}
|
||||
className="grid h-full w-full grid-cols-[60px_1fr] overflow-scroll px-0 py-4 text-center text-sm text-white"
|
||||
className="grid grid-cols-[60px_1fr] w-full h-full py-4 px-0 text-sm text-white text-center overflow-scroll"
|
||||
>
|
||||
<div className="px-3 text-left text-xs">
|
||||
<div className="px-3 text-xs text-left">
|
||||
{params?.data?.rankingDisplay}
|
||||
</div>
|
||||
<div className="whitespace-normal px-3">
|
||||
<div className="px-3 whitespace-normal">
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
data-testid="show-all-validators"
|
||||
rightIcon={
|
||||
<Icon
|
||||
name="arrow-right"
|
||||
className="mr-2 fill-current align-text-top"
|
||||
className="mr-2 align-text-top fill-current"
|
||||
/>
|
||||
}
|
||||
className="inline-flex items-center"
|
||||
|
||||
+3
-3
@@ -22,9 +22,9 @@ import {
|
||||
PendingStakeRenderer,
|
||||
VotingPowerRenderer,
|
||||
} from './shared';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import { type ColDef } from 'ag-grid-community';
|
||||
import { type ValidatorsTableProps } from './shared';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import type { ValidatorsTableProps } from './shared';
|
||||
import {
|
||||
formatNumber,
|
||||
formatNumberPercentage,
|
||||
|
||||
@@ -28,14 +28,12 @@ interface StakingNodeProps {
|
||||
previousEpochData?: PreviousEpochQuery;
|
||||
}
|
||||
|
||||
type Params = { node: string };
|
||||
|
||||
export const StakingNode = ({ data, previousEpochData }: StakingNodeProps) => {
|
||||
const { pubKey: vegaKey } = useVegaWallet();
|
||||
const {
|
||||
appState: { decimals },
|
||||
} = useAppState();
|
||||
const { node } = useParams<Params>();
|
||||
const { node } = useParams<{ node: string }>();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { nodeInfo, currentEpoch, delegations } = React.useMemo(
|
||||
|
||||
@@ -16,12 +16,10 @@ import Routes from '../routes';
|
||||
import { TrancheLabel } from './tranche-label';
|
||||
import { useTranches } from '../../lib/tranches/tranches-store';
|
||||
|
||||
type Params = { trancheId: string; address: string };
|
||||
|
||||
export const Tranche = () => {
|
||||
const tranches = useTranches((state) => state.tranches);
|
||||
const { t } = useTranslation();
|
||||
const { trancheId } = useParams<Params>();
|
||||
const { trancheId } = useParams<{ trancheId: string; address: string }>();
|
||||
const { chainId } = useWeb3React();
|
||||
const tranche = tranches?.find(
|
||||
(tranche) => trancheId && parseInt(trancheId) === tranche.tranche_id
|
||||
@@ -43,7 +41,7 @@ export const Tranche = () => {
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="flex justify-between gap-x-4 px-4 py-2"
|
||||
className="flex justify-between gap-x-4 py-2 px-4"
|
||||
data-testid="redeemed-tranche-tokens"
|
||||
>
|
||||
<span>{t('alreadyRedeemed')}</span>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
||||
import { locales } from '@vegaprotocol/i18n';
|
||||
import dev from './i18n/translations/dev.json';
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
@@ -12,10 +12,16 @@ import ResizeObserver from 'resize-observer-polyfill';
|
||||
// en translations
|
||||
i18n.use(initReactI18next).init({
|
||||
// we init with resources
|
||||
resources: locales,
|
||||
resources: {
|
||||
en: {
|
||||
translations: {
|
||||
...dev,
|
||||
},
|
||||
},
|
||||
},
|
||||
fallbackLng: 'en',
|
||||
ns: ['governance'],
|
||||
defaultNS: 'governance',
|
||||
ns: ['translations'],
|
||||
defaultNS: 'translations',
|
||||
});
|
||||
|
||||
global.ResizeObserver = ResizeObserver;
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
import { DApp, useLinks } from '@vegaprotocol/environment';
|
||||
import { type Market } from '@vegaprotocol/liquidity';
|
||||
import type { Market } from '@vegaprotocol/liquidity';
|
||||
import {
|
||||
displayChange,
|
||||
formatWithAsset,
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { type VegaValueFormatterParams } from '@vegaprotocol/datagrid';
|
||||
import type { VegaValueFormatterParams } from '@vegaprotocol/datagrid';
|
||||
import { PriceChangeCell } from '@vegaprotocol/datagrid';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
@@ -21,10 +21,10 @@ import {
|
||||
HealthBar,
|
||||
TooltipCellComponent,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
type GetRowIdParams,
|
||||
type RowClickedEvent,
|
||||
type ColDef,
|
||||
import type {
|
||||
GetRowIdParams,
|
||||
RowClickedEvent,
|
||||
ColDef,
|
||||
} from 'ag-grid-community';
|
||||
import 'ag-grid-community/styles/ag-grid.css';
|
||||
import 'ag-grid-community/styles/ag-theme-alpine.css';
|
||||
@@ -253,7 +253,7 @@ export const MarketList = () => {
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
<div
|
||||
className="w-full grow"
|
||||
className="grow w-full"
|
||||
style={{ minHeight: 500, overflow: 'hidden' }}
|
||||
>
|
||||
<Grid
|
||||
|
||||
@@ -60,21 +60,19 @@ const useMarketDetails = (marketId: string | undefined) => {
|
||||
};
|
||||
};
|
||||
|
||||
type Params = { marketId: string };
|
||||
|
||||
export const Detail = () => {
|
||||
const { marketId } = useParams<Params>();
|
||||
const { marketId } = useParams<{ marketId: string }>();
|
||||
const { data, loading, error } = useMarketDetails(marketId);
|
||||
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
<div className="bg-greys-light-100 px-16 pb-12 pt-14">
|
||||
<div className="mx-auto max-w-screen-xl">
|
||||
<div className="px-16 pt-14 pb-12 bg-greys-light-100">
|
||||
<div className="max-w-screen-xl mx-auto">
|
||||
<Header name={data.name} symbol={data.symbol} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-16">
|
||||
<div className="mx-auto max-w-screen-xl">
|
||||
<div className="max-w-screen-xl mx-auto">
|
||||
<div className="py-12">
|
||||
{marketId && (
|
||||
<Market
|
||||
@@ -88,7 +86,7 @@ export const Detail = () => {
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="font-alpha calt mb-4 text-2xl">
|
||||
<h2 className="font-alpha calt text-2xl mb-4">
|
||||
{t('Current Liquidity Provision')}
|
||||
</h2>
|
||||
<LPProvidersGrid
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { type GetRowIdParams, type ColDef } from 'ag-grid-community';
|
||||
import type { GetRowIdParams, ColDef } from 'ag-grid-community';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
import {
|
||||
type LiquidityProviderFeeShareFieldsFragment,
|
||||
type LiquidityProvisionFieldsFragment,
|
||||
import type {
|
||||
LiquidityProviderFeeShareFieldsFragment,
|
||||
LiquidityProvisionFieldsFragment,
|
||||
} from '@vegaprotocol/liquidity';
|
||||
import { formatWithAsset } from '@vegaprotocol/liquidity';
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useRef, useCallback, useEffect } from 'react';
|
||||
import { AgGridReact } from 'ag-grid-react';
|
||||
import {
|
||||
type AgGridReactProps,
|
||||
type AgReactUiProps,
|
||||
type AgGridReact as AgGridReactType,
|
||||
import type {
|
||||
AgGridReactProps,
|
||||
AgReactUiProps,
|
||||
AgGridReact as AgGridReactType,
|
||||
} from 'ag-grid-react';
|
||||
import classNames from 'classnames';
|
||||
import 'ag-grid-community/styles/ag-grid.css';
|
||||
@@ -34,7 +34,7 @@ export const Grid = ({ isRowClickable, ...props }: Props) => {
|
||||
|
||||
return (
|
||||
<AgGridReact
|
||||
className={classNames('ag-theme-alpine font-alpha calt h-full', {
|
||||
className={classNames('ag-theme-alpine h-full font-alpha calt', {
|
||||
'row-hover': isRowClickable,
|
||||
})}
|
||||
rowHeight={92}
|
||||
|
||||
@@ -11,12 +11,12 @@ import {
|
||||
Loader,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useContracts } from '../../config/contracts/contracts-context';
|
||||
import { type FormEvent } from 'react';
|
||||
import {
|
||||
type AddSignerBundle,
|
||||
type AddSignerBundleVariables,
|
||||
import type { FormEvent } from 'react';
|
||||
import type {
|
||||
AddSignerBundle,
|
||||
AddSignerBundleVariables,
|
||||
} from '../__generated__/AddSignerBundle';
|
||||
import { type MultisigControl } from '@vegaprotocol/smart-contracts';
|
||||
import type { MultisigControl } from '@vegaprotocol/smart-contracts';
|
||||
|
||||
export const ADD_SIGNER_QUERY = gql`
|
||||
query AddSignerBundle($nodeId: ID!) {
|
||||
|
||||
@@ -11,12 +11,12 @@ import {
|
||||
Loader,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useContracts } from '../../config/contracts/contracts-context';
|
||||
import { type FormEvent } from 'react';
|
||||
import {
|
||||
type RemoveSignerBundle,
|
||||
type RemoveSignerBundleVariables,
|
||||
import type { FormEvent } from 'react';
|
||||
import type {
|
||||
RemoveSignerBundle,
|
||||
RemoveSignerBundleVariables,
|
||||
} from '../__generated__/RemoveSignerBundle';
|
||||
import { type MultisigControl } from '@vegaprotocol/smart-contracts';
|
||||
import type { MultisigControl } from '@vegaprotocol/smart-contracts';
|
||||
|
||||
const REMOVE_SIGNER_QUERY = gql`
|
||||
query RemoveSignerBundle($nodeId: ID!) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { MultisigControl } from '@vegaprotocol/smart-contracts';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { type ContractsContextShape } from './contracts-context';
|
||||
import type { ContractsContextShape } from './contracts-context';
|
||||
import { ContractsContext } from './contracts-context';
|
||||
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
export const useTranslation = () => ({
|
||||
t: (label: string, replacements?: Record<string, string>) => {
|
||||
let translatedLabel = label;
|
||||
if (typeof replacements === 'object' && replacements !== null) {
|
||||
Object.keys(replacements).forEach((key) => {
|
||||
translatedLabel = translatedLabel.replace(
|
||||
`{{${key}}}`,
|
||||
replacements[key]
|
||||
);
|
||||
});
|
||||
}
|
||||
return translatedLabel;
|
||||
},
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { TransferContainer } from '@vegaprotocol/accounts';
|
||||
import { GetStarted } from '../../components/welcome-dialog/get-started';
|
||||
import { GetStarted } from '../../components/welcome-dialog';
|
||||
|
||||
export const Transfer = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { GetStarted } from '../../components/welcome-dialog/get-started';
|
||||
import { GetStarted } from '../../components/welcome-dialog';
|
||||
import { WithdrawContainer } from '../../components/withdraw-container';
|
||||
|
||||
export const Withdraw = () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '@vegaprotocol/environment';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { VegaWalletProvider } from '@vegaprotocol/wallet';
|
||||
import { Suspense, type ReactNode } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Web3Provider } from './web3-provider';
|
||||
|
||||
export const Bootstrapper = ({ children }: { children: ReactNode }) => {
|
||||
@@ -36,43 +36,41 @@ export const Bootstrapper = ({ children }: { children: ReactNode }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Suspense fallback={<AppLoader />}>
|
||||
<NetworkLoader
|
||||
cache={cacheConfig}
|
||||
<NetworkLoader
|
||||
cache={cacheConfig}
|
||||
skeleton={<AppLoader />}
|
||||
failure={
|
||||
<AppFailure title={t('Could not initialize app')} error={error} />
|
||||
}
|
||||
>
|
||||
<NodeGuard
|
||||
skeleton={<AppLoader />}
|
||||
failure={
|
||||
<AppFailure title={t('Could not initialize app')} error={error} />
|
||||
}
|
||||
failure={<NodeFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
|
||||
>
|
||||
<NodeGuard
|
||||
<Web3Provider
|
||||
skeleton={<AppLoader />}
|
||||
failure={<NodeFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
|
||||
failure={
|
||||
<AppFailure title={t(`Could not configure web3 provider`)} />
|
||||
}
|
||||
>
|
||||
<Web3Provider
|
||||
skeleton={<AppLoader />}
|
||||
failure={
|
||||
<AppFailure title={t(`Could not configure web3 provider`)} />
|
||||
}
|
||||
<VegaWalletProvider
|
||||
config={{
|
||||
network: VEGA_ENV,
|
||||
vegaUrl: VEGA_URL,
|
||||
vegaWalletServiceUrl: VEGA_WALLET_URL,
|
||||
links: {
|
||||
explorer: VEGA_EXPLORER_URL,
|
||||
concepts: DocsLinks.VEGA_WALLET_CONCEPTS_URL,
|
||||
chromeExtensionUrl: CHROME_EXTENSION_URL,
|
||||
mozillaExtensionUrl: MOZILLA_EXTENSION_URL,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<VegaWalletProvider
|
||||
config={{
|
||||
network: VEGA_ENV,
|
||||
vegaUrl: VEGA_URL,
|
||||
vegaWalletServiceUrl: VEGA_WALLET_URL,
|
||||
links: {
|
||||
explorer: VEGA_EXPLORER_URL,
|
||||
concepts: DocsLinks.VEGA_WALLET_CONCEPTS_URL,
|
||||
chromeExtensionUrl: CHROME_EXTENSION_URL,
|
||||
mozillaExtensionUrl: MOZILLA_EXTENSION_URL,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</VegaWalletProvider>
|
||||
</Web3Provider>
|
||||
</NodeGuard>
|
||||
</NetworkLoader>
|
||||
</Suspense>
|
||||
{children}
|
||||
</VegaWalletProvider>
|
||||
</Web3Provider>
|
||||
</NodeGuard>
|
||||
</NetworkLoader>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
import type { Module } from 'i18next';
|
||||
import i18n from 'i18next';
|
||||
import HttpBackend from 'i18next-http-backend';
|
||||
import LocizeBackend from 'i18next-locize-backend';
|
||||
import type { HttpBackendOptions, RequestCallback } from 'i18next-http-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
const isInDev = process.env.NODE_ENV === 'development';
|
||||
const useLocize = isInDev && !!process.env.NX_USE_LOCIZE;
|
||||
|
||||
const backend = useLocize
|
||||
? {
|
||||
projectId: '96ac1231-4bdd-455a-b9d7-f5322a2e7430',
|
||||
apiKey: process.env.NX_LOCIZE_API_KEY,
|
||||
referenceLng: 'en',
|
||||
}
|
||||
: {
|
||||
loadPath: '/locales/{{lng}}/{{ns}}.json',
|
||||
request: (
|
||||
options: HttpBackendOptions,
|
||||
url: string,
|
||||
payload: string,
|
||||
callback: RequestCallback
|
||||
) => {
|
||||
if (typeof window === 'undefined') {
|
||||
callback(false, { status: 200, data: {} });
|
||||
return;
|
||||
}
|
||||
fetch(url).then((response) => {
|
||||
if (!response.ok) {
|
||||
return callback(response.statusText || 'Error', {
|
||||
status: response.status,
|
||||
data: {},
|
||||
});
|
||||
}
|
||||
response
|
||||
.text()
|
||||
.then((data) => {
|
||||
callback(null, { status: response.status, data });
|
||||
})
|
||||
.catch((error) => callback(error, { status: 200, data: {} }));
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const Backend: Module = useLocize ? LocizeBackend : HttpBackend;
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: 'en',
|
||||
fallbackLng: 'en',
|
||||
supportedLngs: ['en'],
|
||||
load: 'languageOnly',
|
||||
// have a common namespace used around the full app
|
||||
ns: [
|
||||
'accounts',
|
||||
'assets',
|
||||
'candles-chart',
|
||||
'datagrid',
|
||||
'deal-ticket',
|
||||
'deposits',
|
||||
'environment',
|
||||
'fills',
|
||||
'funding-payments',
|
||||
'trading',
|
||||
],
|
||||
defaultNS: 'trading',
|
||||
keySeparator: false, // we use content as keys
|
||||
backend,
|
||||
debug: isInDev,
|
||||
saveMissing: useLocize && !!process.env.NX_LOCIZE_API_KEY,
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
@@ -3,7 +3,7 @@ import Head from 'next/head';
|
||||
import type { AppProps } from 'next/app';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
useEnvTriggerMapping,
|
||||
envTriggerMapping,
|
||||
Networks,
|
||||
NodeSwitcherDialog,
|
||||
useEnvironment,
|
||||
@@ -32,7 +32,6 @@ import { SSRLoader } from './ssr-loader';
|
||||
import { PartyActiveOrdersHandler } from './party-active-orders-handler';
|
||||
import { MaybeConnectEagerly } from './maybe-connect-eagerly';
|
||||
import { TransactionHandlers } from './transaction-handlers';
|
||||
import '../lib/i18n';
|
||||
|
||||
const DEFAULT_TITLE = t('Welcome to Vega trading!');
|
||||
|
||||
@@ -40,7 +39,7 @@ const Title = () => {
|
||||
const { pageTitle } = usePageTitleStore((store) => ({
|
||||
pageTitle: store.pageTitle,
|
||||
}));
|
||||
const envTriggerMapping = useEnvTriggerMapping();
|
||||
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
const networkName = envTriggerMapping[VEGA_ENV];
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../libs/i18n/src/locales
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ETHERSCAN_ADDRESS, useEtherscanLink } from '@vegaprotocol/environment';
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
ActionsDropdown,
|
||||
TradingDropdownCopyItem,
|
||||
@@ -27,7 +27,7 @@ export const AccountsActionsDropdown = ({
|
||||
}) => {
|
||||
const etherscanLink = useEtherscanLink();
|
||||
const openAssetDialog = useAssetDetailsDialogStore((store) => store.open);
|
||||
const t = useT();
|
||||
|
||||
return (
|
||||
<ActionsDropdown>
|
||||
<TradingDropdownItem
|
||||
|
||||
@@ -6,18 +6,22 @@ import {
|
||||
makeDerivedDataProvider,
|
||||
} from '@vegaprotocol/data-provider';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { type Market } from '@vegaprotocol/markets';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import produce from 'immer';
|
||||
import { type IterableElement } from 'type-fest';
|
||||
|
||||
import {
|
||||
AccountEventsDocument,
|
||||
AccountsDocument,
|
||||
} from './__generated__/Accounts';
|
||||
|
||||
import type { IterableElement } from 'type-fest';
|
||||
import type {
|
||||
AccountFieldsFragment,
|
||||
AccountsQuery,
|
||||
AccountEventsSubscription,
|
||||
AccountsQueryVariables,
|
||||
} from './__generated__/Accounts';
|
||||
import { type Asset } from '@vegaprotocol/assets';
|
||||
import type { Asset } from '@vegaprotocol/assets';
|
||||
|
||||
const AccountType = Schema.AccountType;
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { useRef, memo, useState, useCallback } from 'react';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import {
|
||||
aggregatedAccountsDataProvider,
|
||||
aggregatedAccountDataProvider,
|
||||
} from './accounts-data-provider';
|
||||
import { type PinnedAsset } from './accounts-table';
|
||||
import type { PinnedAsset } from './accounts-table';
|
||||
import { AccountTable } from './accounts-table';
|
||||
import { Dialog } from '@vegaprotocol/ui-toolkit';
|
||||
import BreakdownTable from './breakdown-table';
|
||||
import { type useDataGridEvents } from '@vegaprotocol/datagrid';
|
||||
import type { useDataGridEvents } from '@vegaprotocol/datagrid';
|
||||
|
||||
const AccountBreakdown = ({
|
||||
assetId,
|
||||
@@ -22,7 +22,6 @@ const AccountBreakdown = ({
|
||||
partyId: string;
|
||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const gridRef = useRef<AgGridReact>(null);
|
||||
const { data } = useDataProvider({
|
||||
dataProvider: aggregatedAccountDataProvider,
|
||||
@@ -38,18 +37,18 @@ const AccountBreakdown = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className="m-auto flex h-[35vh] w-full flex-col"
|
||||
className="h-[35vh] w-full m-auto flex flex-col"
|
||||
data-testid="usage-breakdown"
|
||||
>
|
||||
<h1 className="mb-4 text-xl">
|
||||
<h1 className="text-xl mb-4">
|
||||
{data?.asset?.symbol} {t('usage breakdown')}
|
||||
</h1>
|
||||
{data && (
|
||||
<p className="mb-2 text-sm">
|
||||
{t('You have {{value}} {{symbol}} in total.', {
|
||||
value: addDecimalsFormatNumber(data.total, data.asset.decimals),
|
||||
symbol: data.asset.symbol,
|
||||
})}
|
||||
{t('You have %s %s in total.', [
|
||||
addDecimalsFormatNumber(data.total, data.asset.decimals),
|
||||
data.asset.symbol,
|
||||
])}
|
||||
</p>
|
||||
)}
|
||||
<BreakdownTable
|
||||
@@ -119,7 +118,6 @@ export const AccountManager = ({
|
||||
onMarketClick,
|
||||
gridProps,
|
||||
}: AccountManagerProps) => {
|
||||
const t = useT();
|
||||
const [breakdownAssetId, setBreakdownAssetId] = useState<string>();
|
||||
const { data, error } = useDataProvider({
|
||||
dataProvider: aggregatedAccountsDataProvider,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
isNumeric,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
@@ -96,7 +96,6 @@ export const AccountTable = ({
|
||||
pinnedAsset,
|
||||
...props
|
||||
}: AccountTableProps) => {
|
||||
const t = useT();
|
||||
const pinnedRow = useMemo(() => {
|
||||
if (!pinnedAsset) {
|
||||
return;
|
||||
@@ -192,7 +191,7 @@ export const AccountTable = ({
|
||||
<>
|
||||
<span className="underline">{valueFormatted}</span>
|
||||
<span className="inline-block ml-2 w-14 text-muted">
|
||||
{(0).toFixed(2)}%
|
||||
{t('0.00%')}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
@@ -311,7 +310,6 @@ export const AccountTable = ({
|
||||
onClickTransfer,
|
||||
isReadOnly,
|
||||
showDepositButton,
|
||||
t,
|
||||
]);
|
||||
|
||||
const data = rowData?.filter((data) => data.asset.id !== pinnedAsset?.id);
|
||||
|
||||
@@ -3,14 +3,14 @@ import {
|
||||
addDecimalsFormatNumber,
|
||||
addDecimalsFormatNumberQuantum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Intent, TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
|
||||
import { type AgGridReact, type AgGridReactProps } from 'ag-grid-react';
|
||||
import { type AccountFields } from './accounts-data-provider';
|
||||
import type { AgGridReact, AgGridReactProps } from 'ag-grid-react';
|
||||
import type { AccountFields } from './accounts-data-provider';
|
||||
import { AccountTypeMapping } from '@vegaprotocol/types';
|
||||
import {
|
||||
type VegaValueFormatterParams,
|
||||
type VegaICellRendererParams,
|
||||
import type {
|
||||
VegaValueFormatterParams,
|
||||
VegaICellRendererParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { ProgressBarCell } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid, PriceCell } from '@vegaprotocol/datagrid';
|
||||
@@ -31,7 +31,6 @@ interface BreakdownTableProps extends AgGridReactProps {
|
||||
|
||||
const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
||||
({ data }, ref) => {
|
||||
const t = useT();
|
||||
const coldefs = useMemo(() => {
|
||||
const defs: ColDef[] = [
|
||||
{
|
||||
@@ -54,7 +53,7 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
t('None')
|
||||
'None'
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -127,7 +126,7 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
||||
},
|
||||
];
|
||||
return defs;
|
||||
}, [t]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AgGrid
|
||||
|
||||
@@ -7,10 +7,12 @@ import {
|
||||
import {
|
||||
MarginsSubscriptionDocument,
|
||||
MarginsDocument,
|
||||
type MarginsQuery,
|
||||
type MarginFieldsFragment,
|
||||
type MarginsSubscriptionSubscription,
|
||||
type MarginsQueryVariables,
|
||||
} from './__generated__/Margins';
|
||||
import type {
|
||||
MarginsQuery,
|
||||
MarginFieldsFragment,
|
||||
MarginsSubscriptionSubscription,
|
||||
MarginsQueryVariables,
|
||||
} from './__generated__/Margins';
|
||||
|
||||
const update = (
|
||||
|
||||
@@ -4,10 +4,9 @@ import { Tooltip, ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { marketMarginDataProvider } from './margin-data-provider';
|
||||
import { useAssetsMapProvider } from '@vegaprotocol/assets';
|
||||
import { useT, ns } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useAccountBalance } from './use-account-balance';
|
||||
import { useMarketAccountBalance } from './use-market-account-balance';
|
||||
import { Trans } from 'react-i18next';
|
||||
|
||||
const MarginHealthChartTooltipRow = ({
|
||||
label,
|
||||
@@ -59,7 +58,6 @@ export const MarginHealthChartTooltip = ({
|
||||
decimals: number;
|
||||
marginAccountBalance?: string;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const tooltipContent = [
|
||||
<MarginHealthChartTooltipRow
|
||||
key={'maintenance'}
|
||||
@@ -171,23 +169,14 @@ export const MarginHealthChart = ({
|
||||
|
||||
return (
|
||||
<div data-testid="margin-health-chart">
|
||||
<Trans
|
||||
defaults="{{balance}} above <0>maintenance level</0>"
|
||||
components={[
|
||||
<ExternalLink href="https://docs.vega.xyz/testnet/concepts/trading-on-vega/positions-margin#margin-level-maintenance">
|
||||
maintenance level
|
||||
</ExternalLink>,
|
||||
]}
|
||||
values={{
|
||||
balance: addDecimalsFormatNumber(
|
||||
(
|
||||
BigInt(marginAccountBalance) - BigInt(maintenanceLevel)
|
||||
).toString(),
|
||||
decimals
|
||||
),
|
||||
}}
|
||||
ns={ns}
|
||||
/>
|
||||
{addDecimalsFormatNumber(
|
||||
(BigInt(marginAccountBalance) - BigInt(maintenanceLevel)).toString(),
|
||||
decimals
|
||||
)}{' '}
|
||||
{t('above')}{' '}
|
||||
<ExternalLink href="https://docs.vega.xyz/testnet/concepts/trading-on-vega/positions-margin#margin-level-maintenance">
|
||||
{t('maintenance level')}
|
||||
</ExternalLink>
|
||||
<Tooltip description={tooltip}>
|
||||
<div
|
||||
data-testid="margin-health-chart-track"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { truncateByChars } from '@vegaprotocol/utils';
|
||||
import { ns, useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
@@ -22,7 +21,6 @@ export const ALLOWED_ACCOUNTS = [
|
||||
];
|
||||
|
||||
export const TransferContainer = ({ assetId }: { assetId?: string }) => {
|
||||
const t = useT();
|
||||
const { pubKey, pubKeys } = useVegaWallet();
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.transfer_fee_factor,
|
||||
@@ -52,20 +50,16 @@ export const TransferContainer = ({ assetId }: { assetId?: string }) => {
|
||||
return (
|
||||
<>
|
||||
<p className="mb-4 text-sm" data-testid="transfer-intro-text">
|
||||
{pubKey ? (
|
||||
<Trans
|
||||
i18nKey="TRANSFER_FUNDS_TO_ANOTHER_KNOWN_VEGA_KEY"
|
||||
defaults="Transfer funds to another Vega key <0>{{pubKey}}</0>. If you are at all unsure, stop and seek advice."
|
||||
ns={ns}
|
||||
components={[<Lozenge className="font-mono">pubKey</Lozenge>]}
|
||||
values={{ pubKey: truncateByChars(pubKey || '') }}
|
||||
/>
|
||||
) : (
|
||||
t('TRANSFER_FUNDS_TO_ANOTHER_VEGA_KEY', {
|
||||
defaultValue:
|
||||
'Transfer funds to another Vega key. If you are at all unsure, stop and seek advice.',
|
||||
})
|
||||
{t('Transfer funds to another Vega key')}
|
||||
{pubKey && (
|
||||
<>
|
||||
{t(' from ')}
|
||||
<Lozenge className="font-mono">
|
||||
{truncateByChars(pubKey || '')}
|
||||
</Lozenge>
|
||||
</>
|
||||
)}
|
||||
{t('. If you are at all unsure, stop and seek advice.')}
|
||||
</p>
|
||||
<TransferForm
|
||||
pubKey={pubKey}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
addDecimalsFormatNumber,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
TradingFormGroup,
|
||||
TradingInput,
|
||||
@@ -66,7 +66,6 @@ export const TransferForm = ({
|
||||
accounts,
|
||||
minQuantumMultiple,
|
||||
}: TransferFormProps) => {
|
||||
const t = useT();
|
||||
const {
|
||||
control,
|
||||
register,
|
||||
@@ -301,7 +300,7 @@ export const TransferForm = ({
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
<TradingFormGroup label={t('To Vega key')} labelFor="toVegaKey">
|
||||
<TradingFormGroup label="To Vega key" labelFor="toVegaKey">
|
||||
<AddressField
|
||||
onChange={() => {
|
||||
setValue('toVegaKey', '');
|
||||
@@ -318,10 +317,7 @@ export const TransferForm = ({
|
||||
{t('Please select')}
|
||||
</option>
|
||||
{pubKeys?.map((pk) => {
|
||||
const text =
|
||||
pk === pubKey
|
||||
? t('Current key: {{pubKey}}', { pubKey: pk }) + pk
|
||||
: pk;
|
||||
const text = pk === pubKey ? t('Current key: ') + pk : pk;
|
||||
|
||||
return (
|
||||
<option key={pk} value={pk}>
|
||||
@@ -355,7 +351,7 @@ export const TransferForm = ({
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
<TradingFormGroup label={t('Amount')} labelFor="amount">
|
||||
<TradingFormGroup label="Amount" labelFor="amount">
|
||||
<TradingInput
|
||||
id="amount"
|
||||
autoComplete="off"
|
||||
@@ -477,7 +473,6 @@ export const TransferFee = ({
|
||||
fee?: string;
|
||||
decimals?: number;
|
||||
}) => {
|
||||
const t = useT();
|
||||
if (!feeFactor || !amount || !transferAmount || !fee) return null;
|
||||
if (
|
||||
isNaN(Number(feeFactor)) ||
|
||||
@@ -495,8 +490,8 @@ export const TransferFee = ({
|
||||
<div className="flex flex-wrap items-center justify-between gap-1">
|
||||
<Tooltip
|
||||
description={t(
|
||||
`The transfer fee is set by the network parameter transfer.fee.factor, currently set to {{feeFactor}}`,
|
||||
{ feeFactor }
|
||||
`The transfer fee is set by the network parameter transfer.fee.factor, currently set to %s`,
|
||||
[feeFactor]
|
||||
)}
|
||||
>
|
||||
<div>{t('Transfer fee')}</div>
|
||||
@@ -551,7 +546,6 @@ export const AddressField = ({
|
||||
mode,
|
||||
onChange,
|
||||
}: AddressInputProps) => {
|
||||
const t = useT();
|
||||
const isInput = mode === 'input';
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
export const ns = 'accounts';
|
||||
export const useT = () => useTranslation(ns).t;
|
||||
@@ -1,21 +1,6 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
import { defaultFallbackInView } from 'react-intersection-observer';
|
||||
import { locales } from '@vegaprotocol/i18n';
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
defaultFallbackInView(true);
|
||||
global.ResizeObserver = ResizeObserver;
|
||||
|
||||
// Set up i18n instance so that components have the correct default
|
||||
// en translations
|
||||
i18n.use(initReactI18next).init({
|
||||
// we init with resources
|
||||
resources: locales,
|
||||
fallbackLng: 'en',
|
||||
ns: ['accounts'],
|
||||
defaultNS: 'accounts',
|
||||
});
|
||||
|
||||
global.ResizeObserver = ResizeObserver;
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { makeDataProvider, useDataProvider } from '@vegaprotocol/data-provider';
|
||||
|
||||
import {
|
||||
type AssetQuery,
|
||||
type AssetQueryVariables,
|
||||
type AssetFieldsFragment,
|
||||
import type {
|
||||
AssetQuery,
|
||||
AssetFieldsFragment,
|
||||
AssetQueryVariables,
|
||||
} from './__generated__/Asset';
|
||||
import { AssetDocument } from './__generated__/Asset';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
@@ -56,7 +56,6 @@ export const AssetDetailsDialog = ({
|
||||
onChange,
|
||||
asJson = false,
|
||||
}: AssetDetailsDialogProps) => {
|
||||
const t = useT();
|
||||
const { data: asset } = useAssetDataProvider(assetId);
|
||||
|
||||
const assetSymbol = asset?.symbol || '';
|
||||
@@ -78,7 +77,7 @@ export const AssetDetailsDialog = ({
|
||||
</div>
|
||||
);
|
||||
const title = asset
|
||||
? t('Asset details - {{symbol}}', asset)
|
||||
? t(`Asset details - ${asset.symbol}`)
|
||||
: t('Asset not found');
|
||||
|
||||
return (
|
||||
@@ -101,8 +100,8 @@ export const AssetDetailsDialog = ({
|
||||
{content}
|
||||
<p className="my-4 text-xs">
|
||||
{t(
|
||||
'There is 1 unit of the settlement asset ({{assetSymbol}}) to every 1 quote unit.',
|
||||
{ assetSymbol }
|
||||
'There is 1 unit of the settlement asset (%s) to every 1 quote unit.',
|
||||
[assetSymbol]
|
||||
)}
|
||||
</p>
|
||||
<div className="w-1/4">
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { render, screen, renderHook } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { Asset } from './asset-data-provider';
|
||||
import {
|
||||
AssetDetail,
|
||||
AssetDetailsTable,
|
||||
useRows,
|
||||
rows,
|
||||
testId,
|
||||
} from './asset-details-table';
|
||||
import { generateBuiltinAsset, generateERC20Asset } from './test-helpers';
|
||||
@@ -67,8 +67,6 @@ describe('AssetDetailsTable', () => {
|
||||
it.each(cases)(
|
||||
"displays the available asset's data of %p with correct labels",
|
||||
async (_type, asset, details) => {
|
||||
const { result } = renderHook(() => useRows());
|
||||
const rows = result.current;
|
||||
render(<AssetDetailsTable asset={asset} />);
|
||||
for (const detail of details) {
|
||||
expect(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EtherscanLink } from '@vegaprotocol/environment';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
import type { KeyValueTableRowProps } from '@vegaprotocol/ui-toolkit';
|
||||
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
KeyValueTableRow,
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useMemo, type ReactNode } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { Asset } from './asset-data-provider';
|
||||
import { WITHDRAW_THRESHOLD_TOOLTIP_TEXT } from './constants';
|
||||
|
||||
@@ -52,208 +52,183 @@ const num = (asset: Asset, n: string | undefined | null) => {
|
||||
return addDecimalsFormatNumber(n, asset.decimals);
|
||||
};
|
||||
|
||||
export const useRows = () => {
|
||||
const t = useT();
|
||||
const AssetTypeMapping = useAssetTypeMapping();
|
||||
const AssetStatusMapping = useAssetStatusMapping();
|
||||
return useMemo<Rows>(
|
||||
() => [
|
||||
{
|
||||
key: AssetDetail.ID,
|
||||
label: t('ID'),
|
||||
tooltip: '',
|
||||
value: (asset) => (
|
||||
<>
|
||||
{truncateMiddle(asset.id)}{' '}
|
||||
<CopyWithTooltip text={asset.id}>
|
||||
<button title={t('Copy id to clipboard')}>
|
||||
<VegaIcon size={14} name={VegaIconNames.COPY} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.TYPE,
|
||||
label: t('Type'),
|
||||
tooltip: '',
|
||||
value: (asset) => AssetTypeMapping[asset.source.__typename].value,
|
||||
valueTooltip: (asset) =>
|
||||
AssetTypeMapping[asset.source.__typename].tooltip,
|
||||
},
|
||||
{
|
||||
key: AssetDetail.NAME,
|
||||
label: t('Name'),
|
||||
tooltip: '',
|
||||
value: (asset) => asset.name,
|
||||
},
|
||||
{
|
||||
key: AssetDetail.SYMBOL,
|
||||
label: t('Symbol'),
|
||||
tooltip: '',
|
||||
value: (asset) => asset.symbol,
|
||||
},
|
||||
{
|
||||
key: AssetDetail.DECIMALS,
|
||||
label: t('Decimals'),
|
||||
tooltip: t('Number of decimal / precision handled by this asset'),
|
||||
value: (asset) => asset.decimals.toString(),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.QUANTUM,
|
||||
label: t('Quantum'),
|
||||
tooltip: t('The minimum economically meaningful amount of the asset'),
|
||||
value: (asset) => num(asset, asset.quantum),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.STATUS,
|
||||
label: t('Status'),
|
||||
tooltip: t('The status of the asset in the Vega network'),
|
||||
value: (asset) => AssetStatusMapping[asset.status].value,
|
||||
valueTooltip: (asset) => AssetStatusMapping[asset.status].tooltip,
|
||||
},
|
||||
{
|
||||
key: AssetDetail.CONTRACT_ADDRESS,
|
||||
label: t('Contract address'),
|
||||
tooltip: t(
|
||||
'The address of the contract for the token, on the ethereum network'
|
||||
),
|
||||
value: (asset) => {
|
||||
if (asset.source.__typename !== 'ERC20') {
|
||||
return;
|
||||
}
|
||||
export const rows: Rows = [
|
||||
{
|
||||
key: AssetDetail.ID,
|
||||
label: t('ID'),
|
||||
tooltip: '',
|
||||
value: (asset) => (
|
||||
<>
|
||||
{truncateMiddle(asset.id)}{' '}
|
||||
<CopyWithTooltip text={asset.id}>
|
||||
<button title={t('Copy id to clipboard')}>
|
||||
<VegaIcon size={14} name={VegaIconNames.COPY} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.TYPE,
|
||||
label: t('Type'),
|
||||
tooltip: '',
|
||||
value: (asset) => AssetTypeMapping[asset.source.__typename].value,
|
||||
valueTooltip: (asset) => AssetTypeMapping[asset.source.__typename].tooltip,
|
||||
},
|
||||
{
|
||||
key: AssetDetail.NAME,
|
||||
label: t('Name'),
|
||||
tooltip: '',
|
||||
value: (asset) => asset.name,
|
||||
},
|
||||
{
|
||||
key: AssetDetail.SYMBOL,
|
||||
label: t('Symbol'),
|
||||
tooltip: '',
|
||||
value: (asset) => asset.symbol,
|
||||
},
|
||||
{
|
||||
key: AssetDetail.DECIMALS,
|
||||
label: t('Decimals'),
|
||||
tooltip: t('Number of decimal / precision handled by this asset'),
|
||||
value: (asset) => asset.decimals.toString(),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.QUANTUM,
|
||||
label: t('Quantum'),
|
||||
tooltip: t('The minimum economically meaningful amount of the asset'),
|
||||
value: (asset) => num(asset, asset.quantum),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.STATUS,
|
||||
label: t('Status'),
|
||||
tooltip: t('The status of the asset in the Vega network'),
|
||||
value: (asset) => AssetStatusMapping[asset.status].value,
|
||||
valueTooltip: (asset) => AssetStatusMapping[asset.status].tooltip,
|
||||
},
|
||||
{
|
||||
key: AssetDetail.CONTRACT_ADDRESS,
|
||||
label: t('Contract address'),
|
||||
tooltip: t(
|
||||
'The address of the contract for the token, on the ethereum network'
|
||||
),
|
||||
value: (asset) => {
|
||||
if (asset.source.__typename !== 'ERC20') {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<EtherscanLink address={asset.source.contractAddress}>
|
||||
{truncateMiddle(asset.source.contractAddress)}
|
||||
</EtherscanLink>{' '}
|
||||
<CopyWithTooltip text={asset.source.contractAddress}>
|
||||
<button title={t('Copy address to clipboard')}>
|
||||
<VegaIcon size={14} name={VegaIconNames.COPY} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: AssetDetail.WITHDRAWAL_THRESHOLD,
|
||||
label: t('Withdrawal threshold'),
|
||||
tooltip: t('WITHDRAW_THRESHOLD_TOOLTIP_TEXT', {
|
||||
defaultValue: WITHDRAW_THRESHOLD_TOOLTIP_TEXT,
|
||||
}),
|
||||
value: (asset) =>
|
||||
num(asset, (asset.source as Schema.ERC20).withdrawThreshold),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.LIFETIME_LIMIT,
|
||||
label: t('Lifetime limit'),
|
||||
tooltip: t(
|
||||
'The lifetime deposit limit per address. Note: this is a temporary measure that can be changed or removed through governance'
|
||||
),
|
||||
value: (asset) =>
|
||||
num(asset, (asset.source as Schema.ERC20).lifetimeLimit),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.MAX_FAUCET_AMOUNT_MINT,
|
||||
label: t('Max faucet amount'),
|
||||
tooltip: t(
|
||||
'Maximum amount that can be requested by a party through the built-in asset faucet at a time'
|
||||
),
|
||||
value: (asset) =>
|
||||
num(asset, (asset.source as Schema.BuiltinAsset).maxFaucetAmountMint),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.INFRASTRUCTURE_FEE_ACCOUNT_BALANCE,
|
||||
label: t('Infrastructure fee account balance'),
|
||||
tooltip: t('The infrastructure fee account in this asset'),
|
||||
value: (asset) => num(asset, asset.infrastructureFeeAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.GLOBAL_REWARD_POOL_ACCOUNT_BALANCE,
|
||||
label: t('Global reward pool account balance'),
|
||||
tooltip: t('The global rewards acquired in this asset'),
|
||||
value: (asset) => num(asset, asset.globalRewardPoolAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.MAKER_PAID_FEES_ACCOUNT_BALANCE,
|
||||
label: t('Maker paid fees account balance'),
|
||||
tooltip: t(
|
||||
'The rewards acquired based on the fees paid to makers in this asset'
|
||||
),
|
||||
value: (asset) => num(asset, asset.takerFeeRewardAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.MAKER_RECEIVED_FEES_ACCOUNT_BALANCE,
|
||||
label: t('Maker received fees account balance'),
|
||||
tooltip: t(
|
||||
'The rewards acquired based on fees received for being a maker on trades'
|
||||
),
|
||||
value: (asset) => num(asset, asset.makerFeeRewardAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.LP_FEE_REWARD_ACCOUNT_BALANCE,
|
||||
label: t('Liquidity provision fee reward account balance'),
|
||||
tooltip: t(
|
||||
'The rewards acquired based on the liquidity provision fees in this asset'
|
||||
),
|
||||
value: (asset) => num(asset, asset.lpFeeRewardAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.MARKET_PROPOSER_REWARD_ACCOUNT_BALANCE,
|
||||
label: t('Market proposer reward account balance'),
|
||||
tooltip: t(
|
||||
'The rewards acquired based on the market proposer reward in this asset'
|
||||
),
|
||||
value: (asset) =>
|
||||
num(asset, asset.marketProposerRewardAccount?.balance),
|
||||
},
|
||||
],
|
||||
[t, AssetTypeMapping, AssetStatusMapping]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<EtherscanLink address={asset.source.contractAddress}>
|
||||
{truncateMiddle(asset.source.contractAddress)}
|
||||
</EtherscanLink>{' '}
|
||||
<CopyWithTooltip text={asset.source.contractAddress}>
|
||||
<button title={t('Copy address to clipboard')}>
|
||||
<VegaIcon size={14} name={VegaIconNames.COPY} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: AssetDetail.WITHDRAWAL_THRESHOLD,
|
||||
label: t('Withdrawal threshold'),
|
||||
tooltip: WITHDRAW_THRESHOLD_TOOLTIP_TEXT,
|
||||
value: (asset) =>
|
||||
num(asset, (asset.source as Schema.ERC20).withdrawThreshold),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.LIFETIME_LIMIT,
|
||||
label: t('Lifetime limit'),
|
||||
tooltip: t(
|
||||
'The lifetime deposit limit per address. Note: this is a temporary measure that can be changed or removed through governance'
|
||||
),
|
||||
value: (asset) => num(asset, (asset.source as Schema.ERC20).lifetimeLimit),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.MAX_FAUCET_AMOUNT_MINT,
|
||||
label: t('Max faucet amount'),
|
||||
tooltip: t(
|
||||
'Maximum amount that can be requested by a party through the built-in asset faucet at a time'
|
||||
),
|
||||
value: (asset) =>
|
||||
num(asset, (asset.source as Schema.BuiltinAsset).maxFaucetAmountMint),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.INFRASTRUCTURE_FEE_ACCOUNT_BALANCE,
|
||||
label: t('Infrastructure fee account balance'),
|
||||
tooltip: t('The infrastructure fee account in this asset'),
|
||||
value: (asset) => num(asset, asset.infrastructureFeeAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.GLOBAL_REWARD_POOL_ACCOUNT_BALANCE,
|
||||
label: t('Global reward pool account balance'),
|
||||
tooltip: t('The global rewards acquired in this asset'),
|
||||
value: (asset) => num(asset, asset.globalRewardPoolAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.MAKER_PAID_FEES_ACCOUNT_BALANCE,
|
||||
label: t('Maker paid fees account balance'),
|
||||
tooltip: t(
|
||||
'The rewards acquired based on the fees paid to makers in this asset'
|
||||
),
|
||||
value: (asset) => num(asset, asset.takerFeeRewardAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.MAKER_RECEIVED_FEES_ACCOUNT_BALANCE,
|
||||
label: t('Maker received fees account balance'),
|
||||
tooltip: t(
|
||||
'The rewards acquired based on fees received for being a maker on trades'
|
||||
),
|
||||
value: (asset) => num(asset, asset.makerFeeRewardAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.LP_FEE_REWARD_ACCOUNT_BALANCE,
|
||||
label: t('Liquidity provision fee reward account balance'),
|
||||
tooltip: t(
|
||||
'The rewards acquired based on the liquidity provision fees in this asset'
|
||||
),
|
||||
value: (asset) => num(asset, asset.lpFeeRewardAccount?.balance),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.MARKET_PROPOSER_REWARD_ACCOUNT_BALANCE,
|
||||
label: t('Market proposer reward account balance'),
|
||||
tooltip: t(
|
||||
'The rewards acquired based on the market proposer reward in this asset'
|
||||
),
|
||||
value: (asset) => num(asset, asset.marketProposerRewardAccount?.balance),
|
||||
},
|
||||
];
|
||||
|
||||
export const AssetStatusMapping: Mapping = {
|
||||
STATUS_ENABLED: {
|
||||
value: t('Enabled'),
|
||||
tooltip: t('Asset can be used on the Vega network'),
|
||||
},
|
||||
STATUS_PENDING_LISTING: {
|
||||
value: t('Pending listing'),
|
||||
tooltip: t('Asset needs to be added to the Ethereum bridge'),
|
||||
},
|
||||
STATUS_PROPOSED: {
|
||||
value: t('Proposed'),
|
||||
tooltip: t('Asset has been proposed to the network'),
|
||||
},
|
||||
STATUS_REJECTED: {
|
||||
value: t('Rejected'),
|
||||
tooltip: t('Asset has been rejected'),
|
||||
},
|
||||
};
|
||||
|
||||
export const useAssetStatusMapping = () => {
|
||||
const t = useT();
|
||||
return useMemo<Mapping>(
|
||||
() => ({
|
||||
STATUS_ENABLED: {
|
||||
value: t('Enabled'),
|
||||
tooltip: t('Asset can be used on the Vega network'),
|
||||
},
|
||||
STATUS_PENDING_LISTING: {
|
||||
value: t('Pending listing'),
|
||||
tooltip: t('Asset needs to be added to the Ethereum bridge'),
|
||||
},
|
||||
STATUS_PROPOSED: {
|
||||
value: t('Proposed'),
|
||||
tooltip: t('Asset has been proposed to the network'),
|
||||
},
|
||||
STATUS_REJECTED: {
|
||||
value: t('Rejected'),
|
||||
tooltip: t('Asset has been rejected'),
|
||||
},
|
||||
}),
|
||||
[t]
|
||||
);
|
||||
};
|
||||
|
||||
export const useAssetTypeMapping = () => {
|
||||
const t = useT();
|
||||
return useMemo<Mapping>(
|
||||
() => ({
|
||||
BuiltinAsset: {
|
||||
value: t('Builtin asset'),
|
||||
tooltip: t('A Vega builtin asset'),
|
||||
},
|
||||
ERC20: {
|
||||
value: t('ERC20'),
|
||||
tooltip: t('An asset originated from an Ethereum ERC20 Token'),
|
||||
},
|
||||
}),
|
||||
[t]
|
||||
);
|
||||
export const AssetTypeMapping: Mapping = {
|
||||
BuiltinAsset: {
|
||||
value: 'Builtin asset',
|
||||
tooltip: t('A Vega builtin asset'),
|
||||
},
|
||||
ERC20: {
|
||||
value: 'ERC20',
|
||||
tooltip: t('An asset originated from an Ethereum ERC20 Token'),
|
||||
},
|
||||
};
|
||||
|
||||
export const testId = (detail: AssetDetail, field: 'label' | 'value') =>
|
||||
@@ -273,7 +248,7 @@ export const AssetDetailsTable = ({
|
||||
? { className: 'break-all', title: value }
|
||||
: {};
|
||||
|
||||
const details = useRows().map((r) => ({
|
||||
const details = rows.map((r) => ({
|
||||
...r,
|
||||
value: r.value(asset),
|
||||
valueTooltip: r.valueTooltip?.(asset),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TradingOption, truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AssetFieldsFragment } from './__generated__/Asset';
|
||||
import classNames from 'classnames';
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
type AssetOptionProps = {
|
||||
@@ -15,9 +15,8 @@ export const Balance = ({
|
||||
}: {
|
||||
balance?: string;
|
||||
symbol: string;
|
||||
}) => {
|
||||
const t = useT();
|
||||
return balance ? (
|
||||
}) =>
|
||||
balance ? (
|
||||
<div className="mt-1 font-alpha" data-testid="asset-balance">
|
||||
{balance} {symbol}
|
||||
</div>
|
||||
@@ -26,7 +25,6 @@ export const Balance = ({
|
||||
{t('Fetching balance…')}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const AssetOption = ({ asset, balance }: AssetOptionProps) => {
|
||||
return (
|
||||
|
||||
@@ -3,9 +3,10 @@ import {
|
||||
makeDerivedDataProvider,
|
||||
} from '@vegaprotocol/data-provider';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { AssetsDocument, type AssetsQuery } from './__generated__/Assets';
|
||||
import { AssetsDocument } from './__generated__/Assets';
|
||||
import { AssetStatus } from '@vegaprotocol/types';
|
||||
import { type Asset } from './asset-data-provider';
|
||||
import type { AssetsQuery } from './__generated__/Assets';
|
||||
import type { Asset } from './asset-data-provider';
|
||||
import { DENY_LIST } from './constants';
|
||||
|
||||
export interface BuiltinAssetSource {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
export const WITHDRAW_THRESHOLD_TOOLTIP_TEXT =
|
||||
"The maximum you can withdraw instantly. There's no limit on the size of a withdrawal, but all withdrawals over the threshold will have a delay time added to them";
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export const WITHDRAW_THRESHOLD_TOOLTIP_TEXT = t(
|
||||
"The maximum you can withdraw instantly. There's no limit on the size of a withdrawal, but all withdrawals over the threshold will have a delay time added to them"
|
||||
);
|
||||
|
||||
// List of defunct and no longer used assets that were created for various testnets
|
||||
export const DENY_LIST: Record<string, string[]> = {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const useT = () => useTranslation('assets').t;
|
||||
@@ -6,12 +6,12 @@ import { useMemo } from 'react';
|
||||
import debounce from 'lodash/debounce';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
STUDY_SIZE,
|
||||
useCandlesChartSettings,
|
||||
} from './use-candles-chart-settings';
|
||||
import { useT } from './use-t';
|
||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
|
||||
export type CandlesChartContainerProps = {
|
||||
marketId: string;
|
||||
@@ -25,7 +25,6 @@ export const CandlesChartContainer = ({
|
||||
const client = useApolloClient();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { theme } = useThemeSwitcher();
|
||||
const t = useT();
|
||||
|
||||
const {
|
||||
interval,
|
||||
|
||||
@@ -20,10 +20,10 @@ import {
|
||||
TradingDropdownTrigger,
|
||||
Icon,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { type IconName } from '@blueprintjs/icons';
|
||||
import type { IconName } from '@blueprintjs/icons';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useCandlesChartSettings } from './use-candles-chart-settings';
|
||||
import { useT } from './use-t';
|
||||
|
||||
const chartTypeIcon = new Map<ChartType, IconName>([
|
||||
[ChartType.AREA, IconNames.TIMELINE_AREA_CHART],
|
||||
@@ -43,7 +43,6 @@ export const CandlesMenu = () => {
|
||||
setStudies,
|
||||
setOverlays,
|
||||
} = useCandlesChartSettings();
|
||||
const t = useT();
|
||||
const triggerClasses = 'text-xs';
|
||||
const contentAlign = 'end';
|
||||
const triggerButtonProps = { size: 'extra-small' } as const;
|
||||
@@ -54,10 +53,7 @@ export const CandlesMenu = () => {
|
||||
trigger={
|
||||
<TradingDropdownTrigger className={triggerClasses}>
|
||||
<TradingButton {...triggerButtonProps}>
|
||||
{t('Interval: {{interval}}', {
|
||||
replace: { interval: intervalLabels[interval] },
|
||||
nsSeparator: '|',
|
||||
})}
|
||||
{t(`Interval: ${intervalLabels[interval]}`)}
|
||||
</TradingButton>
|
||||
</TradingDropdownTrigger>
|
||||
}
|
||||
|
||||
@@ -1,33 +1,29 @@
|
||||
import { type ApolloClient } from '@apollo/client';
|
||||
import { type Duration } from 'date-fns';
|
||||
import type { ApolloClient } from '@apollo/client';
|
||||
import type { Duration } from 'date-fns';
|
||||
import {
|
||||
add,
|
||||
differenceInDays,
|
||||
differenceInHours,
|
||||
differenceInMinutes,
|
||||
} from 'date-fns';
|
||||
import {
|
||||
type Candle,
|
||||
type DataSource,
|
||||
type PriceMonitoringBounds,
|
||||
} from 'pennant';
|
||||
import type { Candle, DataSource, PriceMonitoringBounds } from 'pennant';
|
||||
import { Interval as PennantInterval } from 'pennant';
|
||||
|
||||
import { addDecimal } from '@vegaprotocol/utils';
|
||||
import {
|
||||
ChartDocument,
|
||||
type ChartQuery,
|
||||
type ChartQueryVariables,
|
||||
} from './__generated__/Chart';
|
||||
import { ChartDocument } from './__generated__/Chart';
|
||||
import type { ChartQuery, ChartQueryVariables } from './__generated__/Chart';
|
||||
import {
|
||||
CandlesDocument,
|
||||
CandlesEventsDocument,
|
||||
type CandlesQuery,
|
||||
type CandlesQueryVariables,
|
||||
type CandlesEventsSubscription,
|
||||
type CandlesEventsSubscriptionVariables,
|
||||
type CandleFieldsFragment,
|
||||
} from './__generated__/Candles';
|
||||
import { type Subscription } from 'zen-observable-ts';
|
||||
import type {
|
||||
CandlesQuery,
|
||||
CandlesQueryVariables,
|
||||
CandleFieldsFragment,
|
||||
CandlesEventsSubscription,
|
||||
CandlesEventsSubscriptionVariables,
|
||||
} from './__generated__/Candles';
|
||||
import type { Subscription } from 'zen-observable-ts';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
|
||||
const INTERVAL_TO_PENNANT_MAP = {
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
export const useT = () => useTranslation('candles-chart').t;
|
||||
@@ -3,29 +3,29 @@ import {
|
||||
makeDerivedDataProvider,
|
||||
defaultAppend,
|
||||
} from './generic-data-provider';
|
||||
import {
|
||||
type CombineDerivedData,
|
||||
type CombineDerivedDelta,
|
||||
type CombineInsertionData,
|
||||
type UpdateCallback,
|
||||
type Update,
|
||||
type Query,
|
||||
type PageInfo,
|
||||
type Reload,
|
||||
type Load,
|
||||
import type {
|
||||
CombineDerivedData,
|
||||
CombineDerivedDelta,
|
||||
CombineInsertionData,
|
||||
Query,
|
||||
UpdateCallback,
|
||||
Update,
|
||||
PageInfo,
|
||||
Reload,
|
||||
Load,
|
||||
} from './generic-data-provider';
|
||||
import {
|
||||
type FetchResult,
|
||||
type SubscriptionOptions,
|
||||
type OperationVariables,
|
||||
type ApolloQueryResult,
|
||||
type QueryOptions,
|
||||
type ApolloClient,
|
||||
import type {
|
||||
ApolloClient,
|
||||
FetchResult,
|
||||
SubscriptionOptions,
|
||||
OperationVariables,
|
||||
ApolloQueryResult,
|
||||
QueryOptions,
|
||||
} from '@apollo/client';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import type { GraphQLErrors } from '@apollo/client/errors';
|
||||
import { GraphQLError } from 'graphql';
|
||||
import { Subscription, Observable } from 'zen-observable-ts';
|
||||
import type { Subscription, Observable } from 'zen-observable-ts';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
|
||||
type Item = {
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import type { IGetRowsParams } from 'ag-grid-community';
|
||||
import {
|
||||
type Edge,
|
||||
type Load,
|
||||
type DerivedPart,
|
||||
type Node,
|
||||
} from './generic-data-provider';
|
||||
import type { Load, DerivedPart, Node, Edge } from './generic-data-provider';
|
||||
import type { MutableRefObject } from 'react';
|
||||
|
||||
const getLastRow = (
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { renderHook, act } from '@testing-library/react';
|
||||
import {
|
||||
useDataProvider,
|
||||
useThrottledDataProvider,
|
||||
type useDataProviderParams,
|
||||
} from './use-data-provider';
|
||||
import { type Subscribe, type UpdateCallback } from './generic-data-provider';
|
||||
import { useDataProvider, useThrottledDataProvider } from './use-data-provider';
|
||||
import type { useDataProviderParams } from './use-data-provider';
|
||||
import type { Subscribe, UpdateCallback } from './generic-data-provider';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
|
||||
type Data = number;
|
||||
|
||||
@@ -3,11 +3,11 @@ import throttle from 'lodash/throttle';
|
||||
import isEqualWith from 'lodash/isEqualWith';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import type { OperationVariables } from '@apollo/client';
|
||||
import {
|
||||
type UpdateCallback,
|
||||
type PageInfo,
|
||||
type Subscribe,
|
||||
type Load,
|
||||
import type {
|
||||
Subscribe,
|
||||
Load,
|
||||
UpdateCallback,
|
||||
PageInfo,
|
||||
} from './generic-data-provider';
|
||||
import { variablesIsEqualCustomizer } from './generic-data-provider';
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
export const useTranslation = () => ({
|
||||
t: (label: string, replacements?: Record<string, string>) => {
|
||||
const replace =
|
||||
replacements?.['replace'] && typeof replacements === 'object'
|
||||
? replacements?.['replace']
|
||||
: replacements;
|
||||
let translatedLabel = replacements?.['defaultValue'] || label;
|
||||
if (typeof replace === 'object' && replace !== null) {
|
||||
Object.keys(replace).forEach((key) => {
|
||||
translatedLabel = translatedLabel.replace(`{{${key}}}`, replace[key]);
|
||||
});
|
||||
}
|
||||
return translatedLabel;
|
||||
},
|
||||
});
|
||||
@@ -1,12 +1,14 @@
|
||||
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
|
||||
import { AgGridReact } from 'ag-grid-react';
|
||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import classNames from 'classnames';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { useT } from '../use-t';
|
||||
|
||||
const defaultProps: AgGridReactProps = {
|
||||
enableCellTextSelection: true,
|
||||
overlayLoadingTemplate: t('Loading...'),
|
||||
overlayNoRowsTemplate: t('No data'),
|
||||
suppressCellFocus: true,
|
||||
suppressColumnMoveAnimation: true,
|
||||
};
|
||||
@@ -24,7 +26,6 @@ export const AgGridThemed = ({
|
||||
style?: React.CSSProperties;
|
||||
gridRef?: React.ForwardedRef<AgGridReact>;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const { theme } = useThemeSwitcher();
|
||||
|
||||
const wrapperClasses = classNames('vega-ag-grid', 'w-full h-full', {
|
||||
@@ -37,8 +38,6 @@ export const AgGridThemed = ({
|
||||
<AgGridReact
|
||||
defaultColDef={defaultColDef}
|
||||
ref={gridRef}
|
||||
overlayLoadingTemplate={t('Loading...')}
|
||||
overlayNoRowsTemplate={t('No data')}
|
||||
{...defaultProps}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { forwardRef } from 'react';
|
||||
import { type AgGridReactProps, type AgGridReact } from 'ag-grid-react';
|
||||
import type { AgGridReactProps, AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridThemed } from './ag-grid-themed';
|
||||
|
||||
type Props = AgGridReactProps & {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { useT } from '../use-t';
|
||||
|
||||
interface OrderTypeCellProps {
|
||||
value?: Schema.OrderType;
|
||||
@@ -17,7 +17,6 @@ export const OrderTypeCell = ({
|
||||
onClick,
|
||||
}: OrderTypeCellProps) => {
|
||||
const id = order?.market?.id ?? '';
|
||||
const t = useT();
|
||||
|
||||
const label = useMemo(() => {
|
||||
if (!order) {
|
||||
@@ -26,9 +25,7 @@ export const OrderTypeCell = ({
|
||||
if (!value) return '-';
|
||||
|
||||
if (order?.icebergOrder) {
|
||||
return t('{{orderType}} (Iceberg)', {
|
||||
orderType: Schema.OrderTypeMapping[value],
|
||||
});
|
||||
return t('%s (Iceberg)', [Schema.OrderTypeMapping[value]]);
|
||||
}
|
||||
|
||||
if (order?.peggedOrder) {
|
||||
@@ -40,18 +37,14 @@ export const OrderTypeCell = ({
|
||||
order.peggedOrder?.offset,
|
||||
order.market.decimalPlaces
|
||||
);
|
||||
return t('{{reference}} {{side}} {{offset}} Peg limit', {
|
||||
reference,
|
||||
side,
|
||||
offset,
|
||||
});
|
||||
return t('%s %s %s Peg limit', [reference, side, offset]);
|
||||
}
|
||||
|
||||
if (order?.liquidityProvision) {
|
||||
return t('Liquidity provision');
|
||||
}
|
||||
return Schema.OrderTypeMapping[value];
|
||||
}, [order, value, t]);
|
||||
}, [order, value]);
|
||||
|
||||
const handleOnClick = useCallback(
|
||||
(ev: MouseEvent<HTMLButtonElement>) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ChangeEvent } from 'react';
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import { type DateRange } from '@vegaprotocol/types';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react';
|
||||
import type { IDoesFilterPassParams, IFilterParams } from 'ag-grid-community';
|
||||
import {
|
||||
@@ -14,12 +14,12 @@ import {
|
||||
isValid,
|
||||
} from 'date-fns';
|
||||
import { formatForInput } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { TradingInputError } from '@vegaprotocol/ui-toolkit';
|
||||
import { useT } from '../use-t';
|
||||
|
||||
const defaultValue: DateRange = {};
|
||||
const defaultValue: Schema.DateRange = {};
|
||||
export interface DateRangeFilterProps extends IFilterParams {
|
||||
defaultValue?: DateRange;
|
||||
defaultValue?: Schema.DateRange;
|
||||
maxSubDays?: number;
|
||||
maxNextDays?: number;
|
||||
maxDaysRange?: number;
|
||||
@@ -27,10 +27,9 @@ export interface DateRangeFilterProps extends IFilterParams {
|
||||
|
||||
export const DateRangeFilter = forwardRef(
|
||||
(props: DateRangeFilterProps, ref) => {
|
||||
const t = useT();
|
||||
const defaultDates = props?.defaultValue || defaultValue;
|
||||
const [value, setValue] = useState<DateRange>(defaultDates);
|
||||
const valueRef = useRef<DateRange>(value);
|
||||
const [value, setValue] = useState<Schema.DateRange>(defaultDates);
|
||||
const valueRef = useRef<Schema.DateRange>(value);
|
||||
const [error, setError] = useState<string>('');
|
||||
const [minStartDate, maxStartDate, minEndDate, maxEndDate] = useMemo(() => {
|
||||
const minStartDate =
|
||||
@@ -106,24 +105,26 @@ export const DateRangeFilter = forwardRef(
|
||||
return { value: valueRef.current };
|
||||
},
|
||||
|
||||
setModel(model?: { value: DateRange } | null) {
|
||||
setModel(model?: { value: Schema.DateRange } | null) {
|
||||
valueRef.current =
|
||||
model?.value || props?.defaultValue || defaultValue;
|
||||
setValue(valueRef.current);
|
||||
},
|
||||
};
|
||||
});
|
||||
const validate = (name: string, timeValue: Date, update?: DateRange) => {
|
||||
const validate = (
|
||||
name: string,
|
||||
timeValue: Date,
|
||||
update?: Schema.DateRange
|
||||
) => {
|
||||
if (
|
||||
props.maxSubDays !== undefined &&
|
||||
isBefore(new Date(timeValue), subDays(Date.now(), props.maxSubDays + 1))
|
||||
) {
|
||||
setError(
|
||||
t(
|
||||
'The earliest data that can be queried is {{maxSubDays}} days ago.',
|
||||
{
|
||||
maxSubDays: String(props.maxSubDays),
|
||||
}
|
||||
'The earliest data that can be queried is %s days ago.',
|
||||
String(props.maxSubDays)
|
||||
)
|
||||
);
|
||||
return false;
|
||||
@@ -140,8 +141,8 @@ export const DateRangeFilter = forwardRef(
|
||||
) {
|
||||
setError(
|
||||
t(
|
||||
'The maximum time range that can be queried is {{maxDaysRange}} days.',
|
||||
{ maxDaysRange: String(props.maxDaysRange) }
|
||||
'The maximum time range that can be queried is %s days.',
|
||||
String(props.maxDaysRange)
|
||||
)
|
||||
);
|
||||
return false;
|
||||
@@ -208,7 +209,7 @@ export const DateRangeFilter = forwardRef(
|
||||
<div className="ag-filter-apply-panel">
|
||||
<fieldset className="ag-simple-filter-body-wrapper">
|
||||
<label className="block" key="start">
|
||||
<span className="mb-1 block">{t('Start')}</span>
|
||||
<span className="block mb-1">{t('Start')}</span>
|
||||
<input
|
||||
type="datetime-local"
|
||||
name="start"
|
||||
@@ -221,7 +222,7 @@ export const DateRangeFilter = forwardRef(
|
||||
</fieldset>
|
||||
<fieldset className="ag-simple-filter-body-wrapper">
|
||||
<label className="block" key="end">
|
||||
<span className="mb-1 block">{t('End')}</span>
|
||||
<span className="block mb-1">{t('End')}</span>
|
||||
<input
|
||||
type="datetime-local"
|
||||
name="end"
|
||||
|
||||
@@ -7,11 +7,10 @@ import {
|
||||
useRef,
|
||||
} from 'react';
|
||||
import type { IDoesFilterPassParams, IFilterParams } from 'ag-grid-community';
|
||||
import { useT } from '../use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export const SetFilter = forwardRef(
|
||||
(props: IFilterParams & { readonly?: boolean }, ref) => {
|
||||
const t = useT();
|
||||
const [value, setValue] = useState<string[]>([]);
|
||||
const valueRef = useRef(value);
|
||||
const { readonly } = props;
|
||||
|
||||
@@ -30,6 +30,15 @@ describe('Pagination', () => {
|
||||
expect(mockOnLoad).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('renders message for a single row', async () => {
|
||||
const mockOnLoad = jest.fn();
|
||||
const count = 1;
|
||||
render(<Pagination {...props} count={count} onLoad={mockOnLoad} />);
|
||||
expect(screen.getByText(`${count} row loaded`)).toBeInTheDocument();
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Load more' }));
|
||||
expect(mockOnLoad).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('renders the data rentention message', () => {
|
||||
render(<Pagination {...props} showRetentionMessage={true} />);
|
||||
expect(screen.getByText(/data node retention/)).toBeInTheDocument();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TradingButton as Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { useT } from './use-t';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export const Pagination = ({
|
||||
count,
|
||||
@@ -14,19 +14,16 @@ export const Pagination = ({
|
||||
hasDisplayedRows: boolean;
|
||||
showRetentionMessage: boolean;
|
||||
}) => {
|
||||
const t = useT();
|
||||
let rowMessage = '';
|
||||
|
||||
if (count && !pageInfo?.hasNextPage) {
|
||||
rowMessage = t('paginationAllLoaded', {
|
||||
replace: { count },
|
||||
defaultValue: 'All {{count}} rows loaded',
|
||||
});
|
||||
rowMessage = t('all %s rows loaded', count.toString());
|
||||
} else {
|
||||
rowMessage = t('paginationLoaded', {
|
||||
replace: { count },
|
||||
defaultValue: '{{count}} rows loaded',
|
||||
});
|
||||
if (count === 1) {
|
||||
rowMessage = t('%s row loaded', count.toString());
|
||||
} else {
|
||||
rowMessage = t('%s rows loaded', count.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useDataGridEvents } from './use-datagrid-events';
|
||||
import { AgGridThemed } from './ag-grid/ag-grid-themed';
|
||||
import type { MutableRefObject } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
|
||||
const gridProps = {
|
||||
rowData: [{ id: 1 }],
|
||||
@@ -17,7 +17,7 @@ const gridProps = {
|
||||
style: { width: 500, height: 300 },
|
||||
};
|
||||
const GRID_EVENT_DEBOUNCE_TIME = 300;
|
||||
let gridRef: MutableRefObject<AgGridReact | null> | undefined;
|
||||
let gridRef: MutableRefObject<AgGridReact | null>;
|
||||
function TestComponent({
|
||||
hookParams,
|
||||
}: {
|
||||
@@ -61,11 +61,11 @@ describe('useDataGridEvents', () => {
|
||||
|
||||
// column state was not updated, so the default width provided by the
|
||||
// col def should be set
|
||||
expect(gridRef?.current?.columnApi.getColumnState()[0].width).toEqual(
|
||||
expect(gridRef.current?.columnApi.getColumnState()[0].width).toEqual(
|
||||
gridProps.columnDefs[0].width
|
||||
);
|
||||
// no filters set
|
||||
expect(gridRef?.current?.api.getFilterModel()).toEqual({});
|
||||
expect(gridRef.current?.api.getFilterModel()).toEqual({});
|
||||
|
||||
// Set filter
|
||||
const idFilter = {
|
||||
@@ -74,7 +74,7 @@ describe('useDataGridEvents', () => {
|
||||
type: 'equals',
|
||||
};
|
||||
await act(async () => {
|
||||
gridRef?.current?.api.setFilterModel({
|
||||
gridRef.current?.api.setFilterModel({
|
||||
id: idFilter,
|
||||
});
|
||||
});
|
||||
@@ -90,7 +90,7 @@ describe('useDataGridEvents', () => {
|
||||
},
|
||||
});
|
||||
callback.mockClear();
|
||||
expect(gridRef?.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
||||
expect(gridRef.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
||||
});
|
||||
|
||||
it('applies grid state on ready', async () => {
|
||||
@@ -110,8 +110,8 @@ describe('useDataGridEvents', () => {
|
||||
setup(initialState, jest.fn());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(gridRef?.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
||||
expect(gridRef?.current?.columnApi.getColumnState()[0]).toEqual(
|
||||
expect(gridRef.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
||||
expect(gridRef.current?.columnApi.getColumnState()[0]).toEqual(
|
||||
expect.objectContaining(colState)
|
||||
);
|
||||
});
|
||||
@@ -130,7 +130,7 @@ describe('useDataGridEvents', () => {
|
||||
|
||||
// Set col width multiple times
|
||||
await act(async () => {
|
||||
gridRef?.current?.columnApi.setColumnWidth('id', newWidth);
|
||||
gridRef.current?.columnApi.setColumnWidth('id', newWidth);
|
||||
});
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
@@ -150,13 +150,13 @@ describe('useDataGridEvents', () => {
|
||||
};
|
||||
|
||||
const { rerender } = setup(initialState, callback, ['id']);
|
||||
jest.spyOn(gridRef?.current?.columnApi, 'autoSizeColumns');
|
||||
jest.spyOn(gridRef.current?.columnApi, 'autoSizeColumns');
|
||||
rerender(<TestComponent hookParams={[initialState, callback, ['id']]} />);
|
||||
act(() => {
|
||||
gridRef?.current?.api.setRowData([{ id: 'test-id' }]);
|
||||
gridRef.current?.api.setRowData([{ id: 'test-id' }]);
|
||||
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
||||
});
|
||||
expect(gridRef?.current?.columnApi.autoSizeColumns).toHaveBeenCalledWith([
|
||||
expect(gridRef.current?.columnApi.autoSizeColumns).toHaveBeenCalledWith([
|
||||
'id',
|
||||
]);
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user