Compare commits

...
Author SHA1 Message Date
Edd b589ca1405 feat(explorer): add settlementasset option to priceinmarket component 2023-01-26 12:58:25 +00:00
mattrussell36 6362c022b5 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-26 12:06:16 +00:00
Bartłomiej Głownia a6118c14dd feat: fix EthTxCompletedToastContent (#2741) 2023-01-26 12:00:00 +00:00
Sam Keen d384fb35f1 feat(2396): token delegations pagination (#2575) 2023-01-26 10:20:26 +00:00
Ciaran McGhie 3ed3714e79 fix(#2216): lp-dashboard grab market close from metadata (#2564) 2023-01-26 09:58:39 +00:00
Matthew Russell 3893b26d30 fix: dropdown menu portals (#2740) 2023-01-26 09:52:49 +01:00
mattrussell36 1ba0ad234b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-26 06:07:07 +00:00
mattrussell36 9f6a5aac39 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-26 00:13:06 +00:00
57 changed files with 450 additions and 572 deletions
@@ -8,6 +8,9 @@ query ExplorerMarket($id: ID!) {
product {
... on Future {
quoteName
settlementAsset {
decimals
}
}
}
}
@@ -8,7 +8,7 @@ export type ExplorerMarketQueryVariables = Types.Exact<{
}>;
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } | null };
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null };
export const ExplorerMarketDocument = gql`
@@ -22,6 +22,9 @@ export const ExplorerMarketDocument = gql`
product {
... on Future {
quoteName
settlementAsset {
decimals
}
}
}
}
@@ -97,6 +97,10 @@ describe('Order TX Summary component', () => {
product: {
__typename: 'Future',
quoteName: 'TEST',
settlementAsset: {
__typeName: 'SettlementAsset',
decimals: 18,
},
},
},
},
@@ -3,61 +3,78 @@ import { MockedProvider } from '@apollo/client/testing';
import type { MockedResponse } from '@apollo/client/testing';
import { render } from '@testing-library/react';
import PriceInMarket from './price-in-market';
import type { DecimalSource } from './price-in-market';
import { ExplorerMarketDocument } from '../links/market-link/__generated__/Market';
function renderComponent(
price: string,
marketId: string,
mocks: MockedResponse[]
mocks: MockedResponse[],
decimalSource: DecimalSource = 'MARKET'
) {
return (
<MockedProvider mocks={mocks} addTypename={false}>
<MemoryRouter>
<PriceInMarket marketId={marketId} price={price} />
<PriceInMarket
marketId={marketId}
price={price}
decimalSource={decimalSource}
/>
</MemoryRouter>
</MockedProvider>
);
}
const fullMock = {
request: {
query: ExplorerMarketDocument,
variables: {
id: '123',
},
},
result: {
data: {
market: {
id: '123',
decimalPlaces: 2,
state: 'irrelevant-test-data',
tradableInstrument: {
instrument: {
name: 'test dai',
product: {
__typename: 'Future',
quoteName: 'dai',
settlementAsset: {
decimals: 18,
},
},
},
},
},
},
},
};
describe('Price in Market component', () => {
it('Renders the raw price when there is no market data', () => {
const res = render(renderComponent('100', '123', []));
expect(res.getByText('100')).toBeInTheDocument();
});
it('Renders the formatted price when market data is fetched', async () => {
const mock = {
request: {
query: ExplorerMarketDocument,
variables: {
id: '123',
},
},
result: {
data: {
market: {
id: '123',
decimalPlaces: 2,
state: 'irrelevant-test-data',
tradableInstrument: {
instrument: {
name: 'test dai',
product: {
__typename: 'Future',
quoteName: 'dai',
},
},
},
},
},
},
};
const res = render(renderComponent('100', '123', [mock]));
it('Renders the formatted price when market data is fetched, using market decimals by default', async () => {
const res = render(renderComponent('100', '123', [fullMock]));
expect(await res.findByText('1.00')).toBeInTheDocument();
expect(await res.findByText('dai')).toBeInTheDocument();
});
it('Renders the formatted price when market data is fetched, using settlement decimals', async () => {
const res = render(
renderComponent('100', '123', [fullMock], 'SETTLEMENT_ASSET')
);
expect(await res.findByText('0.0000000000000001')).toBeInTheDocument();
expect(await res.findByText('dai')).toBeInTheDocument();
});
it('Leaves the market id when the market is not found', async () => {
const mock = {
request: {
@@ -3,16 +3,23 @@ import isUndefined from 'lodash/isUndefined';
import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market';
import get from 'lodash/get';
export type DecimalSource = 'MARKET' | 'SETTLEMENT_ASSET';
export type PriceInMarketProps = {
marketId: string;
price: string;
decimalSource?: DecimalSource;
};
/**
* Given a market ID and a price it will fetch the market
* and format the price in that market's decimal places.
*/
const PriceInMarket = ({ marketId, price }: PriceInMarketProps) => {
const PriceInMarket = ({
marketId,
price,
decimalSource = 'MARKET',
}: PriceInMarketProps) => {
const { data } = useExplorerMarketQuery({
variables: { id: marketId },
fetchPolicy: 'cache-first',
@@ -20,8 +27,19 @@ const PriceInMarket = ({ marketId, price }: PriceInMarketProps) => {
let label = price;
if (data && data.market?.decimalPlaces) {
label = addDecimalsFormatNumber(price, data.market.decimalPlaces);
if (data) {
if (decimalSource === 'MARKET' && data.market?.decimalPlaces) {
label = addDecimalsFormatNumber(price, data.market.decimalPlaces);
} else if (
decimalSource === 'SETTLEMENT_ASSET' &&
data.market?.tradableInstrument.instrument.product.settlementAsset
) {
label = addDecimalsFormatNumber(
price,
data.market?.tradableInstrument.instrument.product.settlementAsset
.decimals
);
}
}
const suffix = get(
@@ -55,6 +55,7 @@ export const TxDetailsLiquidityAmendment = ({
<PriceInMarket
price={amendment.commitmentAmount}
marketId={marketId}
decimalSource="SETTLEMENT_ASSET"
/>
</TableCell>
</TableRow>
@@ -54,6 +54,7 @@ export const TxDetailsLiquiditySubmission = ({
<PriceInMarket
price={submission.commitmentAmount}
marketId={marketId}
decimalSource="SETTLEMENT_ASSET"
/>
</TableCell>
</TableRow>
@@ -10,7 +10,6 @@ import {
formatNumberPercentage,
t,
toBigNum,
getDateTimeFormat,
} from '@vegaprotocol/react-helpers';
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
import type * as Schema from '@vegaprotocol/types';
@@ -31,6 +30,7 @@ import { HealthBar } from '../../health-bar';
import { HealthDialog } from '../../health-dialog';
import { Status } from '../../status';
import { formatDistanceToNow } from 'date-fns';
import { getExpiryDate } from '@vegaprotocol/react-helpers';
export const MarketList = () => {
const { data, error, loading } = useMarketsLiquidity();
@@ -299,17 +299,20 @@ export const MarketList = () => {
/>
<AgGridColumn
headerName={t('Closing Time')}
field="proposal.terms.closingDatetime"
field="tradableInstrument.instrument.metadata.tags"
headerTooltip={t('Closing time of the market')}
valueFormatter={({
value,
}: VegaValueFormatterParams<
Market,
'proposal.terms.closingDatetime'
>) => {
return value
? getDateTimeFormat().format(new Date(value).getTime())
: '-';
data,
}: VegaValueFormatterParams<Market, ''>) => {
let expiry;
if (data?.tradableInstrument.instrument.metadata.tags) {
expiry = getExpiryDate(
data?.tradableInstrument.instrument.metadata.tags,
data?.marketTimestamps.close,
data?.state
);
}
return expiry ? expiry : '-';
}}
/>
</Grid>
+73 -29
View File
@@ -5,7 +5,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "86666.297",
"total_removed": "0",
"locked_amount": "74377.3343235149335839749",
"locked_amount": "74199.563434561395345826",
"deposits": [
{
"amount": "86666.297",
@@ -71,7 +71,7 @@
"tranche_end": "2023-06-01T00:00:00.000Z",
"total_added": "2500",
"total_removed": "0",
"locked_amount": "1734.125553266178",
"locked_amount": "1723.8413207163205",
"deposits": [
{
"amount": "2500",
@@ -450,7 +450,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "74309.47436445978496023",
"locked_amount": "74131.865669074416617715",
"deposits": [
{
"amount": "129999.45",
@@ -516,7 +516,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "62600",
"total_removed": "0",
"locked_amount": "37773.4128805175029",
"locked_amount": "37645.00705225773502",
"deposits": [
{
"amount": "10000",
@@ -709,7 +709,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000",
"total_removed": "0",
"locked_amount": "3208.826579147641",
"locked_amount": "3198.570522577372",
"deposits": [
{
"amount": "5000",
@@ -920,7 +920,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "97499.58",
"total_removed": "0",
"locked_amount": "16112.873733795746655318",
"locked_amount": "15938.65614862105375962",
"deposits": [
{
"amount": "97499.58",
@@ -953,7 +953,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "135173.4239508",
"total_removed": "98230.390980249184455396",
"locked_amount": "22023.516622497674397517810344",
"locked_amount": "21785.391260975192260443858312",
"deposits": [
{
"amount": "135173.4239508",
@@ -999,7 +999,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "32499.86",
"total_removed": "0",
"locked_amount": "6778.4077253618634870844",
"locked_amount": "6705.1173958556428760904",
"deposits": [
{
"amount": "32499.86",
@@ -1032,7 +1032,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "10833.29",
"total_removed": "0",
"locked_amount": "2206.3059384936688557712",
"locked_amount": "2182.4506474319168306297",
"deposits": [
{
"amount": "10833.29",
@@ -1065,7 +1065,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "22749.93",
"total_removed": "0",
"locked_amount": "8247.664367621075063898",
"locked_amount": "8158.48796164921464204",
"deposits": [
{
"amount": "6500",
@@ -1204,7 +1204,7 @@
"tranche_end": "2023-05-01T00:00:00.000Z",
"total_added": "22500",
"total_removed": "3539.640404325",
"locked_amount": "11839.76605662983325",
"locked_amount": "11746.696593001842",
"deposits": [
{
"amount": "7500",
@@ -1369,7 +1369,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "928642.9598472029154",
"locked_amount": "676287.4161622965221101968",
"locked_amount": "672308.21312078634624765",
"deposits": [
{
"amount": "1852091.69",
@@ -1721,7 +1721,7 @@
"tranche_end": "2023-02-01T00:00:00.000Z",
"total_added": "42500",
"total_removed": "24434.0787288",
"locked_amount": "1442.306857638887255",
"locked_amount": "1269.3752516103057225",
"deposits": [
{
"amount": "12500",
@@ -33096,8 +33096,8 @@
"tranche_start": "2022-03-05T00:00:00.000Z",
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "441714.6865497406814",
"locked_amount": "1063719.625100700820753200245",
"total_removed": "442882.3484327902809",
"locked_amount": "1057604.97543725296329993117",
"deposits": [
{
"amount": "1998.95815",
@@ -33276,6 +33276,11 @@
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0x63016a4e870bc38285eac8057aab58aa9fe896f1659f4f2e7e4e8de19c1202db"
},
{
"amount": "1167.6618830495995",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0xdd0c8931e8c9ec3205ab9e4cdbb30dd5a6f43253c388f2e05b5bb5fd847ed8fb"
},
{
"amount": "1906.7742941475005",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -33622,6 +33627,12 @@
"tranche_id": 1,
"tx": "0x63016a4e870bc38285eac8057aab58aa9fe896f1659f4f2e7e4e8de19c1202db"
},
{
"amount": "1167.6618830495995",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tranche_id": 1,
"tx": "0xdd0c8931e8c9ec3205ab9e4cdbb30dd5a6f43253c388f2e05b5bb5fd847ed8fb"
},
{
"amount": "1906.7742941475005",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -33870,8 +33881,8 @@
}
],
"total_tokens": "187637.95",
"withdrawn_tokens": "133256.984196977461",
"remaining_tokens": "54380.965803022539"
"withdrawn_tokens": "134424.6460800270605",
"remaining_tokens": "53213.3039199729395"
},
{
"address": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
@@ -34377,8 +34388,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "545472.50137003958740452",
"locked_amount": "9071569.0789202252235565659217193396309814",
"total_removed": "545536.65519596862040452",
"locked_amount": "9049886.9238116721047082457828299231170587",
"deposits": [
{
"amount": "16249.93",
@@ -34982,6 +34993,11 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x6d913b124af23621f8b97087a51d4cd912c6a8d9cca325cb756b56d4970f3f62"
},
{
"amount": "64.153825929033",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0x33446fce935f9568b7d6e796e6a9a73049585fc7225f935e343acbb5c68a60b7"
},
{
"amount": "434.254023685890375",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -38806,6 +38822,12 @@
"tranche_id": 2,
"tx": "0x55802ccf2bf20a0bf6ffffa5add678cacd8d31450517a2ac65ff384ee5f71f22"
},
{
"amount": "64.153825929033",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tranche_id": 2,
"tx": "0x33446fce935f9568b7d6e796e6a9a73049585fc7225f935e343acbb5c68a60b7"
},
{
"amount": "104.762232778042",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -39036,8 +39058,8 @@
}
],
"total_tokens": "12362.05",
"withdrawn_tokens": "5246.0507139289135",
"remaining_tokens": "7115.9992860710865"
"withdrawn_tokens": "5310.2045398579465",
"remaining_tokens": "7051.8454601420535"
},
{
"address": "0xb091D456d0dFCB94dcba6f355379056C5bb995fC",
@@ -39669,7 +39691,7 @@
"tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999",
"total_removed": "3706973.15022981060693393",
"locked_amount": "2653369.424853388202023095424913904",
"locked_amount": "2633352.597699040729631521134098664",
"deposits": [
{
"amount": "129284.449",
@@ -46370,7 +46392,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "5778205.3912159303",
"total_removed": "2622261.560853924298939789",
"locked_amount": "731458.903664069114159753480553424",
"locked_amount": "723550.13419462381518165594274868",
"deposits": [
{
"amount": "552496.6455",
@@ -48265,7 +48287,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "29683.1054262326685",
"locked_amount": "168552.45507780998384909840791476",
"locked_amount": "167583.553885809073086558333536292",
"deposits": [
{
"amount": "3000",
@@ -76659,7 +76681,7 @@
"tranche_start": "2021-12-05T00:00:00.000Z",
"tranche_end": "2022-06-05T00:00:00.000Z",
"total_added": "171288.42",
"total_removed": "63445.7249006422989",
"total_removed": "63646.1049690697989",
"locked_amount": "0",
"deposits": [
{
@@ -80904,6 +80926,16 @@
"user": "0x4fD63682E3e6803e2F3805D0c40Fcb7a37c5e7c4",
"tx": "0x591b81e6f118be1436cede9763019b99a33594f029716341adb45d6710b66ca6"
},
{
"amount": "99.7195512825",
"user": "0x01a66CdA5D3212D3Ac9f9ff837eE4e4833E52895",
"tx": "0xcaab4c813b9ce156921f1a8cc3193f20d9f2b397e66e774233c13e64475b1853"
},
{
"amount": "100.660517145",
"user": "0xC343fD1a1dd3F8D5412b2bae1c3A4a0482029f63",
"tx": "0xd6c9e31ca9abc4832ba4d6345ddeefbc3ab947b9c48ad834e2002d790642db22"
},
{
"amount": "50",
"user": "0x300A831523b53112F5CF8B802D85EC48a8CB7dcC",
@@ -96556,6 +96588,12 @@
}
],
"withdrawals": [
{
"amount": "99.7195512825",
"user": "0x01a66CdA5D3212D3Ac9f9ff837eE4e4833E52895",
"tranche_id": 6,
"tx": "0xcaab4c813b9ce156921f1a8cc3193f20d9f2b397e66e774233c13e64475b1853"
},
{
"amount": "150.2804487175",
"user": "0x01a66CdA5D3212D3Ac9f9ff837eE4e4833E52895",
@@ -96564,8 +96602,8 @@
}
],
"total_tokens": "250",
"withdrawn_tokens": "150.2804487175",
"remaining_tokens": "99.7195512825"
"withdrawn_tokens": "250",
"remaining_tokens": "0"
},
{
"address": "0x6b671cfa2619790c861Fd3b4B3cb3aE5A78ee3fC",
@@ -96593,6 +96631,12 @@
}
],
"withdrawals": [
{
"amount": "100.660517145",
"user": "0xC343fD1a1dd3F8D5412b2bae1c3A4a0482029f63",
"tranche_id": 6,
"tx": "0xd6c9e31ca9abc4832ba4d6345ddeefbc3ab947b9c48ad834e2002d790642db22"
},
{
"amount": "149.339482855",
"user": "0xC343fD1a1dd3F8D5412b2bae1c3A4a0482029f63",
@@ -96601,8 +96645,8 @@
}
],
"total_tokens": "250",
"withdrawn_tokens": "149.339482855",
"remaining_tokens": "100.660517145"
"withdrawn_tokens": "250",
"remaining_tokens": "0"
},
{
"address": "0x9a25025F722305b4336CcD7E67995E691A12426E",
+1
View File
@@ -11,6 +11,7 @@ NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
#Test configuration variables
CYPRESS_FAIRGROUND=false
+1
View File
@@ -14,6 +14,7 @@ NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit suppl
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
#Test configuration variables
CYPRESS_FAIRGROUND=false
+1
View File
@@ -8,3 +8,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
+2 -1
View File
@@ -8,4 +8,5 @@ NX_ETHERSCAN_URL=https://etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
NX_DELEGATIONS_PAGINATION=50
+1
View File
@@ -8,3 +8,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://mirror.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_DELEGATIONS_PAGINATION=50
+1
View File
@@ -5,3 +5,4 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://sta
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
+1
View File
@@ -5,3 +5,4 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://sta
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
+1
View File
@@ -6,3 +6,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
+1
View File
@@ -9,3 +9,4 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
@@ -7,13 +7,13 @@ fragment WalletDelegationFields on Delegation {
epoch
}
query Delegations($partyId: ID!) {
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
epoch {
id
}
party(id: $partyId) {
id
delegationsConnection {
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...WalletDelegationFields
@@ -7,6 +7,7 @@ export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amount
export type DelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
@@ -23,13 +24,13 @@ export const WalletDelegationFieldsFragmentDoc = gql`
}
`;
export const DelegationsDocument = gql`
query Delegations($partyId: ID!) {
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
epoch {
id
}
party(id: $partyId) {
id
delegationsConnection {
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...WalletDelegationFields
@@ -76,6 +77,7 @@ export const DelegationsDocument = gql`
* const { data, loading, error } = useDelegationsQuery({
* variables: {
* partyId: // value for 'partyId'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
*/
@@ -1,92 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } };
export type DelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type DelegationsQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } } } } | null> | null } | null } | null };
export const WalletDelegationFieldsFragmentDoc = gql`
fragment WalletDelegationFields on Delegation {
amount
node {
id
name
}
epoch
}
`;
export const DelegationsDocument = gql`
query Delegations($partyId: ID!) {
epoch {
id
}
party(id: $partyId) {
id
delegationsConnection {
edges {
node {
...WalletDelegationFields
}
}
}
stakingSummary {
currentStakeAvailable
}
accountsConnection {
edges {
node {
asset {
name
id
decimals
symbol
source {
__typename
... on ERC20 {
contractAddress
}
}
}
type
balance
}
}
}
}
}
${WalletDelegationFieldsFragmentDoc}`;
/**
* __useDelegationsQuery__
*
* To run a query within a React component, call `useDelegationsQuery` and pass it any options that fit your needs.
* When your component renders, `useDelegationsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useDelegationsQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useDelegationsQuery(baseOptions: Apollo.QueryHookOptions<DelegationsQuery, DelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<DelegationsQuery, DelegationsQueryVariables>(DelegationsDocument, options);
}
export function useDelegationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DelegationsQuery, DelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<DelegationsQuery, DelegationsQueryVariables>(DelegationsDocument, options);
}
export type DelegationsQueryHookResult = ReturnType<typeof useDelegationsQuery>;
export type DelegationsLazyQueryHookResult = ReturnType<typeof useDelegationsLazyQuery>;
export type DelegationsQueryResult = Apollo.QueryResult<DelegationsQuery, DelegationsQueryVariables>;
+13 -5
View File
@@ -4,6 +4,7 @@ import keyBy from 'lodash/keyBy';
import uniq from 'lodash/uniq';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { ENV } from '../../config';
import noIcon from '../../images/token-no-icon.png';
import vegaBlack from '../../images/vega_black.png';
@@ -23,18 +24,18 @@ import type {
DelegationsQuery,
DelegationsQueryVariables,
WalletDelegationFieldsFragment,
} from './__generated___/Delegations';
import { DelegationsDocument } from './__generated___/Delegations';
} from './__generated__/Delegations';
import { DelegationsDocument } from './__generated__/Delegations';
export const usePollForDelegations = () => {
const { token: vegaToken } = useContracts();
const {
appState: { decimals },
} = useAppState();
const { t } = useTranslation();
const { pubKey } = useVegaWallet();
const client = useApolloClient();
const { delegationsPagination } = ENV;
const [delegations, setDelegations] = React.useState<
WalletDelegationFieldsFragment[]
>([]);
@@ -62,7 +63,14 @@ export const usePollForDelegations = () => {
client
.query<DelegationsQuery, DelegationsQueryVariables>({
query: DelegationsDocument,
variables: { partyId: pubKey },
variables: {
partyId: pubKey,
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
fetchPolicy: 'network-only',
})
.then((res) => {
@@ -207,7 +215,7 @@ export const usePollForDelegations = () => {
clearInterval(interval);
mounted = false;
};
}, [client, decimals, pubKey, t, vegaToken.address]);
}, [delegationsPagination, client, decimals, pubKey, t, vegaToken.address]);
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
};
+1
View File
@@ -64,6 +64,7 @@ export const ENV = {
docsUrl: windowOrDefault('NX_VEGA_DOCS_URL'),
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
flags: {
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
@@ -20,7 +20,7 @@ fragment DelegationFields on Delegation {
epoch
}
query Rewards($partyId: ID!) {
query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
rewardsConnection {
@@ -30,7 +30,7 @@ query Rewards($partyId: ID!) {
}
}
}
delegationsConnection {
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...DelegationFields
+4 -2
View File
@@ -9,6 +9,7 @@ export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: stri
export type RewardsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
@@ -39,7 +40,7 @@ export const DelegationFieldsFragmentDoc = gql`
}
`;
export const RewardsDocument = gql`
query Rewards($partyId: ID!) {
query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
rewardsConnection {
@@ -49,7 +50,7 @@ export const RewardsDocument = gql`
}
}
}
delegationsConnection {
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...DelegationFields
@@ -82,6 +83,7 @@ ${DelegationFieldsFragmentDoc}`;
* const { data, loading, error } = useRewardsQuery({
* variables: {
* partyId: // value for 'partyId'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
*/
@@ -1,98 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type RewardFieldsFragment = { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } };
export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number };
export type RewardsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type RewardsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, rewardsConnection?: { __typename?: 'RewardsConnection', edges?: Array<{ __typename?: 'RewardEdge', node: { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } } } | null> | null } | null, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } } };
export const RewardFieldsFragmentDoc = gql`
fragment RewardFields on Reward {
rewardType
asset {
id
symbol
}
party {
id
}
epoch {
id
}
amount
percentageOfTotal
receivedAt
}
`;
export const DelegationFieldsFragmentDoc = gql`
fragment DelegationFields on Delegation {
amount
epoch
}
`;
export const RewardsDocument = gql`
query Rewards($partyId: ID!) {
party(id: $partyId) {
id
rewardsConnection {
edges {
node {
...RewardFields
}
}
}
delegationsConnection {
edges {
node {
...DelegationFields
}
}
}
}
epoch {
id
timestamps {
start
end
expiry
}
}
}
${RewardFieldsFragmentDoc}
${DelegationFieldsFragmentDoc}`;
/**
* __useRewardsQuery__
*
* To run a query within a React component, call `useRewardsQuery` and pass it any options that fit your needs.
* When your component renders, `useRewardsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useRewardsQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useRewardsQuery(baseOptions: Apollo.QueryHookOptions<RewardsQuery, RewardsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<RewardsQuery, RewardsQueryVariables>(RewardsDocument, options);
}
export function useRewardsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<RewardsQuery, RewardsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<RewardsQuery, RewardsQueryVariables>(RewardsDocument, options);
}
export type RewardsQueryHookResult = ReturnType<typeof useRewardsQuery>;
export type RewardsLazyQueryHookResult = ReturnType<typeof useRewardsLazyQuery>;
export type RewardsQueryResult = Apollo.QueryResult<RewardsQuery, RewardsQueryVariables>;
@@ -9,7 +9,7 @@ import type {
RewardsQuery,
RewardFieldsFragment,
DelegationFieldsFragment,
} from './__generated___/Rewards';
} from './__generated__/Rewards';
import {
formatNumber,
removePaginationWrapper,
@@ -4,6 +4,7 @@ import { formatDistance } from 'date-fns';
import Duration from 'duration-js';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { ENV } from '../../../config';
import { EpochCountdown } from '../../../components/epoch-countdown';
import { Heading } from '../../../components/heading';
@@ -15,7 +16,7 @@ import {
import { RewardInfo } from './reward-info';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { useNetworkParams, NetworkParams } from '@vegaprotocol/react-helpers';
import { useRewardsQuery } from './__generated___/Rewards';
import { useRewardsQuery } from './__generated__/Rewards';
export const RewardsPage = () => {
const { t } = useTranslation();
@@ -24,8 +25,16 @@ export const RewardsPage = () => {
openVegaWalletDialog: store.openVegaWalletDialog,
}));
const { appDispatch } = useAppState();
const { delegationsPagination } = ENV;
const { data, loading, error } = useRewardsQuery({
variables: { partyId: pubKey || '' },
variables: {
partyId: pubKey || '',
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
skip: !pubKey,
});
const { params } = useNetworkParams([
@@ -6,10 +6,10 @@ fragment StakingDelegationsFields on Delegation {
epoch
}
query PartyDelegations($partyId: ID!) {
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
delegationsConnection {
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...StakingDelegationsFields
@@ -23,13 +23,13 @@ fragment StakingNodeFields on Node {
}
}
query Staking($partyId: ID!) {
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
}
delegationsConnection {
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
amount
@@ -7,6 +7,7 @@ export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amou
export type PartyDelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
@@ -22,10 +23,10 @@ export const StakingDelegationsFieldsFragmentDoc = gql`
}
`;
export const PartyDelegationsDocument = gql`
query PartyDelegations($partyId: ID!) {
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
delegationsConnection {
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
...StakingDelegationsFields
@@ -52,6 +53,7 @@ export const PartyDelegationsDocument = gql`
* const { data, loading, error } = usePartyDelegationsQuery({
* variables: {
* partyId: // value for 'partyId'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
*/
+4 -2
View File
@@ -7,6 +7,7 @@ export type StakingNodeFieldsFragment = { __typename?: 'Node', id: string, name:
export type StakingQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
@@ -39,13 +40,13 @@ export const StakingNodeFieldsFragmentDoc = gql`
}
`;
export const StakingDocument = gql`
query Staking($partyId: ID!) {
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
}
delegationsConnection {
delegationsConnection(pagination: $delegationsPagination) {
edges {
node {
amount
@@ -94,6 +95,7 @@ export const StakingDocument = gql`
* const { data, loading, error } = useStakingQuery({
* variables: {
* partyId: // value for 'partyId'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
*/
@@ -1,68 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } };
export type PartyDelegationsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PartyDelegationsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string } };
export const StakingDelegationsFieldsFragmentDoc = gql`
fragment StakingDelegationsFields on Delegation {
amount
node {
id
}
epoch
}
`;
export const PartyDelegationsDocument = gql`
query PartyDelegations($partyId: ID!) {
party(id: $partyId) {
id
delegationsConnection {
edges {
node {
...StakingDelegationsFields
}
}
}
}
epoch {
id
}
}
${StakingDelegationsFieldsFragmentDoc}`;
/**
* __usePartyDelegationsQuery__
*
* To run a query within a React component, call `usePartyDelegationsQuery` and pass it any options that fit your needs.
* When your component renders, `usePartyDelegationsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = usePartyDelegationsQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function usePartyDelegationsQuery(baseOptions: Apollo.QueryHookOptions<PartyDelegationsQuery, PartyDelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(PartyDelegationsDocument, options);
}
export function usePartyDelegationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyDelegationsQuery, PartyDelegationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(PartyDelegationsDocument, options);
}
export type PartyDelegationsQueryHookResult = ReturnType<typeof usePartyDelegationsQuery>;
export type PartyDelegationsLazyQueryHookResult = ReturnType<typeof usePartyDelegationsLazyQuery>;
export type PartyDelegationsQueryResult = Apollo.QueryResult<PartyDelegationsQuery, PartyDelegationsQueryVariables>;
@@ -1,110 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type StakingNodeFieldsFragment = { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } };
export type StakingQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type StakingQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string, totalNodes: number, inactiveNodes: number, uptime: number } | null };
export const StakingNodeFieldsFragmentDoc = gql`
fragment StakingNodeFields on Node {
id
name
pubkey
infoUrl
location
ethereumAddress
stakedByOperator
stakedByDelegates
stakedTotal
pendingStake
epochData {
total
offline
online
}
rankingScore {
rankingScore
stakeScore
performanceScore
votingPower
status
}
}
`;
export const StakingDocument = gql`
query Staking($partyId: ID!) {
party(id: $partyId) {
id
stakingSummary {
currentStakeAvailable
}
delegationsConnection {
edges {
node {
amount
epoch
node {
id
}
}
}
}
}
epoch {
id
timestamps {
start
end
expiry
}
}
nodesConnection {
edges {
node {
...StakingNodeFields
}
}
}
nodeData {
stakedTotal
totalNodes
inactiveNodes
uptime
}
}
${StakingNodeFieldsFragmentDoc}`;
/**
* __useStakingQuery__
*
* To run a query within a React component, call `useStakingQuery` and pass it any options that fit your needs.
* When your component renders, `useStakingQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useStakingQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function useStakingQuery(baseOptions: Apollo.QueryHookOptions<StakingQuery, StakingQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<StakingQuery, StakingQueryVariables>(StakingDocument, options);
}
export function useStakingLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StakingQuery, StakingQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<StakingQuery, StakingQueryVariables>(StakingDocument, options);
}
export type StakingQueryHookResult = ReturnType<typeof useStakingQuery>;
export type StakingLazyQueryHookResult = ReturnType<typeof useStakingLazyQuery>;
export type StakingQueryResult = Apollo.QueryResult<StakingQuery, StakingQueryVariables>;
+1 -1
View File
@@ -20,7 +20,7 @@ import NodeContainer from './nodes-container';
import { useAppState } from '../../../contexts/app-state/app-state-context';
import { Heading, SubHeading } from '../../../components/heading';
import Routes from '../../routes';
import type { StakingQuery } from './__generated___/Staking';
import type { StakingQuery } from './__generated__/Staking';
import type { PreviousEpochQuery } from '../__generated___/PreviousEpoch';
interface StakingNodeProps {
@@ -1,14 +1,14 @@
import { ENV } from '../../../config';
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useStakingQuery } from './__generated___/Staking';
import { SplashLoader } from '../../../components/splash-loader';
import { usePreviousEpochQuery } from '../__generated___/PreviousEpoch';
import type { StakingQuery } from './__generated___/Staking';
import type { PreviousEpochQuery } from '../__generated___/PreviousEpoch';
import { useRefreshValidators } from '../../../hooks/use-refresh-validators';
import { SplashLoader } from '../../../components/splash-loader';
import { useStakingQuery } from './__generated__/Staking';
import { usePreviousEpochQuery } from '../__generated___/PreviousEpoch';
import type { ReactElement } from 'react';
import type { StakingQuery } from './__generated__/Staking';
import type { PreviousEpochQuery } from '../__generated___/PreviousEpoch';
// TODO should only request a single node. When migrating from deprecated APIs we should address this.
@@ -23,12 +23,20 @@ export const NodeContainer = ({
}: {
data?: StakingQuery;
previousEpochData?: PreviousEpochQuery;
}) => React.ReactElement;
}) => ReactElement;
}) => {
const { t } = useTranslation();
const { pubKey } = useVegaWallet();
const { delegationsPagination } = ENV;
const { data, loading, error, refetch } = useStakingQuery({
variables: { partyId: pubKey || '' },
variables: {
partyId: pubKey || '',
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
});
const { data: previousEpochData } = usePreviousEpochQuery({
variables: {
@@ -3,7 +3,8 @@ import * as Sentry from '@sentry/react';
import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { usePartyDelegationsLazyQuery } from './__generated___/PartyDelegations';
import { ENV } from '../../../config';
import { usePartyDelegationsLazyQuery } from './__generated__/PartyDelegations';
import { TokenInput } from '../../../components/token-input';
import { useAppState } from '../../../contexts/app-state/app-state-context';
import { useSearchParams } from '../../../hooks/use-search-params';
@@ -73,6 +74,7 @@ export const StakingForm = ({
const [error, setError] = useState<Error | null>(null);
const [isDialogVisible, setIsDialogVisible] = useState(false);
const { t } = useTranslation();
const { delegationsPagination } = ENV;
const [action, setAction] = React.useState<StakeAction>(
params.action as StakeAction
);
@@ -147,6 +149,11 @@ export const StakingForm = ({
const [delegationSearch, { data }] = usePartyDelegationsLazyQuery({
variables: {
partyId: pubKey,
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
fetchPolicy: 'network-only',
});
@@ -25,7 +25,7 @@ import {
getUnnormalisedVotingPower,
} from '../shared';
import type { ReactNode } from 'react';
import type { StakingNodeFieldsFragment } from './__generated___/Staking';
import type { StakingNodeFieldsFragment } from './__generated__/Staking';
import type { PreviousEpochQuery } from '../__generated___/PreviousEpoch';
const statuses = {
@@ -2,8 +2,11 @@ import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment';
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
import { MarketProposalNotification } from '@vegaprotocol/governance';
import { getExpiryDate, getMarketExpiryDate } from '@vegaprotocol/market-info';
import { t } from '@vegaprotocol/react-helpers';
import {
getExpiryDate,
getMarketExpiryDate,
t,
} from '@vegaprotocol/react-helpers';
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list';
import {
ColumnKind,
@@ -125,7 +128,14 @@ type ExpiryLabelProps = {
};
const ExpiryLabel = ({ market }: ExpiryLabelProps) => {
const content = market ? getExpiryDate(market) : '-';
const content =
market && market.tradableInstrument.instrument.metadata.tags
? getExpiryDate(
market.tradableInstrument.instrument.metadata.tags,
market.marketTimestamps.close,
market.state
)
: '-';
return <div data-testid="trading-expiry">{content}</div>;
};
@@ -139,16 +139,19 @@ const AccountHistoryManager = ({
<div className="h-full w-full flex flex-col gap-8">
<div className="w-full flex flex-col-reverse lg:flex-row items-start lg:items-center justify-between gap-4 px-2">
<div className="flex items-center gap-4 shrink-0">
<DropdownMenu>
<DropdownMenuTrigger>
{accountType
? `${
AccountTypeMapping[
accountType as keyof typeof Schema.AccountType
]
} Account`
: t('Select account type')}
</DropdownMenuTrigger>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
{accountType
? `${
AccountTypeMapping[
accountType as keyof typeof Schema.AccountType
]
} Account`
: t('Select account type')}
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
{[
Schema.AccountType.ACCOUNT_TYPE_GENERAL,
@@ -164,10 +167,13 @@ const AccountHistoryManager = ({
))}
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<DropdownMenuTrigger>
{asset ? asset.symbol : t('Select asset')}
</DropdownMenuTrigger>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
{asset ? asset.symbol : t('Select asset')}
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
{assets.map((a) => (
<DropdownMenuItem key={a.id} onClick={() => setAsset(a)}>
@@ -3,6 +3,7 @@ import { VegaWalletContext } from '@vegaprotocol/wallet';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletConnectButton } from './vega-wallet-connect-button';
import { truncateByChars } from '@vegaprotocol/react-helpers';
import userEvent from '@testing-library/user-event';
const mockUpdateDialogOpen = jest.fn();
jest.mock('@vegaprotocol/wallet', () => ({
@@ -31,7 +32,7 @@ it('Not connected', () => {
expect(mockUpdateDialogOpen).toHaveBeenCalled();
});
it('Connected', () => {
it('Connected', async () => {
const pubKey = { publicKey: '123456__123456', name: 'test' };
render(
generateJsx({
@@ -42,6 +43,6 @@ it('Connected', () => {
const button = screen.getByTestId('manage-vega-wallet');
expect(button).toHaveTextContent(truncateByChars(pubKey.publicKey));
fireEvent.click(button);
userEvent.click(button);
expect(mockUpdateDialogOpen).not.toHaveBeenCalled();
});
@@ -142,15 +142,21 @@ export const VegaWalletConnectButton = () => {
return (
<>
<div className="hidden lg:block">
<DropdownMenu open={dropdownOpen}>
<DropdownMenuTrigger
data-testid="manage-vega-wallet"
onClick={() => setDropdownOpen((curr) => !curr)}
>
{activeKey && <span className="uppercase">{activeKey.name}</span>}
{': '}
{truncateByChars(pubKey)}
</DropdownMenuTrigger>
<DropdownMenu
open={dropdownOpen}
trigger={
<DropdownMenuTrigger
data-testid="manage-vega-wallet"
onClick={() => setDropdownOpen((curr) => !curr)}
>
{activeKey && (
<span className="uppercase">{activeKey.name}</span>
)}
{': '}
{truncateByChars(pubKey)}
</DropdownMenuTrigger>
}
>
<DropdownMenuContent
onInteractOutside={() => setDropdownOpen(false)}
>
@@ -27,7 +27,7 @@ const isWithdrawTransaction = (tx: EthStoredTxState) =>
tx.methodName === 'withdraw_asset';
const isDepositTransaction = (tx: EthStoredTxState) =>
tx.methodName === 'withdraw_asset';
tx.methodName === 'deposit_asset';
const EthTransactionDetails = ({ tx }: { tx: EthStoredTxState }) => {
const { data: assets } = useAssetsDataProvider();
@@ -150,11 +150,11 @@ const EthTxCompletedToastContent = ({ tx }: EthTxToastContentProps) => {
return (
<div>
<h3 className="font-bold">
{t('Processing')} {isDeposit && 'deposit'}
{t('Processing')} {isDeposit && t('deposit')}
</h3>
<p>
{t('Your transaction has been completed.')}
{isDeposit && t('Waiting for deposit confirmation')}
{isDeposit && t('Waiting for deposit confirmation.')}
</p>
<EtherscanLink tx={tx} />
<EthTransactionDetails tx={tx} />
+20 -12
View File
@@ -60,10 +60,13 @@ export const CandlesChartContainer = ({
return (
<div className="h-full flex flex-col">
<div className="px-4 py-2 flex flex-row flex-wrap gap-4">
<DropdownMenu>
<DropdownMenuTrigger>
{t(`Interval: ${intervalLabels[interval]}`)}
</DropdownMenuTrigger>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
{t(`Interval: ${intervalLabels[interval]}`)}
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
<DropdownMenuRadioGroup
value={interval}
@@ -84,10 +87,13 @@ export const CandlesChartContainer = ({
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<DropdownMenuTrigger>
<Icon name={chartTypeIcon.get(chartType) as IconName} />
</DropdownMenuTrigger>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
<Icon name={chartTypeIcon.get(chartType) as IconName} />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
<DropdownMenuRadioGroup
value={chartType}
@@ -104,8 +110,9 @@ export const CandlesChartContainer = ({
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<DropdownMenuTrigger>{t('Overlays')}</DropdownMenuTrigger>
<DropdownMenu
trigger={<DropdownMenuTrigger>{t('Overlays')}</DropdownMenuTrigger>}
>
<DropdownMenuContent>
{Object.values(Overlay).map((overlay) => (
<DropdownMenuCheckboxItem
@@ -128,8 +135,9 @@ export const CandlesChartContainer = ({
))}
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<DropdownMenuTrigger>{t('Studies')}</DropdownMenuTrigger>
<DropdownMenu
trigger={<DropdownMenuTrigger>{t('Studies')}</DropdownMenuTrigger>}
>
<DropdownMenuContent>
{Object.values(Study).map((study) => (
<DropdownMenuCheckboxItem
@@ -96,13 +96,18 @@ export const NetworkSwitcher = () => {
const menuRef = useRef<HTMLButtonElement | null>(null);
return (
<DropdownMenu open={isOpen} onOpenChange={handleOpen}>
<DropdownMenuTrigger
ref={menuRef}
className="flex justify-between items-center"
>
{envTriggerMapping[VEGA_ENV]}
</DropdownMenuTrigger>
<DropdownMenu
open={isOpen}
onOpenChange={handleOpen}
trigger={
<DropdownMenuTrigger
ref={menuRef}
className="flex justify-between items-center"
>
{envTriggerMapping[VEGA_ENV]}
</DropdownMenuTrigger>
}
>
<DropdownMenuContent
align="start"
style={{ minWidth: `${menuRef.current?.offsetWidth || 290}px` }}
@@ -31,8 +31,6 @@ import {
getTargetStake,
} from './utils/liquidity-utils';
import type { Provider, LiquidityProvisionMarket } from './utils';
import { proposalsListDataProvider } from '@vegaprotocol/governance';
import type { Proposal } from '@vegaprotocol/types';
export interface FeeLevels {
commitmentAmount: number;
@@ -46,7 +44,13 @@ export type Market = MarketWithData &
dayVolume: string;
liquidityCommitted: number;
volumeChange: string;
proposal?: Proposal;
tradableInstrument?: {
instrument?: {
metadata?: {
tags?: string[] | null;
};
};
};
};
export interface Markets {
@@ -66,8 +70,7 @@ const getData = (
export const addData = (
markets: (MarketWithData & MarketWithCandles)[],
marketsCandles24hAgo: MarketCandles[],
marketsLiquidity: LiquidityProvisionMarket[],
proposals: Proposal[]
marketsLiquidity: LiquidityProvisionMarket[]
) => {
return markets.map((market) => {
const dayVolume = calcDayVolume(market.candles);
@@ -80,9 +83,6 @@ export const addData = (
marketsLiquidity
) as Provider[];
const proposalForMarket =
proposals && proposals.find((p) => p.id === market.id);
return {
...market,
dayVolume,
@@ -90,7 +90,6 @@ export const addData = (
liquidityCommitted: sumLiquidityCommitted(liquidityProviders),
feeLevels: getFeeLevels(liquidityProviders) || [],
target: getTargetStake(market.id, marketsLiquidity),
proposal: proposalForMarket,
};
});
};
@@ -114,14 +113,12 @@ const liquidityProvisionProvider = makeDerivedDataProvider<Markets, never>(
interval: Schema.Interval.INTERVAL_I1D,
}),
liquidityMarketsProvider,
proposalsListDataProvider,
],
(parts) => {
const data = addData(
parts[0] as (MarketWithData & MarketWithCandles)[],
parts[1] as MarketCandles[],
parts[2] as LiquidityProvisionMarket[],
parts[3] as Proposal[]
parts[2] as LiquidityProvisionMarket[]
);
return { markets: data };
}
-1
View File
@@ -1,3 +1,2 @@
export * from './market-expires';
export * from './market-info';
export * from './fees-breakdown';
@@ -1 +0,0 @@
export * from './market-expires';
@@ -23,10 +23,12 @@ import pick from 'lodash/pick';
import { useMemo } from 'react';
import { generatePath, Link } from 'react-router-dom';
import { getMarketExpiryDateFormatted } from '../market-expires';
import { MarketInfoTable } from './info-key-value-table';
import { marketInfoDataProvider } from './market-info-data-provider';
import { TokenLinks } from '@vegaprotocol/react-helpers';
import {
TokenLinks,
getMarketExpiryDateFormatted,
} from '@vegaprotocol/react-helpers';
import type { MarketInfoQuery } from './__generated__/MarketInfo';
import { MarketProposalNotification } from '@vegaprotocol/governance';
+1
View File
@@ -17,3 +17,4 @@ export * from './lib/remove-pagination-wrapper';
export * from './lib/__generated__/ChainId';
export * from './lib/data-grid';
export * from './lib/local-logger';
export * from './lib/market-expires';
+1
View File
@@ -13,3 +13,4 @@ export * from './links';
export * from './remove-pagination-wrapper';
export * from './data-grid';
export * from './local-logger';
export * from './market-expires';
@@ -3,8 +3,7 @@ import React from 'react';
import { MarketExpires } from './market-expires';
jest.mock('@vegaprotocol/react-helpers', () => ({
t: jest.fn().mockImplementation((text) => text),
jest.mock('./format', () => ({
getDateTimeFormat: () =>
Intl.DateTimeFormat('en-GB', {
year: 'numeric',
@@ -16,6 +15,10 @@ jest.mock('@vegaprotocol/react-helpers', () => ({
}),
}));
jest.mock('./i18n', () => ({
t: jest.fn().mockImplementation((text) => text),
}));
describe('MarketExpires', () => {
describe('should properly parse different tags', () => {
it('settlement:date', () => {
@@ -1,7 +1,7 @@
import { getDateTimeFormat, t } from '@vegaprotocol/react-helpers';
import { t } from './i18n';
import { getDateTimeFormat } from './format';
import { isValid, parseISO } from 'date-fns';
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list';
import { MarketState } from '@vegaprotocol/types';
export const getMarketExpiryDate = (
@@ -36,12 +36,13 @@ export const getMarketExpiryDateFormatted = (
return null;
};
export const getExpiryDate = (market: SingleMarketFieldsFragment): string => {
const metadataExpiryDate = getMarketExpiryDate(
market.tradableInstrument.instrument.metadata.tags
);
const marketTimestampCloseDate =
market.marketTimestamps.close && new Date(market.marketTimestamps.close);
export const getExpiryDate = (
tags: ReadonlyArray<string> | null,
close: string | null,
state: MarketState
): string => {
const metadataExpiryDate = getMarketExpiryDate(tags);
const marketTimestampCloseDate = close && new Date(close);
let content = null;
if (!metadataExpiryDate) {
content = marketTimestampCloseDate
@@ -50,8 +51,8 @@ export const getExpiryDate = (market: SingleMarketFieldsFragment): string => {
} else {
const isExpired =
Date.now() - metadataExpiryDate.valueOf() > 0 &&
(market.state === MarketState.STATE_TRADING_TERMINATED ||
market.state === MarketState.STATE_SETTLED);
(state === MarketState.STATE_TRADING_TERMINATED ||
state === MarketState.STATE_SETTLED);
if (isExpired) {
content = marketTimestampCloseDate
? `Expired on ${getDateTimeFormat().format(marketTimestampCloseDate)}`
+4
View File
@@ -3894,6 +3894,10 @@ export type Statistics = {
chainVersion: Scalars['String'];
/** RFC3339Nano current time (real) */
currentTime: Scalars['Timestamp'];
/** Total number of events on the last block */
eventCount: Scalars['String'];
/** The number of events per second on the last block */
eventsPerSecond: Scalars['String'];
/** RFC3339Nano genesis time of the chain */
genesisTime: Scalars['Timestamp'];
/** Number of orders per seconds */
@@ -0,0 +1,34 @@
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from './dropdown-menu';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('DropdownMenu', () => {
const text = 'Dropdown menu content';
// Upgrade from @radix-ui/react-dropdown-menu 0.1.6 to 2.0.2 renders
// dropdowns inline (rather than portals). Currently not using a portal
// will break the UI due to z-index issues
it('renders using a portal', async () => {
render(
<div className="test-wrapper">
<DropdownMenu
trigger={<DropdownMenuTrigger>Trigger</DropdownMenuTrigger>}
>
<DropdownMenuContent>
<p>{text}</p>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
userEvent.click(screen.getByText(/trigger/i));
const contentElement = await screen.findByText(text);
expect(contentElement).toBeInTheDocument();
// if content is within .test-wrapper then its not been rendered in a portal
expect(contentElement.closest('.test-wrapper')).toBe(null);
});
});
@@ -29,16 +29,21 @@ export const CheckboxItems = () => {
console.log(checkboxItems);
return (
<DropdownMenu>
<DropdownMenuTrigger>
<span>Select many things</span>
</DropdownMenuTrigger>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
<span>Select many things</span>
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
{checkboxItems.map(({ label, state: [checked, setChecked] }) => (
<DropdownMenuCheckboxItem
key={label}
checked={checked}
onCheckedChange={setChecked}
onCheckedChange={(checked) =>
setChecked(typeof checked === 'boolean' ? checked : false)
}
>
{label}
<DropdownMenuItemIndicator />
@@ -55,10 +60,13 @@ export const RadioItems = () => {
return (
<div style={{ textAlign: 'center', padding: 50 }}>
<DropdownMenu>
<DropdownMenuTrigger>
<span>Open</span>
</DropdownMenuTrigger>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
<span>Open</span>
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
<DropdownMenuItem onSelect={() => console.log('minimize')}>
Minimize window
@@ -92,10 +100,13 @@ export const IconMenu = () => {
return (
<div style={{ textAlign: 'center', padding: 50 }}>
<DropdownMenu>
<DropdownMenuTrigger>
<Icon name="cog" />
</DropdownMenuTrigger>
<DropdownMenu
trigger={
<DropdownMenuTrigger>
<Icon name="cog" />
</DropdownMenuTrigger>
}
>
<DropdownMenuContent>
{iconMenuItems.map(({ label }) => (
<DropdownMenuItem key={label}>{label}</DropdownMenuItem>
@@ -1,5 +1,6 @@
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
import classNames from 'classnames';
import type { ReactNode } from 'react';
import { forwardRef } from 'react';
import { Icon } from '../icon';
@@ -12,11 +13,24 @@ const itemClass = classNames(
'whitespace-nowrap'
);
type DropdownMenuProps = DropdownMenuPrimitive.DropdownMenuProps & {
trigger: ReactNode;
};
/**
* Contains all the parts of a dropdown menu.
*/
export const DropdownMenu = DropdownMenuPrimitive.Root;
export const DropdownMenu = ({
children,
trigger,
...props
}: DropdownMenuProps) => {
return (
<DropdownMenuPrimitive.Root {...props}>
{trigger}
<DropdownMenuPrimitive.Portal>{children}</DropdownMenuPrimitive.Portal>
</DropdownMenuPrimitive.Root>
);
};
/**
* The button that toggles the dropdown menu.
* By default, the {@link DropdownMenuContent} will position itself against the trigger.