Compare commits

...
Author SHA1 Message Date
Bartłomiej Głownia b80e5aca22 chore: improve generic data provider unit test 2023-02-08 15:41:45 +01:00
Bartłomiej Głownia dada8521e2 chore: add generic data provider unit test 2023-02-08 15:41:45 +01:00
mattrussell36 5d613396e1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-08 12:09:14 +00:00
Sam Keen da551f9d3c feat(governance): replace proposal and vote busEvents with subscriptions (#2862) 2023-02-08 09:42:20 +00:00
Edd 47e4861fdb fix(explorer): use position decimal places to format size in order (#2861) 2023-02-08 08:22:27 +00:00
mattrussell36 1a85a89440 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-08 06:06:13 +00:00
mattrussell36 7ab412a8f7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-08 00:12:40 +00:00
23 changed files with 315 additions and 146 deletions
@@ -2,6 +2,7 @@ query ExplorerMarket($id: ID!) {
market(id: $id) {
id
decimalPlaces
positionDecimalPlaces
tradableInstrument {
instrument {
name
@@ -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, settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null };
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: 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`
@@ -16,6 +16,7 @@ export const ExplorerMarketDocument = gql`
market(id: $id) {
id
decimalPlaces
positionDecimalPlaces
tradableInstrument {
instrument {
name
@@ -55,6 +55,7 @@ describe('Market link component', () => {
market: {
id: '123',
decimalPlaces: 5,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data',
tradableInstrument: {
instrument: {
@@ -19,6 +19,7 @@ fragment ExplorerDeterministicOrderFields on Order {
market {
id
decimalPlaces
positionDecimalPlaces
tradableInstrument {
instrument {
name
@@ -3,7 +3,7 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } };
export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } };
export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
orderId: Types.Scalars['ID'];
@@ -11,7 +11,7 @@ export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
}>;
export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } } };
export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } } };
export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
fragment ExplorerDeterministicOrderFields on Order {
@@ -35,6 +35,7 @@ export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
market {
id
decimalPlaces
positionDecimalPlaces
tradableInstrument {
instrument {
name
@@ -61,6 +61,7 @@ function renderExistingAmend(id: string, version: number, amend: Amend) {
__typename: 'Market',
id: '789',
state: 'STATUS_ACTIVE',
positionDecimalPlaces: 2,
decimalPlaces: '5',
tradableInstrument: {
instrument: {
@@ -88,6 +89,7 @@ function renderExistingAmend(id: string, version: number, amend: Amend) {
market: {
id: '789',
decimalPlaces: 5,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data',
tradableInstrument: {
instrument: {
@@ -4,6 +4,7 @@ import { MarketLink } from '../links';
import PriceInMarket from '../price-in-market/price-in-market';
import { Time } from '../time';
import { sideText, statusText, tifFull, tifShort } from './lib/order-labels';
import SizeInMarket from '../size-in-market/size-in-market';
export interface DeterministicOrderDetailsProps {
id: string;
@@ -90,7 +91,7 @@ const DeterministicOrderDetails = ({
<div className="mb-12 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-4">{t('Size')}</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
{o.size}
<SizeInMarket size={o.size} marketId={o.market.id} />
</h5>
</div>
@@ -38,6 +38,7 @@ const mock = {
__typename: 'Market',
id: '789',
state: 'STATE_ACTIVE',
positionDecimalPlaces: 2,
decimalPlaces: 2,
tradableInstrument: {
instrument: {
@@ -90,6 +90,7 @@ describe('Order TX Summary component', () => {
market: {
id: '123',
decimalPlaces: 2,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data',
tradableInstrument: {
instrument: {
@@ -37,6 +37,7 @@ const fullMock = {
market: {
id: '123',
decimalPlaces: 2,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data',
tradableInstrument: {
instrument: {
@@ -0,0 +1,69 @@
import { MemoryRouter } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing';
import type { MockedResponse } from '@apollo/client/testing';
import { render } from '@testing-library/react';
import SizeInMarket from './size-in-market';
import type { DecimalSource } from './size-in-market';
import { ExplorerMarketDocument } from '../links/market-link/__generated__/Market';
function renderComponent(
price: string,
marketId: string,
mocks: MockedResponse[],
decimalSource: DecimalSource = 'MARKET'
) {
return (
<MockedProvider mocks={mocks} addTypename={false}>
<MemoryRouter>
<SizeInMarket
marketId={marketId}
size={price}
decimalSource={decimalSource}
/>
</MemoryRouter>
</MockedProvider>
);
}
const fullMock = {
request: {
query: ExplorerMarketDocument,
variables: {
id: '123',
},
},
result: {
data: {
market: {
id: '123',
decimalPlaces: 2,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data',
tradableInstrument: {
instrument: {
name: 'test dai',
product: {
__typename: 'Future',
quoteName: 'dai',
settlementAsset: {
decimals: 18,
},
},
},
},
},
},
},
};
describe('Size in Market component', () => {
it('Renders the raw size when there is no market data', () => {
const res = render(renderComponent('100', '123', []));
expect(res.getByText('100')).toBeInTheDocument();
});
it('Renders the formatted size when market data is fetched', async () => {
const res = render(renderComponent('100', '123', [fullMock]));
expect(await res.findByText('1.00')).toBeInTheDocument();
});
});
@@ -0,0 +1,41 @@
import { addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market';
export type DecimalSource = 'MARKET';
export type PriceInMarketProps = {
marketId: string;
size: string | number;
decimalSource?: DecimalSource;
};
/**
* Given a market ID and an order size it will fetch the market
* order size, and format the size accordingly
*/
const SizeInMarket = ({
marketId,
size,
decimalSource = 'MARKET',
}: PriceInMarketProps) => {
const { data } = useExplorerMarketQuery({
variables: { id: marketId },
fetchPolicy: 'cache-first',
});
let label = size;
if (data) {
if (decimalSource === 'MARKET' && data.market?.positionDecimalPlaces) {
label = addDecimalsFormatNumber(size, data.market.positionDecimalPlaces);
}
}
return (
<label>
<span>{label}</span>
</label>
);
};
export default SizeInMarket;
+71 -27
View File
@@ -98,13 +98,24 @@
}
]
},
{
"tranche_id": 53,
"tranche_start": "2023-03-06T00:00:00.000Z",
"tranche_end": "2023-04-06T00:00:00.000Z",
"total_added": "0",
"total_removed": "0",
"locked_amount": "0",
"deposits": [],
"withdrawals": [],
"users": []
},
{
"tranche_id": 49,
"tranche_start": "2022-12-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "86666.297",
"total_removed": "0",
"locked_amount": "71290.812100647638944706",
"locked_amount": "71112.3321837696257405828",
"deposits": [
{
"amount": "86666.297",
@@ -170,7 +181,7 @@
"tranche_end": "2023-06-01T00:00:00.000Z",
"total_added": "2500",
"total_removed": "0",
"locked_amount": "1555.5670024420025",
"locked_amount": "1545.241751882377",
"deposits": [
{
"amount": "2500",
@@ -558,7 +569,7 @@
"tranche_end": "2023-08-01T00:00:00.000Z",
"total_added": "37500",
"total_removed": "183.137181525",
"locked_amount": "36100.54097605893375",
"locked_amount": "35944.80653391651375",
"deposits": [
{
"amount": "7500",
@@ -624,7 +635,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "71225.768204759715901935",
"locked_amount": "71047.451128348659886215",
"deposits": [
{
"amount": "129999.45",
@@ -690,7 +701,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "62600",
"total_removed": "0",
"locked_amount": "35543.98462709284528",
"locked_amount": "35415.06666032470672",
"deposits": [
{
"amount": "10000",
@@ -883,7 +894,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000",
"total_removed": "0",
"locked_amount": "3030.7572298325725",
"locked_amount": "3020.4602676306445",
"deposits": [
{
"amount": "5000",
@@ -1094,7 +1105,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "97499.58",
"total_removed": "0",
"locked_amount": "13088.045251352428418448",
"locked_amount": "12913.1328103802082906612",
"deposits": [
{
"amount": "97499.58",
@@ -1127,7 +1138,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "135173.4239508",
"total_removed": "98230.390980249184455396",
"locked_amount": "17889.0983018495693667123126",
"locked_amount": "17650.023192413700622871272848",
"deposits": [
{
"amount": "135173.4239508",
@@ -1173,7 +1184,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "32499.86",
"total_removed": "0",
"locked_amount": "5505.914618791834455152",
"locked_amount": "5432.3319754511083747504",
"deposits": [
{
"amount": "32499.86",
@@ -1206,7 +1217,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "10833.29",
"total_removed": "0",
"locked_amount": "1792.1217802859475346957",
"locked_amount": "1768.171343907611431555",
"deposits": [
{
"amount": "10833.29",
@@ -1239,7 +1250,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "22749.93",
"total_removed": "0",
"locked_amount": "6699.35147787958153563",
"locked_amount": "6609.8193974640044998578",
"deposits": [
{
"amount": "6500",
@@ -1378,7 +1389,7 @@
"tranche_end": "2023-05-01T00:00:00.000Z",
"total_added": "22500",
"total_removed": "3995.28612255",
"locked_amount": "10223.86049723756925",
"locked_amount": "10130.41983195211725",
"deposits": [
{
"amount": "7500",
@@ -1576,7 +1587,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "928642.9598472029154",
"locked_amount": "607199.059293409416755688",
"locked_amount": "603203.9854527480689673466",
"deposits": [
{
"amount": "1852091.69",
@@ -33558,8 +33569,8 @@
"tranche_start": "2022-03-05T00:00:00.000Z",
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "589730.8667090699299",
"locked_amount": "957554.874604284746674723657",
"total_removed": "592998.0503546212334",
"locked_amount": "951415.83704816660962319369",
"deposits": [
{
"amount": "1998.95815",
@@ -33738,6 +33749,11 @@
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0x8a19d30e4686bca650aa1c4e84a82d8a16d607e07828706cb758a6e17cab0190"
},
{
"amount": "3267.1836455513035",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0x96af4603ea4ac4ce4585d25325fd739e2380e315175e181c8ac5aec899e5861c"
},
{
"amount": "2536.282963529438",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -34093,6 +34109,12 @@
"tranche_id": 1,
"tx": "0x8a19d30e4686bca650aa1c4e84a82d8a16d607e07828706cb758a6e17cab0190"
},
{
"amount": "3267.1836455513035",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tranche_id": 1,
"tx": "0x96af4603ea4ac4ce4585d25325fd739e2380e315175e181c8ac5aec899e5861c"
},
{
"amount": "2536.282963529438",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -34359,8 +34381,8 @@
}
],
"total_tokens": "187637.95",
"withdrawn_tokens": "136494.1152043067095",
"remaining_tokens": "51143.8347956932905"
"withdrawn_tokens": "139761.298849858013",
"remaining_tokens": "47876.651150141987"
},
{
"address": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
@@ -34873,8 +34895,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "560317.67585805941693952",
"locked_amount": "8695115.6900884208257391762291393526601783",
"total_removed": "560497.18500562348693952",
"locked_amount": "8673347.0570783123228140520127045570383887",
"deposits": [
{
"amount": "16249.93",
@@ -35448,6 +35470,11 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xb6a33b8b8855789fbc2d0f9545ba5c2258e52f143d90bc75bbe2411bd2f9b4a5"
},
{
"amount": "179.50914756407",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0x86280b4d0cccc9e251d0f18fce5af974d0e1fb31a1aaf219725a27efb0d607f4"
},
{
"amount": "858.360074993579125",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -39471,6 +39498,12 @@
"tranche_id": 2,
"tx": "0xeb5f2401c9402d58fa4a7549ce2045a48a2c3b90ec6e812ca2f0059f1275e213"
},
{
"amount": "179.50914756407",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tranche_id": 2,
"tx": "0x86280b4d0cccc9e251d0f18fce5af974d0e1fb31a1aaf219725a27efb0d607f4"
},
{
"amount": "139.3487773806265",
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
@@ -39719,8 +39752,8 @@
}
],
"total_tokens": "12362.05",
"withdrawn_tokens": "5423.9024394185135",
"remaining_tokens": "6938.1475605814865"
"withdrawn_tokens": "5603.4115869825835",
"remaining_tokens": "6758.6384130174165"
},
{
"address": "0xb091D456d0dFCB94dcba6f355379056C5bb995fC",
@@ -40352,7 +40385,7 @@
"tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999",
"total_removed": "3921707.576409189114087282",
"locked_amount": "2305830.059961451513978716150659574",
"locked_amount": "2285733.39696055204772238928937325",
"deposits": [
{
"amount": "129284.449",
@@ -47188,7 +47221,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "5778205.3912159303",
"total_removed": "2730068.739915456784546642",
"locked_amount": "594143.998694685843745742950916108",
"locked_amount": "586203.563337309134341622543222115",
"deposits": [
{
"amount": "552496.6455",
@@ -49170,8 +49203,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "32476.7515062512685",
"locked_amount": "151730.043498066832591983753120252",
"total_removed": "32520.5457984892685",
"locked_amount": "150757.26292676673422831001319128",
"deposits": [
{
"amount": "3000",
@@ -55840,6 +55873,11 @@
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
"tx": "0xc0f953d7ecc45bfc1d7b69ecd491a63e8b00b0d732ff006bee008e917a04179f"
},
{
"amount": "43.794292238",
"user": "0x916E6Ce65e828e725Affdeda2C0a083071188109",
"tx": "0xdad3bca9bdda18abd6bbed7c1d618f60316bafc507591966b7a86bed3dc36b39"
},
{
"amount": "78.261187214",
"user": "0x479F059c46c6873C6B970A92911084b3eA036d56",
@@ -75978,6 +76016,12 @@
}
],
"withdrawals": [
{
"amount": "43.794292238",
"user": "0x916E6Ce65e828e725Affdeda2C0a083071188109",
"tranche_id": 5,
"tx": "0xdad3bca9bdda18abd6bbed7c1d618f60316bafc507591966b7a86bed3dc36b39"
},
{
"amount": "11.442313546",
"user": "0x916E6Ce65e828e725Affdeda2C0a083071188109",
@@ -75992,8 +76036,8 @@
}
],
"total_tokens": "200",
"withdrawn_tokens": "92.326249364",
"remaining_tokens": "107.673750636"
"withdrawn_tokens": "136.120541602",
"remaining_tokens": "63.879458398"
},
{
"address": "0x93D9D57409e0a1fD340b270Cd41368cc66392249",
@@ -15,7 +15,7 @@ export const ProposalFormTransactionDialog = ({
finalizedProposal,
TransactionDialog,
}: ProposalFormTransactionDialogProps) => {
// Render a custom complete UI if the proposal was rejected other wise
// Render a custom complete UI if the proposal was rejected otherwise
// pass undefined so that the default vega transaction dialog UI gets used
const completeContent = finalizedProposal?.rejectionReason ? (
<p>{finalizedProposal.rejectionReason}</p>
@@ -90,22 +90,15 @@ describe('Raw proposal form', () => {
},
result: {
data: {
busEvents: [
{
__typename: 'BusEvent',
type: Schema.BusEventType.Proposal,
event: {
__typename: 'Proposal',
id: '2fca514cebf9f465ae31ecb4c5721e3a6f5f260425ded887ca50ba15b81a5d50',
reference: 'proposal-reference',
state: Schema.ProposalState.STATE_OPEN,
rejectionReason:
Schema.ProposalRejectionReason
.PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE,
errorDetails: 'error-details',
},
},
],
proposals: {
__typename: 'Proposal',
id: '2fca514cebf9f465ae31ecb4c5721e3a6f5f260425ded887ca50ba15b81a5d50',
reference: 'proposal-reference',
state: Schema.ProposalState.STATE_OPEN,
rejectionReason:
Schema.ProposalRejectionReason.PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE,
errorDetails: 'error-details',
},
},
},
delay: 300,
@@ -7,13 +7,8 @@ fragment ProposalEventFields on Proposal {
}
subscription ProposalEvent($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Proposal]) {
type
event {
... on Proposal {
...ProposalEventFields
}
}
proposals(partyId: $partyId) {
...ProposalEventFields
}
}
@@ -10,7 +10,7 @@ export type ProposalEventSubscriptionVariables = Types.Exact<{
}>;
export type ProposalEventSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', type: Types.BusEventType, event: { __typename?: 'AccountEvent' } | { __typename?: 'Asset' } | { __typename?: 'AuctionEvent' } | { __typename?: 'Deposit' } | { __typename?: 'LiquidityProvision' } | { __typename?: 'LossSocialization' } | { __typename?: 'MarginLevels' } | { __typename?: 'Market' } | { __typename?: 'MarketData' } | { __typename?: 'MarketEvent' } | { __typename?: 'MarketTick' } | { __typename?: 'NodeSignature' } | { __typename?: 'OracleSpec' } | { __typename?: 'Order' } | { __typename?: 'Party' } | { __typename?: 'PositionResolution' } | { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null } | { __typename?: 'RiskFactor' } | { __typename?: 'SettleDistressed' } | { __typename?: 'SettlePosition' } | { __typename?: 'TimeUpdate' } | { __typename?: 'Trade' } | { __typename?: 'TransactionResult' } | { __typename?: 'TransferResponses' } | { __typename?: 'Vote' } | { __typename?: 'Withdrawal' } }> | null };
export type ProposalEventSubscription = { __typename?: 'Subscription', proposals: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null } };
export type UpdateNetworkParameterFieldsFragment = { __typename?: 'Proposal', id?: string | null, state: Types.ProposalState, datetime: any, terms: { __typename?: 'ProposalTerms', enactmentDatetime?: any | null, change: { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } } };
@@ -55,13 +55,8 @@ export const UpdateNetworkParameterFieldsFragmentDoc = gql`
`;
export const ProposalEventDocument = gql`
subscription ProposalEvent($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Proposal]) {
type
event {
... on Proposal {
...ProposalEventFields
}
}
proposals(partyId: $partyId) {
...ProposalEventFields
}
}
${ProposalEventFieldsFragmentDoc}`;
@@ -28,24 +28,15 @@ export const useProposalEvent = (transaction: VegaTxState) => {
variables: { partyId },
})
.subscribe(({ data }) => {
if (!data?.busEvents?.length) {
if (!data?.proposals) {
return;
}
// No types available for the subscription result
const matchingProposalEvent = data.busEvents.find((e) => {
if (e.event.__typename !== 'Proposal') {
return false;
}
// typo in 'proposals' - this should be singular
const proposal = data.proposals;
return e.event.id === id;
});
if (
matchingProposalEvent &&
matchingProposalEvent.event.__typename === 'Proposal'
) {
callback(matchingProposalEvent.event);
if (proposal.id === id) {
callback(proposal);
subRef.current?.unsubscribe();
}
});
@@ -1,18 +1,13 @@
fragment VoteEventFields on Vote {
fragment VoteEventFields on ProposalVote {
proposalId
value
datetime
vote {
value
datetime
}
}
subscription VoteEvent($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Vote]) {
type
event {
... on Vote {
proposalId
value
datetime
}
}
votes(partyId: $partyId) {
...VoteEventFields
}
}
@@ -3,36 +3,31 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type VoteEventFieldsFragment = { __typename?: 'Vote', proposalId: string, value: Types.VoteValue, datetime: any };
export type VoteEventFieldsFragment = { __typename?: 'ProposalVote', proposalId: string, vote: { __typename?: 'Vote', value: Types.VoteValue, datetime: any } };
export type VoteEventSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type VoteEventSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', type: Types.BusEventType, event: { __typename?: 'AccountEvent' } | { __typename?: 'Asset' } | { __typename?: 'AuctionEvent' } | { __typename?: 'Deposit' } | { __typename?: 'LiquidityProvision' } | { __typename?: 'LossSocialization' } | { __typename?: 'MarginLevels' } | { __typename?: 'Market' } | { __typename?: 'MarketData' } | { __typename?: 'MarketEvent' } | { __typename?: 'MarketTick' } | { __typename?: 'NodeSignature' } | { __typename?: 'OracleSpec' } | { __typename?: 'Order' } | { __typename?: 'Party' } | { __typename?: 'PositionResolution' } | { __typename?: 'Proposal' } | { __typename?: 'RiskFactor' } | { __typename?: 'SettleDistressed' } | { __typename?: 'SettlePosition' } | { __typename?: 'TimeUpdate' } | { __typename?: 'Trade' } | { __typename?: 'TransactionResult' } | { __typename?: 'TransferResponses' } | { __typename?: 'Vote', proposalId: string, value: Types.VoteValue, datetime: any } | { __typename?: 'Withdrawal' } }> | null };
export type VoteEventSubscription = { __typename?: 'Subscription', votes: { __typename?: 'ProposalVote', proposalId: string, vote: { __typename?: 'Vote', value: Types.VoteValue, datetime: any } } };
export const VoteEventFieldsFragmentDoc = gql`
fragment VoteEventFields on Vote {
fragment VoteEventFields on ProposalVote {
proposalId
value
datetime
vote {
value
datetime
}
}
`;
export const VoteEventDocument = gql`
subscription VoteEvent($partyId: ID!) {
busEvents(partyId: $partyId, batchSize: 0, types: [Vote]) {
type
event {
... on Vote {
proposalId
value
datetime
}
}
votes(partyId: $partyId) {
...VoteEventFields
}
}
`;
${VoteEventFieldsFragmentDoc}`;
/**
* __useVoteEventSubscription__
@@ -25,23 +25,14 @@ export const useVoteEvent = (transaction: VegaTxState) => {
variables: { partyId },
})
.subscribe(({ data }) => {
if (!data?.busEvents?.length) {
if (!data?.votes) {
return;
}
const matchingVoteEvent = data.busEvents.find((e) => {
if (e.event.__typename !== 'Vote') {
return false;
}
const vote = data.votes;
return e.event.proposalId === proposalId;
});
if (
matchingVoteEvent &&
matchingVoteEvent.event.__typename === 'Vote'
) {
callback(matchingVoteEvent.event);
if (vote.proposalId === proposalId) {
callback(vote);
subRef.current?.unsubscribe();
}
});
@@ -19,7 +19,10 @@ import type {
OperationVariables,
ApolloQueryResult,
QueryOptions,
ApolloError,
} from '@apollo/client';
import { GraphQLError } from 'graphql';
import type { Subscription, Observable } from 'zen-observable-ts';
type Item = {
@@ -58,12 +61,16 @@ const query: Query<QueryData> = {
};
const subscriptionQuery: Query<SubscriptionData> = query;
const getData = jest.fn((r: QueryData | null) => r?.data || null);
const getDelta = jest.fn((r: SubscriptionData) => r.data);
const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
query,
subscriptionQuery,
update,
getData: (r) => r?.data || null,
getDelta: (r) => r.data,
getData,
getDelta,
});
const combineData = jest.fn<
@@ -91,8 +98,8 @@ const paginatedSubscribe = makeDataProvider<
query,
subscriptionQuery,
update,
getData: (r) => r?.data || null,
getDelta: (r) => r.data,
getData,
getDelta,
pagination: {
first,
append: defaultAppend,
@@ -186,9 +193,20 @@ const clearPendingQueries = () => {
};
describe('data provider', () => {
beforeEach(() => {
clearPendingQueries();
callback.mockClear();
getData.mockClear();
clientQuery.mockClear();
clientSubscribeUnsubscribe.mockClear();
clientSubscribeSubscribe.mockClear();
});
it('memoize instance and unsubscribe if no subscribers', () => {
const subscription1 = subscribe(jest.fn(), client);
const subscription2 = subscribe(jest.fn(), client);
const variables = { var: 'val' };
const subscription1 = subscribe(jest.fn(), client, variables);
const subscription2 = subscribe(jest.fn(), client, { ...variables });
// const subscription1 = subscribe(jest.fn(), client);
// const subscription2 = subscribe(jest.fn(), client);
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(1);
subscription1.unsubscribe();
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(0);
@@ -197,7 +215,6 @@ describe('data provider', () => {
});
it('calls callback before and after initial fetch', async () => {
callback.mockClear();
const data: Item[] = [];
const subscription = subscribe(callback, client);
expect(callback.mock.calls.length).toBe(1);
@@ -210,6 +227,49 @@ describe('data provider', () => {
subscription.unsubscribe();
});
it('calls callback on error', async () => {
const subscription = subscribe(callback, client);
expect(callback.mock.calls.length).toBe(1);
expect(callback.mock.calls[0][0].data).toBe(null);
expect(callback.mock.calls[0][0].loading).toBe(true);
const error = new Error('Rejected by unit test');
await rejectQuery(error);
expect(getData).not.toBeCalled();
expect(callback.mock.calls.length).toBe(2);
expect(callback.mock.calls[1][0].error).toEqual(error);
expect(callback.mock.calls[1][0].loading).toBe(false);
subscription.unsubscribe();
});
it('calls successful callback on NotFound error on party path', async () => {
const subscription = subscribe(callback, client);
expect(callback.mock.calls.length).toBe(1);
expect(callback.mock.calls[0][0].data).toBe(null);
expect(callback.mock.calls[0][0].loading).toBe(true);
const error = new Error() as ApolloError;
const graphQLError = new GraphQLError(
'',
undefined,
undefined,
undefined,
['party'],
undefined,
{
type: 'NotFound',
}
);
error.graphQLErrors = [graphQLError];
const data: Data = [];
getData.mockReturnValueOnce(data);
await rejectQuery(error);
expect(getData).toHaveBeenCalledWith(null, undefined);
expect(callback.mock.calls.length).toBe(2);
expect(callback.mock.calls[1][0].data).toEqual(data);
expect(callback.mock.calls[1][0].error).toEqual(undefined);
expect(callback.mock.calls[1][0].loading).toBe(false);
subscription.unsubscribe();
});
it('calls update and callback on each update', async () => {
const data: Item[] = [];
const subscription = subscribe(callback, client);
@@ -228,8 +288,7 @@ describe('data provider', () => {
subscription.unsubscribe();
});
it("don't calls callback on update if data doesn't", async () => {
callback.mockClear();
it("don't calls callback on update if data doesn't change", async () => {
const data: Item[] = [];
const subscription = subscribe(callback, client);
await resolveQuery({ data });
@@ -247,10 +306,6 @@ describe('data provider', () => {
});
it('refetch data on reload', async () => {
clearPendingQueries();
clientQuery.mockClear();
clientSubscribeUnsubscribe.mockClear();
clientSubscribeSubscribe.mockClear();
const data: Item[] = [];
const subscription = subscribe(callback, client);
await resolveQuery({ data });
@@ -263,9 +318,6 @@ describe('data provider', () => {
});
it('refetch data and restart subscription on reload with force', async () => {
clientQuery.mockClear();
clientSubscribeUnsubscribe.mockClear();
clientSubscribeSubscribe.mockClear();
const data: Item[] = [];
const subscription = subscribe(callback, client);
await resolveQuery({ data });
@@ -278,7 +330,6 @@ describe('data provider', () => {
});
it('calls callback on flush', async () => {
callback.mockClear();
const data: Item[] = [];
const subscription = subscribe(callback, client);
await resolveQuery({ data });
@@ -289,8 +340,6 @@ describe('data provider', () => {
});
it('fills data with nulls if pagination is enabled', async () => {
callback.mockClear();
clearPendingQueries();
const totalCount = 1000;
const data: Item[] = new Array(first).fill(null).map((v, i) => ({
cursor: i.toString(),
@@ -311,7 +360,6 @@ describe('data provider', () => {
});
it('loads requested data blocks and inserts data with total count', async () => {
callback.mockClear();
const totalCount = 1000;
const subscription = paginatedSubscribe(callback, client);
await resolveQuery({
@@ -436,7 +484,6 @@ describe('data provider', () => {
});
it('loads requested data blocks and inserts data without totalCount', async () => {
callback.mockClear();
const totalCount = undefined;
const subscription = paginatedSubscribe(callback, client);
await resolveQuery({
@@ -407,6 +407,15 @@ function makeDataProviderInternal<
}
};
const onError = (e: Error) => {
error = e;
if (subscription) {
subscription.unsubscribe();
subscription = undefined;
}
notifyAll();
};
const initialize = async () => {
if (subscription) {
if (resetTimer) {
@@ -427,14 +436,7 @@ function makeDataProviderInternal<
variables,
fetchPolicy,
})
.subscribe(onNext, (e) => {
error = e as Error;
if (subscription) {
subscription.unsubscribe();
subscription = undefined;
}
notifyAll();
});
.subscribe(onNext, onError);
}
await initialFetch();
};