From 91207d31ee800fc53647ce37e935a852f6d94ce5 Mon Sep 17 00:00:00 2001 From: Joe Tsang <30622993+jtsang586@users.noreply.github.com> Date: Wed, 10 May 2023 16:03:47 +0100 Subject: [PATCH 01/19] chore(governance): fix failing validator tests (#3703) --- .../src/integration/flow/staking-flow.cy.ts | 7 +++++-- .../src/integration/view/validators.cy.ts | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts b/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts index f7683bb31..abcdbb8c1 100644 --- a/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts @@ -7,6 +7,7 @@ import { waitForSpinner, navigateTo, navigation, + turnTelemetryOff, } from '../../support/common.functions'; import { clickOnValidatorFromList, @@ -56,6 +57,7 @@ context( // 2001-STKE-002, 2001-STKE-032 before('visit staking tab and connect vega wallet', function () { cy.visit('/'); + cy.validatorsSelfDelegate(); ethereumWalletConnect(); // this is a workaround for #2422 which can be removed once issue is resolved cy.associateTokensToVegaWallet('4'); @@ -67,6 +69,7 @@ context( 'teardown wallet & drill into a specific validator', function () { cy.clearLocalStorage(); + turnTelemetryOff(); cy.reload(); waitForSpinner(); cy.connectVegaWallet(); @@ -252,10 +255,10 @@ context( waitForBeginningOfEpoch(); cy.getByTestId(stakeValidatorListStakePercentage).should( 'have.text', - '100%' + '50.02%' ); navigateTo(navigation.validators); - validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%'); + validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%'); } ); diff --git a/apps/governance-e2e/src/integration/view/validators.cy.ts b/apps/governance-e2e/src/integration/view/validators.cy.ts index 15186eb37..2c3ffce97 100644 --- a/apps/governance-e2e/src/integration/view/validators.cy.ts +++ b/apps/governance-e2e/src/integration/view/validators.cy.ts @@ -29,7 +29,10 @@ const performancePenaltyToolTip = '[data-testid="performance-penalty-tooltip"]'; const overstakedPenaltyToolTip = '[data-testid="overstaked-penalty-tooltip"]'; const totalPenaltyToolTip = '[data-testid="total-penalty-tooltip"]'; const epochCountDown = '[data-testid="epoch-countdown"]'; -const stakeNumberRegex = /^\d*\.?\d*$/; +const stakeNumberRegex = /^\d{1,3}(,\d{3})*(\.\d+)?$/; + +// If running locally, validators need to have self-stake to be displayed +// Run cy.validatorsSelfDelegate() in before hook context('Validators Page - verify elements on page', function () { before('navigate to validators page', function () { @@ -84,13 +87,13 @@ context('Validators Page - verify elements on page', function () { cy.get(stakedByOperatorToolTip) .invoke('text') - .should('contain', 'Staked by operator: 0.00'); + .should('contain', 'Staked by operator: 3,000.00'); cy.get(stakedByDelegatesToolTip) .invoke('text') .should('contain', 'Staked by delegates: 0.00'); cy.get(totalStakedToolTip) .invoke('text') - .should('contain', 'Total stake: 0.00'); + .should('contain', 'Total stake: 3,000.00'); }); it('Should be able to see validator normalised voting power', function () { @@ -106,10 +109,10 @@ context('Validators Page - verify elements on page', function () { cy.get(unnormalisedVotingPowerToolTip) .invoke('text') - .should('contain', 'Unnormalised voting power: 0.00%'); + .should('contain', 'Unnormalised voting power: 20.00%'); cy.get(normalisedVotingPowerToolTip) .invoke('text') - .should('contain', 'Normalised voting power: 0.10%'); + .should('contain', 'Normalised voting power: 50.00%'); }); // 2002-SINC-018 @@ -126,13 +129,13 @@ context('Validators Page - verify elements on page', function () { cy.get(performancePenaltyToolTip) .invoke('text') - .should('contain', 'Performance penalty: 100.00%'); + .should('contain', 'Performance penalty: 0.00%'); cy.get(overstakedPenaltyToolTip) .invoke('text') - .should('contain', 'Overstaked penalty:'); // value not asserted due to #2886 + .should('contain', 'Overstaked penalty: 60.00%'); // value not asserted due to #2886 cy.get(totalPenaltyToolTip) .invoke('text') - .should('contain', 'Total penalties: 0.00%'); + .should('contain', 'Total penalties: 60.00%'); }); it('Should be able to see validator pending stake', function () { From dc7832ac81328fee482e294efd8352b46bb93844 Mon Sep 17 00:00:00 2001 From: Maciek Date: Wed, 10 May 2023 17:26:27 +0200 Subject: [PATCH 02/19] chore(candles-chart): fill up missing candles (#3664) --- .../candles-chart/src/lib/data-source.spec.ts | 280 ++++++++++++++++++ libs/candles-chart/src/lib/data-source.ts | 91 +++++- 2 files changed, 368 insertions(+), 3 deletions(-) create mode 100644 libs/candles-chart/src/lib/data-source.spec.ts diff --git a/libs/candles-chart/src/lib/data-source.spec.ts b/libs/candles-chart/src/lib/data-source.spec.ts new file mode 100644 index 000000000..50cc226b0 --- /dev/null +++ b/libs/candles-chart/src/lib/data-source.spec.ts @@ -0,0 +1,280 @@ +import { VegaDataSource } from './data-source'; +import type { ApolloClient } from '@apollo/client'; +import { Interval } from 'pennant'; +import type { + CandleFieldsFragment, + CandlesQuery, +} from './__generated__/Candles'; +import * as Schema from '@vegaprotocol/types'; + +const returnDataMocks = (nodes: CandleFieldsFragment[]): CandlesQuery => { + return { + data: { + market: { + decimalPlaces: 1, + positionDecimalPlaces: 1, + candlesConnection: { + edges: nodes.map((node) => ({ node })), + }, + }, + }, + } as CandlesQuery; +}; + +const dataMocks: { [key in Schema.Interval]: Partial[] } = + { + [Schema.Interval.INTERVAL_I1M]: [ + { + __typename: 'Candle', + periodStart: '2023-05-10T12:00:00Z', + lastUpdateInPeriod: '', + close: '10', + volume: '1', + }, + { + __typename: 'Candle', + periodStart: '2023-05-10T12:05:00Z', + lastUpdateInPeriod: '', + close: '5', + volume: '2', + }, + ], + [Schema.Interval.INTERVAL_I5M]: [ + { + __typename: 'Candle', + periodStart: '2023-05-10T12:00:00Z', + lastUpdateInPeriod: '', + close: '10', + volume: '1', + }, + { + __typename: 'Candle', + periodStart: '2023-05-10T12:25:00Z', + lastUpdateInPeriod: '', + close: '5', + volume: '2', + }, + ], + [Schema.Interval.INTERVAL_I15M]: [ + { + __typename: 'Candle', + periodStart: '2023-05-10T12:00:00Z', + lastUpdateInPeriod: '', + close: '10', + volume: '1', + }, + { + __typename: 'Candle', + periodStart: '2023-05-10T13:15:00Z', + lastUpdateInPeriod: '', + close: '5', + volume: '2', + }, + ], + [Schema.Interval.INTERVAL_I1H]: [ + { + __typename: 'Candle', + periodStart: '2023-05-10T12:00:00Z', + lastUpdateInPeriod: '', + close: '10', + volume: '1', + }, + { + __typename: 'Candle', + periodStart: '2023-05-10T17:00:00Z', + lastUpdateInPeriod: '', + close: '5', + volume: '2', + }, + ], + [Schema.Interval.INTERVAL_I6H]: [ + { + __typename: 'Candle', + periodStart: '2023-05-10T12:00:00Z', + lastUpdateInPeriod: '', + close: '10', + volume: '1', + }, + { + __typename: 'Candle', + periodStart: '2023-05-11T18:00:00Z', + lastUpdateInPeriod: '', + close: '5', + volume: '2', + }, + ], + [Schema.Interval.INTERVAL_I1D]: [ + { + __typename: 'Candle', + periodStart: '2023-05-10T00:00:00Z', + lastUpdateInPeriod: '', + close: '10', + volume: '1', + }, + { + __typename: 'Candle', + periodStart: '2023-05-15T00:00:00Z', + lastUpdateInPeriod: '', + close: '5', + volume: '2', + }, + ], + [Schema.Interval.INTERVAL_BLOCK]: [], + }; + +describe('VegaDataSource', () => { + const marketId = 'marketId'; + const partyId = 'partyId'; + const client = { + query: jest.fn().mockImplementation(({ variables: { interval } }) => { + return returnDataMocks( + dataMocks[interval as Schema.Interval] as CandleFieldsFragment[] + ); + }), + } as unknown as ApolloClient; + + it('should be properly initialized', () => { + const dataSource = new VegaDataSource(client, marketId, partyId); + expect(dataSource).toBeInstanceOf(VegaDataSource); + expect(dataSource.onReady).toBeDefined(); + expect(dataSource.query).toBeDefined(); + expect(dataSource.subscribeData).toBeDefined(); + expect(dataSource.unsubscribeData).toBeDefined(); + expect(dataSource.decimalPlaces).toBeDefined(); + expect(dataSource.positionDecimalPlaces).toBeDefined(); + }); + + describe('query should return continuous data', () => { + it('when interval is I1M', async () => { + const dataSource = new VegaDataSource(client, marketId, partyId); + const data = await dataSource.query(Interval.I1M, ''); + expect(data).toHaveLength(6); + expect(data[1]).toStrictEqual({ + date: new Date('2023-05-10T12:01:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + expect(data[2]).toStrictEqual({ + date: new Date('2023-05-10T12:02:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + }); + + it('when interval is I5M', async () => { + const dataSource = new VegaDataSource(client, marketId, partyId); + const data = await dataSource.query(Interval.I5M, ''); + expect(data).toHaveLength(6); + expect(data[1]).toStrictEqual({ + date: new Date('2023-05-10T12:05:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + expect(data[2]).toStrictEqual({ + date: new Date('2023-05-10T12:10:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + }); + + it('when interval is I15M', async () => { + const dataSource = new VegaDataSource(client, marketId, partyId); + const data = await dataSource.query(Interval.I15M, ''); + expect(data).toHaveLength(6); + expect(data[1]).toStrictEqual({ + date: new Date('2023-05-10T12:15:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + expect(data[2]).toStrictEqual({ + date: new Date('2023-05-10T12:30:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + }); + + it('when interval is I1H', async () => { + const dataSource = new VegaDataSource(client, marketId, partyId); + const data = await dataSource.query(Interval.I1H, ''); + expect(data).toHaveLength(6); + expect(data[1]).toStrictEqual({ + date: new Date('2023-05-10T13:00:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + expect(data[2]).toStrictEqual({ + date: new Date('2023-05-10T14:00:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + }); + + it('when interval is I6H', async () => { + const dataSource = new VegaDataSource(client, marketId, partyId); + const data = await dataSource.query(Interval.I6H, ''); + expect(data).toHaveLength(6); + expect(data[1]).toStrictEqual({ + date: new Date('2023-05-10T18:00:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + expect(data[2]).toStrictEqual({ + date: new Date('2023-05-11T00:00:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + }); + + it('when interval is I1D', async () => { + const dataSource = new VegaDataSource(client, marketId, partyId); + const data = await dataSource.query(Interval.I1D, ''); + expect(data).toHaveLength(6); + expect(data[1]).toStrictEqual({ + date: new Date('2023-05-11T00:00:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + expect(data[2]).toStrictEqual({ + date: new Date('2023-05-12T00:00:00Z'), + high: 1, + low: 1, + open: 1, + close: 1, + volume: 0, + }); + }); + }); +}); diff --git a/libs/candles-chart/src/lib/data-source.ts b/libs/candles-chart/src/lib/data-source.ts index 237cadad2..fb1e7494a 100644 --- a/libs/candles-chart/src/lib/data-source.ts +++ b/libs/candles-chart/src/lib/data-source.ts @@ -1,4 +1,11 @@ import type { ApolloClient } from '@apollo/client'; +import type { Duration } from 'date-fns'; +import { + add, + differenceInDays, + differenceInHours, + differenceInMinutes, +} from 'date-fns'; import type { Candle, DataSource } from 'pennant'; import { Interval as PennantInterval } from 'pennant'; @@ -153,7 +160,6 @@ export class VegaDataSource implements DataSource { }, fetchPolicy: 'no-cache', }); - if (data?.market?.candlesConnection?.edges) { const decimalPlaces = data.market.decimalPlaces; const positionDecimalPlaces = data.market.positionDecimalPlaces; @@ -163,8 +169,8 @@ export class VegaDataSource implements DataSource { .filter((node): node is CandleFieldsFragment => !!node) .map((node) => parseCandle(node, decimalPlaces, positionDecimalPlaces) - ); - + ) + .reduce(checkGranulationContinuity(interval), []); return candles; } else { return []; @@ -213,6 +219,85 @@ export class VegaDataSource implements DataSource { } } +const getDuration = ( + interval: PennantInterval, + multiplier: number +): Duration => { + switch (interval) { + case 'I1D': + return { + days: 1 * multiplier, + }; + case 'I1H': + return { + hours: 1 * multiplier, + }; + case 'I1M': + return { + minutes: 1 * multiplier, + }; + case 'I5M': + return { + minutes: 5 * multiplier, + }; + case 'I6H': + return { + hours: 6 * multiplier, + }; + case 'I15M': + return { + minutes: 15 * multiplier, + }; + } +}; + +const getDifference = ( + interval: PennantInterval, + dateLeft: Date, + dateRight: Date +): number => { + switch (interval) { + case 'I1D': + return differenceInDays(dateRight, dateLeft); + case 'I6H': + return differenceInHours(dateRight, dateLeft) / 6; + case 'I1H': + return differenceInHours(dateRight, dateLeft); + case 'I15M': + return differenceInMinutes(dateRight, dateLeft) / 15; + case 'I5M': + return differenceInMinutes(dateRight, dateLeft) / 5; + case 'I1M': + return differenceInMinutes(dateRight, dateLeft); + } +}; + +const checkGranulationContinuity = + (interval: PennantInterval) => + (agg: Candle[], candle: Candle, i: number): Candle[] => { + if (agg.length && i) { + const previous = agg[agg.length - 1]; + const difference = getDifference(interval, previous.date, candle.date); + if (difference > 1) { + for (let j = 1; j < difference; j++) { + const duration = getDuration(interval, j); + const newStartDate = add(previous.date, duration); + const newParsedCandle: Candle = { + date: newStartDate, + high: previous.close, + low: previous.close, + open: previous.close, + close: previous.close, + volume: 0, + }; + agg.push(newParsedCandle); + } + } + } + agg.push(candle); + return agg; + }; + function parseCandle( candle: CandleFieldsFragment, decimalPlaces: number, From b4b24167801a0c09fecdc7d8889b46e2d3a711b3 Mon Sep 17 00:00:00 2001 From: Sam Keen Date: Wed, 10 May 2023 17:23:37 +0100 Subject: [PATCH 03/19] fix(governance): my stake share 2 dp (#3685) --- .../home/validator-tables/consensus-validators-table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx b/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx index e9cf5c7c0..7395a3f50 100644 --- a/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx +++ b/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx @@ -216,7 +216,7 @@ export const ConsensusValidatorsTable = ({ : undefined, [ValidatorFields.PENDING_USER_STAKE]: pendingUserStake, [ValidatorFields.USER_STAKE_SHARE]: userStakeShare - ? formatNumberPercentage(new BigNumber(userStakeShare)) + ? formatNumberPercentage(new BigNumber(userStakeShare), 2) : undefined, }; } From e30d48555ece2da903e62d601405e470be35cedf Mon Sep 17 00:00:00 2001 From: dexturr Date: Thu, 11 May 2023 00:16:19 +0000 Subject: [PATCH 04/19] chore: update tranches Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- apps/static/src/assets/mainnet-tranches.json | 62 +++++++++++++------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/apps/static/src/assets/mainnet-tranches.json b/apps/static/src/assets/mainnet-tranches.json index 24d490442..8fd33488c 100644 --- a/apps/static/src/assets/mainnet-tranches.json +++ b/apps/static/src/assets/mainnet-tranches.json @@ -49,7 +49,7 @@ "tranche_end": "2023-05-20T00:00:00.000Z", "total_added": "19242.125", "total_removed": "1979.64045368475", - "locked_amount": "6088.8928113908174973875", + "locked_amount": "5765.37716116898176655", "deposits": [ { "amount": "188", @@ -4907,7 +4907,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "86666.297", "total_removed": "0", - "locked_amount": "49504.9919953353951513585", + "locked_amount": "49385.22948401617067479", "deposits": [ { "amount": "86666.297", @@ -4973,7 +4973,7 @@ "tranche_end": "2023-06-01T00:00:00.000Z", "total_added": "2500", "total_removed": "0", - "locked_amount": "295.23443859381355", + "locked_amount": "288.3060515873015", "deposits": [ { "amount": "2500", @@ -5006,7 +5006,7 @@ "tranche_end": "2023-11-01T00:00:00.000Z", "total_added": "15000.000000000000015", "total_removed": "0", - "locked_amount": "14224.9782986111115142249782986111115", + "locked_amount": "14183.8598278985505141838598278985505", "deposits": [ { "amount": "1.5e-14", @@ -5094,7 +5094,7 @@ "tranche_end": "2023-09-01T00:00:00.000Z", "total_added": "17500", "total_removed": "0", - "locked_amount": "10794.17758026368775", + "locked_amount": "10746.20603109903325", "deposits": [ { "amount": "12500", @@ -5360,8 +5360,8 @@ "tranche_start": "2023-02-01T00:00:00.000Z", "tranche_end": "2023-08-01T00:00:00.000Z", "total_added": "37500", - "total_removed": "18077.0118744", - "locked_amount": "17091.10506829343025", + "total_removed": "18302.01762945", + "locked_amount": "16986.605087476978875", "deposits": [ { "amount": "7500", @@ -5375,6 +5375,11 @@ } ], "withdrawals": [ + { + "amount": "225.00575505", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tx": "0x0a46fa3cc0154727ae4c7abca97bd7e26e6835018f96cf3a3860a9fcc791b9a4" + }, { "amount": "164.727209925", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", @@ -5553,6 +5558,12 @@ } ], "withdrawals": [ + { + "amount": "225.00575505", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tranche_id": 34, + "tx": "0x0a46fa3cc0154727ae4c7abca97bd7e26e6835018f96cf3a3860a9fcc791b9a4" + }, { "amount": "164.727209925", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", @@ -5735,8 +5746,8 @@ } ], "total_tokens": "7500", - "withdrawn_tokens": "3867.2532036", - "remaining_tokens": "3632.7467964" + "withdrawn_tokens": "4092.25895865", + "remaining_tokens": "3407.74104135" }, { "address": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600", @@ -5780,7 +5791,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "129999.45", "total_removed": "0", - "locked_amount": "49459.824919096584707505", + "locked_amount": "49340.17167599985069423", "deposits": [ { "amount": "129999.45", @@ -5813,7 +5824,7 @@ "tranche_end": "2024-04-01T00:00:00.000Z", "total_added": "54144.7663", "total_removed": "0", - "locked_amount": "48300.2481374426486922947", + "locked_amount": "48225.63094296696524765457", "deposits": [ { "amount": "54144.7663", @@ -5846,7 +5857,7 @@ "tranche_end": "2023-09-03T00:00:00.000Z", "total_added": "62600", "total_removed": "0", - "locked_amount": "19807.852061136476024", + "locked_amount": "19721.346308980209976", "deposits": [ { "amount": "10000", @@ -6039,7 +6050,7 @@ "tranche_end": "2023-09-17T00:00:00.000Z", "total_added": "5000", "total_removed": "0", - "locked_amount": "1773.87763191273475", + "locked_amount": "1766.96822678843235", "deposits": [ { "amount": "5000", @@ -7108,7 +7119,7 @@ "tranche_end": "2023-06-02T00:00:00.000Z", "total_added": "1939928.38", "total_removed": "1709370.7872515768348", - "locked_amount": "119547.7788438730317094704", + "locked_amount": "116867.02862596270877676152", "deposits": [ { "amount": "1852091.69", @@ -40980,7 +40991,7 @@ "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "3732368.4671", "total_removed": "715655.108029600523393", - "locked_amount": "208204.638696483881349131871", + "locked_amount": "204085.258949651111693047023", "deposits": [ { "amount": "1998.95815", @@ -42372,8 +42383,8 @@ "tranche_start": "2022-06-05T00:00:00.000Z", "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "15870102.715470999700000001", - "total_removed": "872635.89843522227071852", - "locked_amount": "6037967.8664430882362406121449295313314409", + "total_removed": "873375.18460711694221852", + "locked_amount": "6023360.8103502786888670577764109678751014", "deposits": [ { "amount": "16249.93", @@ -42887,6 +42898,11 @@ "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "tx": "0x4301fcb38d16c1f6aa4a93a18a277a4e77eb3b4565bf98ca6218f6598b78b90b" }, + { + "amount": "739.2861718946715", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tx": "0x989d22d5ba66353cb132b5643100a99e78133e5d40aef1ac91ed6ab0a2290299" + }, { "amount": "10150.87581603206683", "user": "0xe3eB4CF43C072658401996b71D43eE26E573562D", @@ -45067,6 +45083,12 @@ "tranche_id": 2, "tx": "0x4301fcb38d16c1f6aa4a93a18a277a4e77eb3b4565bf98ca6218f6598b78b90b" }, + { + "amount": "739.2861718946715", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tranche_id": 2, + "tx": "0x989d22d5ba66353cb132b5643100a99e78133e5d40aef1ac91ed6ab0a2290299" + }, { "amount": "913.910324501590625", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", @@ -46623,8 +46645,8 @@ } ], "total_tokens": "259998.8875", - "withdrawn_tokens": "160546.342221561692", - "remaining_tokens": "99452.545278438308" + "withdrawn_tokens": "161285.6283934563635", + "remaining_tokens": "98713.2591065436365" }, { "address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c", @@ -59149,7 +59171,7 @@ "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "472355.6199999996", "total_removed": "44544.1737890903416", - "locked_amount": "32991.215149911803725776786707268", + "locked_amount": "32338.47588164759683463159665146", "deposits": [ { "amount": "3000", From bd679957e2de38abb1a1bbc33e561788efae42be Mon Sep 17 00:00:00 2001 From: dexturr Date: Thu, 11 May 2023 06:07:33 +0000 Subject: [PATCH 05/19] chore: update tranches Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- apps/static/src/assets/mainnet-tranches.json | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/static/src/assets/mainnet-tranches.json b/apps/static/src/assets/mainnet-tranches.json index 8fd33488c..a79eb3079 100644 --- a/apps/static/src/assets/mainnet-tranches.json +++ b/apps/static/src/assets/mainnet-tranches.json @@ -49,7 +49,7 @@ "tranche_end": "2023-05-20T00:00:00.000Z", "total_added": "19242.125", "total_removed": "1979.64045368475", - "locked_amount": "5765.37716116898176655", + "locked_amount": "5608.9383879726076446", "deposits": [ { "amount": "188", @@ -4907,7 +4907,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "86666.297", "total_removed": "0", - "locked_amount": "49385.22948401617067479", + "locked_amount": "49327.3172923405910546417", "deposits": [ { "amount": "86666.297", @@ -4973,7 +4973,7 @@ "tranche_end": "2023-06-01T00:00:00.000Z", "total_added": "2500", "total_removed": "0", - "locked_amount": "288.3060515873015", + "locked_amount": "284.955770502645375", "deposits": [ { "amount": "2500", @@ -5006,7 +5006,7 @@ "tranche_end": "2023-11-01T00:00:00.000Z", "total_added": "15000.000000000000015", "total_removed": "0", - "locked_amount": "14183.8598278985505141838598278985505", + "locked_amount": "14163.9766379830905141639766379830905", "deposits": [ { "amount": "1.5e-14", @@ -5094,7 +5094,7 @@ "tranche_end": "2023-09-01T00:00:00.000Z", "total_added": "17500", "total_removed": "0", - "locked_amount": "10746.20603109903325", + "locked_amount": "10723.00897619766325", "deposits": [ { "amount": "12500", @@ -5361,7 +5361,7 @@ "tranche_end": "2023-08-01T00:00:00.000Z", "total_added": "37500", "total_removed": "18302.01762945", - "locked_amount": "16986.605087476978875", + "locked_amount": "16936.07322360343725", "deposits": [ { "amount": "7500", @@ -5791,7 +5791,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "129999.45", "total_removed": "0", - "locked_amount": "49340.17167599985069423", + "locked_amount": "49282.312321912380332265", "deposits": [ { "amount": "129999.45", @@ -5824,7 +5824,7 @@ "tranche_end": "2024-04-01T00:00:00.000Z", "total_added": "54144.7663", "total_removed": "0", - "locked_amount": "48225.63094296696524765457", + "locked_amount": "48189.54915726316779685587", "deposits": [ { "amount": "54144.7663", @@ -5857,7 +5857,7 @@ "tranche_end": "2023-09-03T00:00:00.000Z", "total_added": "62600", "total_removed": "0", - "locked_amount": "19721.346308980209976", + "locked_amount": "19679.51570903094634", "deposits": [ { "amount": "10000", @@ -6050,7 +6050,7 @@ "tranche_end": "2023-09-17T00:00:00.000Z", "total_added": "5000", "total_removed": "0", - "locked_amount": "1766.96822678843235", + "locked_amount": "1763.627124556063", "deposits": [ { "amount": "5000", @@ -7119,7 +7119,7 @@ "tranche_end": "2023-06-02T00:00:00.000Z", "total_added": "1939928.38", "total_removed": "1709370.7872515768348", - "locked_amount": "116867.02862596270877676152", + "locked_amount": "115570.728817751808474185", "deposits": [ { "amount": "1852091.69", @@ -40991,7 +40991,7 @@ "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "3732368.4671", "total_removed": "715655.108029600523393", - "locked_amount": "204085.258949651111693047023", + "locked_amount": "202093.2974680882797136777084", "deposits": [ { "amount": "1998.95815", @@ -42384,7 +42384,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "15870102.715470999700000001", "total_removed": "873375.18460711694221852", - "locked_amount": "6023360.8103502786888670577764109678751014", + "locked_amount": "6016297.4428328087189762607645230040375777", "deposits": [ { "amount": "16249.93", @@ -59171,7 +59171,7 @@ "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "472355.6199999996", "total_removed": "44544.1737890903416", - "locked_amount": "32338.47588164759683463159665146", + "locked_amount": "32022.838198356764871382775241", "deposits": [ { "amount": "3000", From d44392bebf16440f97ca50ec0a177465fbde68b8 Mon Sep 17 00:00:00 2001 From: daro-maj <119658839+daro-maj@users.noreply.github.com> Date: Thu, 11 May 2023 08:18:00 +0200 Subject: [PATCH 06/19] test(trading): show full oracle profile info in markets test (#3695) --- apps/trading-e2e/src/integration/market-info.cy.ts | 14 +++++++++++++- apps/trading-e2e/src/integration/wallet-eth.cy.ts | 2 -- libs/datagrid/src/lib/ag-grid/use-column-sizes.ts | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/trading-e2e/src/integration/market-info.cy.ts b/apps/trading-e2e/src/integration/market-info.cy.ts index 2798325c7..0c9ee83b9 100644 --- a/apps/trading-e2e/src/integration/market-info.cy.ts +++ b/apps/trading-e2e/src/integration/market-info.cy.ts @@ -6,6 +6,7 @@ const row = 'key-value-table-row'; const marketTitle = 'accordion-title'; const externalLink = 'external-link'; const accordionContent = 'accordion-content'; +const providerName = 'provider-name'; describe('market info is displayed', { tags: '@smoke' }, () => { beforeEach(() => { @@ -181,9 +182,20 @@ describe('market info is displayed', { tags: '@smoke' }, () => { cy.getByTestId(marketTitle).contains('Oracle').click(); cy.getByTestId(accordionContent) - .getByTestId('provider-name') + .getByTestId(providerName) .and('contain', 'Another oracle'); + cy.getByTestId(providerName).should('be.visible').click(); + + cy.getByTestId('dialog-content') + .eq(1) + .within(() => { + cy.getByTestId('block-explorer-link').contains('Block explorer'); + cy.getByTestId('github-link').contains('Oracle repository'); + cy.getByTestId('verified-accounts').contains('0 proofs of ownership'); + }); + cy.getByTestId('dialog-close').click(); + cy.getByTestId(accordionContent) .getByTestId('verified-proofs') .and('contain', '1'); diff --git a/apps/trading-e2e/src/integration/wallet-eth.cy.ts b/apps/trading-e2e/src/integration/wallet-eth.cy.ts index 545fcd30f..f1cab6539 100644 --- a/apps/trading-e2e/src/integration/wallet-eth.cy.ts +++ b/apps/trading-e2e/src/integration/wallet-eth.cy.ts @@ -17,7 +17,6 @@ describe('ethereum wallet', { tags: '@smoke', testIsolation: true }, () => { it('can connect', () => { // 0004-EWAL-001 - cy.wait('@NetworkParams'); cy.getByTestId('Deposits').click(); cy.getByTestId('deposit-button').click(); cy.getByTestId('connect-eth-wallet-btn').click(); @@ -30,7 +29,6 @@ describe('ethereum wallet', { tags: '@smoke', testIsolation: true }, () => { it('should see QR code modal for WalletConnect', () => { // 0004-EWAL-003 - cy.wait('@NetworkParams'); cy.getByTestId('Deposits').click(); cy.getByTestId('deposit-button').click(); cy.getByTestId('connect-eth-wallet-btn').click(); diff --git a/libs/datagrid/src/lib/ag-grid/use-column-sizes.ts b/libs/datagrid/src/lib/ag-grid/use-column-sizes.ts index 7c7a67ca8..c364a3a74 100644 --- a/libs/datagrid/src/lib/ag-grid/use-column-sizes.ts +++ b/libs/datagrid/src/lib/ag-grid/use-column-sizes.ts @@ -97,7 +97,7 @@ export const useColumnSizes = ({ const setSizes = useCallback( (apiEvent: GridReadyEvent | GridSizeChangedEvent) => { if (!storeKey || !Object.keys(sizes).length || !widthRef.current) { - apiEvent.api.sizeColumnsToFit(); + apiEvent?.api.sizeColumnsToFit(); } else { const recalculatedSizes = recalculateSizes(sizes); const newSizes = Object.entries(recalculatedSizes).map( From b4c7dc6f593ecbeadab565435c67757b82200cb6 Mon Sep 17 00:00:00 2001 From: Sam Keen Date: Thu, 11 May 2023 11:21:16 +0100 Subject: [PATCH 07/19] fix(governance): more thorough catch for url in error reporting (#3686) --- apps/governance/src/app.tsx | 51 ++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/apps/governance/src/app.tsx b/apps/governance/src/app.tsx index 0e44162cc..911b5ab40 100644 --- a/apps/governance/src/app.tsx +++ b/apps/governance/src/app.tsx @@ -2,7 +2,6 @@ import './i18n'; import React, { useEffect } from 'react'; import * as Sentry from '@sentry/react'; -import { Integrations } from '@sentry/tracing'; import { BrowserRouter as Router, useLocation } from 'react-router-dom'; import { AppLoader } from './app-loader'; import { NetworkInfo } from '@vegaprotocol/network-info'; @@ -184,6 +183,10 @@ const ScrollToTop = () => { return null; }; +const removeQueryParams = (url: string) => { + return url.split('?')[0]; +}; + const AppContainer = () => { const { config, loading, error } = useEthereumConfig(); const { @@ -204,22 +207,46 @@ const AppContainer = () => { if (ENV.dsn && telemetryOn) { Sentry.init({ dsn: ENV.dsn, - integrations: [new Integrations.BrowserTracing()], tracesSampleRate: 0.1, enabled: true, environment: VEGA_ENV, release: GIT_COMMIT_HASH, beforeSend(event) { - if (event.request?.url?.includes('/claim?')) { - return { - ...event, - request: { - ...event.request, - url: event.request?.url.split('?')[0], - }, - }; - } - return event; + const requestUrl = event.request?.url; + const transaction = event.transaction; + + const updatedRequest = + requestUrl && requestUrl.includes('/test?') + ? { ...event.request, url: removeQueryParams(requestUrl) } + : event.request; + + const updatedTransaction = + transaction && transaction.includes('/test?') + ? removeQueryParams(transaction) + : transaction; + + const updatedBreadcrumbs = event.breadcrumbs?.map((breadcrumb) => { + if ( + breadcrumb.type === 'navigation' && + breadcrumb.data?.to?.includes('/test?') + ) { + return { + ...breadcrumb, + data: { + ...breadcrumb.data, + to: removeQueryParams(breadcrumb.data.to), + }, + }; + } + return breadcrumb; + }); + + return { + ...event, + request: updatedRequest, + transaction: updatedTransaction, + breadcrumbs: updatedBreadcrumbs ?? event.breadcrumbs, + }; }, }); Sentry.setTag('branch', GIT_BRANCH); From a8c17b6807973a981d142366e24860abc6503179 Mon Sep 17 00:00:00 2001 From: Sam Keen Date: Thu, 11 May 2023 11:22:52 +0100 Subject: [PATCH 08/19] fix(governance): tranches data (#3708) --- .../src/lib/tranches/tranches-store.tsx | 19 ++++++++++++-- .../src/routes/redemption/tranche-item.tsx | 26 +++++++------------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/apps/governance/src/lib/tranches/tranches-store.tsx b/apps/governance/src/lib/tranches/tranches-store.tsx index 6b48ed913..6336e8719 100644 --- a/apps/governance/src/lib/tranches/tranches-store.tsx +++ b/apps/governance/src/lib/tranches/tranches-store.tsx @@ -50,7 +50,22 @@ export const useTranches = create()((set) => ({ ?.map((t) => { const tranche_progress = t.duration !== 0 ? (now - t.cliff_start) / t.duration : 0; - const lockedDecimal = tranche_progress < 0 ? 1 : 1 - tranche_progress; + let lockedDecimal; + if (t.duration !== 0) { + if (tranche_progress < 0) { + lockedDecimal = 1; + } else { + lockedDecimal = 1 - tranche_progress; + } + } else { + if (now < t.cliff_start) { + lockedDecimal = 1; + } else { + lockedDecimal = 0; + } + } + const clampedLockedDecimal = Math.max(0, Math.min(1, lockedDecimal)); + return { tranche_id: t.tranche_id, tranche_start: secondsToDate(t.cliff_start), @@ -60,7 +75,7 @@ export const useTranches = create()((set) => ({ toBigNum(t.current_balance, decimals) ), locked_amount: toBigNum(t.initial_balance, decimals).times( - lockedDecimal + clampedLockedDecimal ), users: t.users, }; diff --git a/apps/governance/src/routes/redemption/tranche-item.tsx b/apps/governance/src/routes/redemption/tranche-item.tsx index fd9056815..9b2677a7a 100644 --- a/apps/governance/src/routes/redemption/tranche-item.tsx +++ b/apps/governance/src/routes/redemption/tranche-item.tsx @@ -54,22 +54,16 @@ export const TrancheItem = ({ {formatNumber(total, 2)} - - - - - - - - - - - -
{t('Starts unlocking')} - {format(tranche.tranche_start, DATE_FORMAT_LONG)} -
{t('Fully unlocked')} - {format(tranche.tranche_end, DATE_FORMAT_LONG)} -
+
+
+ {t('Starts unlocking')}:{' '} + {format(tranche.tranche_start, DATE_FORMAT_LONG)} +
+
+ {t('Fully unlocked')}:{' '} + {format(tranche.tranche_end, DATE_FORMAT_LONG)} +
+
Date: Thu, 11 May 2023 12:58:12 +0200 Subject: [PATCH 09/19] feat(trading): hook up new EstimatePosition and EstimateFees api methods (#3634) --- .../trading-deal-ticket-order.cy.ts | 6 +- .../trading-deal-ticket-submit-account.cy.ts | 13 +- apps/trading-e2e/src/support/trading.ts | 14 +- libs/accounts/src/lib/use-account-balance.tsx | 6 +- .../src/lib/use-market-account-balance.tsx | 6 +- libs/cypress/mock.ts | 3 + libs/cypress/src/lib/mock-gql.ts | 7 +- libs/cypress/src/lib/mock-ws.ts | 8 +- .../src/components/deal-ticket-estimates.tsx | 132 -------- .../deal-ticket/deal-ticket-fee-details.tsx | 33 +- .../components/deal-ticket/deal-ticket.tsx | 92 +++++- libs/deal-ticket/src/components/index.ts | 1 - libs/deal-ticket/src/constants.ts | 4 + .../src/hooks/EstimateOrder.graphql | 9 +- .../src/hooks/__generated__/EstimateOrder.ts | 37 ++- .../src/hooks/estimate-order.mock.ts | 17 +- .../src/hooks/use-fee-deal-ticket-details.tsx | 288 +++++++++++------- .../src/hooks/use-initial-margin.ts | 74 ----- libs/environment/src/hooks/use-node-health.ts | 2 +- libs/network-info/src/network-info.tsx | 1 - libs/positions/src/index.ts | 1 - libs/positions/src/lib/Positions.graphql | 41 +++ .../src/lib/__generated__/Positions.ts | 80 ++++- .../src/lib/estimate-position.mock.ts | 40 +++ libs/positions/src/lib/margin-calculator.ts | 95 ------ .../src/lib/positions-data-providers.ts | 104 ------- .../block-statistics.mock.ts | 17 ++ .../protocol-statistics-proposals.mock.ts | 13 + .../use-next-protocol-upgrade-proposals.ts | 33 +- .../use-time-to-upgrade.ts | 15 +- libs/utils/src/lib/format/number.ts | 6 +- 31 files changed, 562 insertions(+), 636 deletions(-) delete mode 100644 libs/deal-ticket/src/components/deal-ticket-estimates.tsx delete mode 100644 libs/deal-ticket/src/hooks/use-initial-margin.ts create mode 100644 libs/positions/src/lib/estimate-position.mock.ts delete mode 100644 libs/positions/src/lib/margin-calculator.ts create mode 100644 libs/proposals/src/lib/protocol-upgrade-proposals/block-statistics.mock.ts create mode 100644 libs/proposals/src/lib/protocol-upgrade-proposals/protocol-statistics-proposals.mock.ts diff --git a/apps/trading-e2e/src/integration/trading-deal-ticket-order.cy.ts b/apps/trading-e2e/src/integration/trading-deal-ticket-order.cy.ts index 418d1c290..00d4f1c9d 100644 --- a/apps/trading-e2e/src/integration/trading-deal-ticket-order.cy.ts +++ b/apps/trading-e2e/src/integration/trading-deal-ticket-order.cy.ts @@ -16,6 +16,10 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => { cy.wait('@Markets'); }); + beforeEach(() => { + cy.mockTradingPage(); + }); + describe('limit order', () => { before(() => { cy.getByTestId(toggleLimit).click(); @@ -98,7 +102,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => { 'have.text', 'Total margin available' ); - cy.get('.text-neutral-500').should('have.text', '~100,000.01 tDAI'); + cy.get('.text-neutral-500').should('have.text', '100,000.01 tDAI'); }); }); }); diff --git a/apps/trading-e2e/src/integration/trading-deal-ticket-submit-account.cy.ts b/apps/trading-e2e/src/integration/trading-deal-ticket-submit-account.cy.ts index c964a485a..dd6c8f04e 100644 --- a/apps/trading-e2e/src/integration/trading-deal-ticket-submit-account.cy.ts +++ b/apps/trading-e2e/src/integration/trading-deal-ticket-submit-account.cy.ts @@ -1,10 +1,6 @@ import * as Schema from '@vegaprotocol/types'; import { aliasGQLQuery } from '@vegaprotocol/cypress'; -import { - accountsQuery, - amendGeneralAccountBalance, - estimateOrderQuery, -} from '@vegaprotocol/mock'; +import { accountsQuery, amendGeneralAccountBalance } from '@vegaprotocol/mock'; import type { OrderSubmission } from '@vegaprotocol/wallet'; import { createOrder } from '../support/create-order'; @@ -44,13 +40,10 @@ describe( cy.setVegaWallet(); cy.mockTradingPage(); const accounts = accountsQuery(); - amendGeneralAccountBalance(accounts, 'market-0', '100000000'); + amendGeneralAccountBalance(accounts, 'market-0', '1'); cy.mockGQL((req) => { aliasGQLQuery(req, 'Accounts', accounts); }); - cy.mockGQL((req) => { - aliasGQLQuery(req, 'EstimateOrder', estimateOrderQuery()); - }); cy.mockSubscription(); cy.visit('/#/markets/market-0'); cy.wait('@Markets'); @@ -66,7 +59,7 @@ describe( ); cy.getByTestId('dealticket-warning-margin').should( 'contain.text', - 'You may not have enough margin available to open this position. 2,354.72283 tDAI is currently required. You have only 1,000.01 tDAI available.' + 'You may not have enough margin available to open this position. 5.00 tDAI is currently required. You have only 0.01001 tDAI available.' ); cy.getByTestId('deal-ticket-deposit-dialog-button').click(); cy.getByTestId('dialog-content') diff --git a/apps/trading-e2e/src/support/trading.ts b/apps/trading-e2e/src/support/trading.ts index 17b9f35f0..d27952d71 100644 --- a/apps/trading-e2e/src/support/trading.ts +++ b/apps/trading-e2e/src/support/trading.ts @@ -10,7 +10,7 @@ import { chainIdQuery, chartQuery, depositsQuery, - estimateOrderQuery, + estimateFeesQuery, marginsQuery, marketCandlesQuery, marketDataQuery, @@ -22,11 +22,14 @@ import { networkParamsQuery, nodeGuardQuery, ordersQuery, + estimatePositionQuery, positionsQuery, proposalListQuery, statisticsQuery, tradesQuery, withdrawalsQuery, + protocolUpgradeProposalsQuery, + blockStatisticsQuery, } from '@vegaprotocol/mock'; import type { PartialDeep } from 'type-fest'; import type { MarketDataQuery, MarketsQuery } from '@vegaprotocol/market-list'; @@ -157,9 +160,16 @@ const mockTradingPage = ( aliasGQLQuery(req, 'Candles', candlesQuery()); aliasGQLQuery(req, 'Withdrawals', withdrawalsQuery()); aliasGQLQuery(req, 'NetworkParams', networkParamsQuery()); - aliasGQLQuery(req, 'EstimateOrder', estimateOrderQuery()); + aliasGQLQuery(req, 'EstimateFees', estimateFeesQuery()); + aliasGQLQuery(req, 'EstimatePosition', estimatePositionQuery()); aliasGQLQuery(req, 'ProposalsList', proposalListQuery()); aliasGQLQuery(req, 'Deposits', depositsQuery()); + aliasGQLQuery( + req, + 'ProtocolUpgradeProposals', + protocolUpgradeProposalsQuery() + ); + aliasGQLQuery(req, 'BlockStatistics', blockStatisticsQuery()); }; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace diff --git a/libs/accounts/src/lib/use-account-balance.tsx b/libs/accounts/src/lib/use-account-balance.tsx index 0807f8b39..2b50182bf 100644 --- a/libs/accounts/src/lib/use-account-balance.tsx +++ b/libs/accounts/src/lib/use-account-balance.tsx @@ -33,9 +33,9 @@ export const useAccountBalance = (assetId?: string) => { return useMemo( () => ({ - accountBalance, - accountDecimals, + accountBalance: pubKey ? accountBalance : '', + accountDecimals: pubKey ? accountDecimals : null, }), - [accountBalance, accountDecimals] + [accountBalance, accountDecimals, pubKey] ); }; diff --git a/libs/accounts/src/lib/use-market-account-balance.tsx b/libs/accounts/src/lib/use-market-account-balance.tsx index 1d6317da4..8491598a2 100644 --- a/libs/accounts/src/lib/use-market-account-balance.tsx +++ b/libs/accounts/src/lib/use-market-account-balance.tsx @@ -32,9 +32,9 @@ export const useMarketAccountBalance = (marketId: string) => { return useMemo( () => ({ - accountBalance, - accountDecimals, + accountBalance: pubKey ? accountBalance : '', + accountDecimals: pubKey ? accountDecimals : null, }), - [accountBalance, accountDecimals] + [accountBalance, accountDecimals, pubKey] ); }; diff --git a/libs/cypress/mock.ts b/libs/cypress/mock.ts index d2aff6cfc..8e28e912c 100644 --- a/libs/cypress/mock.ts +++ b/libs/cypress/mock.ts @@ -23,5 +23,8 @@ export * from '../orders/src/lib/components/order-data-provider/orders.mock'; export * from '../positions/src/lib/positions.mock'; export * from '../network-parameters/src/network-params.mock'; export * from '../wallet/src/connect-dialog/chain-id.mock'; +export * from '../positions/src/lib/estimate-position.mock'; export * from '../trades/src/lib/trades.mock'; export * from '../withdraws/src/lib/withdrawal.mock'; +export * from '../proposals/src/lib/protocol-upgrade-proposals/protocol-statistics-proposals.mock'; +export * from '../proposals/src/lib/protocol-upgrade-proposals/block-statistics.mock'; diff --git a/libs/cypress/src/lib/mock-gql.ts b/libs/cypress/src/lib/mock-gql.ts index 56c497533..1303ff282 100644 --- a/libs/cypress/src/lib/mock-gql.ts +++ b/libs/cypress/src/lib/mock-gql.ts @@ -17,7 +17,12 @@ const hasOperationName = ( operationName: string ) => { const { body } = req; - return 'operationName' in body && body.operationName === operationName; + return ( + typeof body === 'object' && + body !== null && + 'operationName' in body && + body.operationName === operationName + ); }; export function addMockGQLCommand() { diff --git a/libs/cypress/src/lib/mock-ws.ts b/libs/cypress/src/lib/mock-ws.ts index c651a4ea2..90124f4d5 100644 --- a/libs/cypress/src/lib/mock-ws.ts +++ b/libs/cypress/src/lib/mock-ws.ts @@ -20,8 +20,12 @@ const mockSocketServer = Cypress.env('VEGA_URL') : null; // DO NOT REMOVE: PASSTHROUGH for walletconnect -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const relayServer = new Server('wss://relay.walletconnect.com', { +new Server('wss://relay.walletconnect.com', { + mock: false, +}); + +// DO NOT REMOVE: PASSTHROUGH for hot module reload +new Server('ws://localhost:4200/_next/webpack-hmr', { mock: false, }); diff --git a/libs/deal-ticket/src/components/deal-ticket-estimates.tsx b/libs/deal-ticket/src/components/deal-ticket-estimates.tsx deleted file mode 100644 index 1df6b7834..000000000 --- a/libs/deal-ticket/src/components/deal-ticket-estimates.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import React from 'react'; -import type { ReactNode } from 'react'; -import { t } from '@vegaprotocol/i18n'; -import { Icon, Tooltip, TrafficLight } from '@vegaprotocol/ui-toolkit'; -import { IconNames } from '@blueprintjs/icons'; -import * as constants from '../constants'; - -interface DealTicketEstimatesProps { - quoteName?: string; - price?: string; - estCloseOut?: string; - estMargin?: string; - fees?: string; - notionalSize?: string; - size?: string; - slippage?: string; -} - -export const DealTicketEstimates = ({ - price, - quoteName, - estCloseOut, - estMargin, - fees, - notionalSize, - size, - slippage, -}: DealTicketEstimatesProps) => ( -
- {size && ( -
- {t('Contracts')} - -
- )} - {price && ( -
- {t('Est. Price')} -
{price}
-
- )} - {notionalSize && ( -
- {t('Est. Position Size')} - -
- )} - {fees && ( -
- {t('Est. Fees')} - -
- )} - {estMargin && ( -
- {t('Est. Margin')} - -
- )} - {estCloseOut && ( -
- {t('Est. Close out')} - -
- )} - {slippage && ( -
- {t('Est. Price Impact / Slippage')} - - - {slippage}% - - -
- )} -
-); - -interface DataTitleProps { - children: ReactNode; - quoteName?: string; -} - -export const DataTitle = ({ children, quoteName = '' }: DataTitleProps) => ( -
- {children} - {quoteName && ({quoteName})} -
-); - -interface ValueTooltipProps { - value?: string; - children?: ReactNode; - description: string; - id?: string; -} - -export const ValueTooltipRow = ({ - value, - children, - description, - id, -}: ValueTooltipProps) => ( -
- {value || children} - -
- -
-
-
-); diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-fee-details.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-fee-details.tsx index 16d2a877c..52969be14 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-fee-details.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-fee-details.tsx @@ -1,24 +1,8 @@ import { Tooltip } from '@vegaprotocol/ui-toolkit'; import classnames from 'classnames'; import type { ReactNode } from 'react'; -import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; -import type { Market, MarketData } from '@vegaprotocol/market-list'; -import { - getFeeDetailsValues, - useFeeDealTicketDetails, -} from '../../hooks/use-fee-deal-ticket-details'; - -interface DealTicketFeeDetailsProps { - order: OrderSubmissionBody['orderSubmission']; - market: Market; - marketData: MarketData; - currentInitialMargin?: string; - currentMaintenanceMargin?: string; - estimatedInitialMargin: string; - estimatedTotalInitialMargin: string; - marginAccountBalance: string; - generalAccountBalance: string; -} +import { getFeeDetailsValues } from '../../hooks/use-fee-deal-ticket-details'; +import type { FeeDetails } from '../../hooks/use-fee-deal-ticket-details'; export interface DealTicketFeeDetailProps { label: string; @@ -45,17 +29,8 @@ export const DealTicketFeeDetail = ({ ); -export const DealTicketFeeDetails = ({ - order, - market, - marketData, - ...args -}: DealTicketFeeDetailsProps) => { - const feeDetails = useFeeDealTicketDetails(order, market, marketData); - const details = getFeeDetailsValues({ - ...feeDetails, - ...args, - }); +export const DealTicketFeeDetails = (props: FeeDetails) => { + const details = getFeeDetailsValues(props); return (
{details.map(({ label, value, labelDescription, symbol, indent }) => ( diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx index 2cba96fd7..6eabd2f58 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx @@ -25,6 +25,16 @@ import { TinyScroll, } from '@vegaprotocol/ui-toolkit'; +import { + useEstimatePositionQuery, + useOpenVolume, +} from '@vegaprotocol/positions'; +import { toBigNum, removeDecimal } from '@vegaprotocol/utils'; +import { activeOrdersProvider } from '@vegaprotocol/orders'; +import { useEstimateFees } from '../../hooks/use-fee-deal-ticket-details'; +import { getDerivedPrice } from '../../utils/get-price'; +import type { OrderInfo } from '@vegaprotocol/types'; + import { validateExpiration, validateMarketState, @@ -34,7 +44,6 @@ import { } from '../../utils'; import { ZeroBalanceError } from '../deal-ticket-validation/zero-balance-error'; import { SummaryValidationType } from '../../constants'; -import { useInitialMargin } from '../../hooks/use-initial-margin'; import type { Market, MarketData } from '@vegaprotocol/market-list'; import { MarginWarning } from '../deal-ticket-validation/margin-warning'; import { @@ -104,7 +113,67 @@ export const DealTicket = ({ market.positionDecimalPlaces ); - const { margin, totalMargin } = useInitialMargin(market.id, normalizedOrder); + const price = useMemo(() => { + return normalizedOrder && getDerivedPrice(normalizedOrder, marketData); + }, [normalizedOrder, marketData]); + + const notionalSize = useMemo(() => { + if (price && normalizedOrder?.size) { + return removeDecimal( + toBigNum( + normalizedOrder.size, + market.positionDecimalPlaces + ).multipliedBy(toBigNum(price, market.decimalPlaces)), + asset.decimals + ); + } + return null; + }, [ + price, + normalizedOrder?.size, + market.decimalPlaces, + market.positionDecimalPlaces, + asset.decimals, + ]); + + const feeEstimate = useEstimateFees( + normalizedOrder && { ...normalizedOrder, price } + ); + const { data: activeOrders } = useDataProvider({ + dataProvider: activeOrdersProvider, + variables: { partyId: pubKey || '' }, + skip: !pubKey, + }); + const openVolume = useOpenVolume(pubKey, market.id) ?? '0'; + const orders = activeOrders + ? activeOrders.map(({ node: order }) => ({ + isMarketOrder: order.type === OrderType.TYPE_MARKET, + price: order.price, + remaining: order.remaining, + side: order.side, + })) + : []; + if (normalizedOrder) { + orders.push({ + isMarketOrder: normalizedOrder.type === OrderType.TYPE_MARKET, + price: normalizedOrder.price ?? '0', + remaining: normalizedOrder.size, + side: normalizedOrder.side, + }); + } + const { data: positionEstimate } = useEstimatePositionQuery({ + variables: { + marketId: market.id, + openVolume, + orders, + collateralAvailable: + marginAccountBalance || generalAccountBalance ? balance : undefined, + }, + skip: !normalizedOrder, + }); + + const assetSymbol = + market.tradableInstrument.instrument.product.settlementAsset.symbol; const { data: currentMargins } = useDataProvider({ dataProvider: marketMarginDataProvider, @@ -401,7 +470,10 @@ export const DealTicket = ({ asset={asset} marketTradingMode={marketData.marketTradingMode} balance={balance} - margin={totalMargin} + margin={ + positionEstimate?.estimatePosition?.margin.bestCase.initialLevel || + '0' + } isReadOnly={isReadOnly} pubKey={pubKey} onClickCollateral={onClickCollateral} @@ -413,15 +485,15 @@ export const DealTicket = ({ } /> diff --git a/libs/deal-ticket/src/components/index.ts b/libs/deal-ticket/src/components/index.ts index dbc74f55b..23656b03d 100644 --- a/libs/deal-ticket/src/components/index.ts +++ b/libs/deal-ticket/src/components/index.ts @@ -1,4 +1,3 @@ export * from './deal-ticket'; export * from './deal-ticket-validation'; export * from './trading-mode-tooltip'; -export * from './deal-ticket-estimates'; diff --git a/libs/deal-ticket/src/constants.ts b/libs/deal-ticket/src/constants.ts index a7802bcf8..1517df713 100644 --- a/libs/deal-ticket/src/constants.ts +++ b/libs/deal-ticket/src/constants.ts @@ -59,6 +59,10 @@ export const EST_FEES_TOOLTIP_TEXT = t( 'When you execute a new buy or sell order, you must pay a small amount of commission to the network for doing so. This fee is used to provide income to the node operates of the network and market makers who make prices on the futures market you are trading.' ); +export const LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT = t( + 'This is a approximation to the liquidation price for that particular contract position, assuming nothing else changes, which may affect your margin and collateral balances.' +); + export const EST_SLIPPAGE = t( 'When you execute a trade on Vega, the price obtained in the market may differ from the best available price displayed at the time of placing the trade. The estimated slippage shows the difference between the best available price and the estimated execution price, determined by market liquidity and your chosen order size.' ); diff --git a/libs/deal-ticket/src/hooks/EstimateOrder.graphql b/libs/deal-ticket/src/hooks/EstimateOrder.graphql index 88d3a6a4e..d7dcbe99f 100644 --- a/libs/deal-ticket/src/hooks/EstimateOrder.graphql +++ b/libs/deal-ticket/src/hooks/EstimateOrder.graphql @@ -1,4 +1,4 @@ -query EstimateOrder( +query EstimateFees( $marketId: ID! $partyId: ID! $price: String @@ -8,7 +8,7 @@ query EstimateOrder( $expiration: Timestamp $type: OrderType! ) { - estimateOrder( + estimateFees( marketId: $marketId partyId: $partyId price: $price @@ -18,14 +18,11 @@ query EstimateOrder( expiration: $expiration type: $type ) { - fee { + fees { makerFee infrastructureFee liquidityFee } - marginLevels { - initialLevel - } totalFeeAmount } } diff --git a/libs/deal-ticket/src/hooks/__generated__/EstimateOrder.ts b/libs/deal-ticket/src/hooks/__generated__/EstimateOrder.ts index abfddbe98..647e56be9 100644 --- a/libs/deal-ticket/src/hooks/__generated__/EstimateOrder.ts +++ b/libs/deal-ticket/src/hooks/__generated__/EstimateOrder.ts @@ -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 EstimateOrderQueryVariables = Types.Exact<{ +export type EstimateFeesQueryVariables = Types.Exact<{ marketId: Types.Scalars['ID']; partyId: Types.Scalars['ID']; price?: Types.InputMaybe; @@ -15,12 +15,12 @@ export type EstimateOrderQueryVariables = Types.Exact<{ }>; -export type EstimateOrderQuery = { __typename?: 'Query', estimateOrder: { __typename?: 'OrderEstimate', totalFeeAmount: string, fee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, marginLevels: { __typename?: 'MarginLevels', initialLevel: string } } }; +export type EstimateFeesQuery = { __typename?: 'Query', estimateFees: { __typename?: 'FeeEstimate', totalFeeAmount: string, fees: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string } } }; -export const EstimateOrderDocument = gql` - query EstimateOrder($marketId: ID!, $partyId: ID!, $price: String, $size: String!, $side: Side!, $timeInForce: OrderTimeInForce!, $expiration: Timestamp, $type: OrderType!) { - estimateOrder( +export const EstimateFeesDocument = gql` + query EstimateFees($marketId: ID!, $partyId: ID!, $price: String, $size: String!, $side: Side!, $timeInForce: OrderTimeInForce!, $expiration: Timestamp, $type: OrderType!) { + estimateFees( marketId: $marketId partyId: $partyId price: $price @@ -30,30 +30,27 @@ export const EstimateOrderDocument = gql` expiration: $expiration type: $type ) { - fee { + fees { makerFee infrastructureFee liquidityFee } - marginLevels { - initialLevel - } totalFeeAmount } } `; /** - * __useEstimateOrderQuery__ + * __useEstimateFeesQuery__ * - * To run a query within a React component, call `useEstimateOrderQuery` and pass it any options that fit your needs. - * When your component renders, `useEstimateOrderQuery` returns an object from Apollo Client that contains loading, error, and data properties + * To run a query within a React component, call `useEstimateFeesQuery` and pass it any options that fit your needs. + * When your component renders, `useEstimateFeesQuery` 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 } = useEstimateOrderQuery({ + * const { data, loading, error } = useEstimateFeesQuery({ * variables: { * marketId: // value for 'marketId' * partyId: // value for 'partyId' @@ -66,14 +63,14 @@ export const EstimateOrderDocument = gql` * }, * }); */ -export function useEstimateOrderQuery(baseOptions: Apollo.QueryHookOptions) { +export function useEstimateFeesQuery(baseOptions: Apollo.QueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(EstimateOrderDocument, options); + return Apollo.useQuery(EstimateFeesDocument, options); } -export function useEstimateOrderLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { +export function useEstimateFeesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(EstimateOrderDocument, options); + return Apollo.useLazyQuery(EstimateFeesDocument, options); } -export type EstimateOrderQueryHookResult = ReturnType; -export type EstimateOrderLazyQueryHookResult = ReturnType; -export type EstimateOrderQueryResult = Apollo.QueryResult; \ No newline at end of file +export type EstimateFeesQueryHookResult = ReturnType; +export type EstimateFeesLazyQueryHookResult = ReturnType; +export type EstimateFeesQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/libs/deal-ticket/src/hooks/estimate-order.mock.ts b/libs/deal-ticket/src/hooks/estimate-order.mock.ts index 3fbf7562b..b644f3bc1 100644 --- a/libs/deal-ticket/src/hooks/estimate-order.mock.ts +++ b/libs/deal-ticket/src/hooks/estimate-order.mock.ts @@ -1,21 +1,20 @@ import type { PartialDeep } from 'type-fest'; import merge from 'lodash/merge'; -import type { EstimateOrderQuery } from './__generated__/EstimateOrder'; +import type { EstimateFeesQuery } from './__generated__/EstimateOrder'; -export const estimateOrderQuery = ( - override?: PartialDeep -): EstimateOrderQuery => { - const defaultResult: EstimateOrderQuery = { - estimateOrder: { - __typename: 'OrderEstimate', +export const estimateFeesQuery = ( + override?: PartialDeep +): EstimateFeesQuery => { + const defaultResult: EstimateFeesQuery = { + estimateFees: { + __typename: 'FeeEstimate', totalFeeAmount: '0.0006', - fee: { + fees: { __typename: 'TradeFee', makerFee: '100000', infrastructureFee: '100000', liquidityFee: '100000', }, - marginLevels: { __typename: 'MarginLevels', initialLevel: '1' }, }, }; return merge(defaultResult, override); diff --git a/libs/deal-ticket/src/hooks/use-fee-deal-ticket-details.tsx b/libs/deal-ticket/src/hooks/use-fee-deal-ticket-details.tsx index 726930c3d..703735cec 100644 --- a/libs/deal-ticket/src/hooks/use-fee-deal-ticket-details.tsx +++ b/libs/deal-ticket/src/hooks/use-fee-deal-ticket-details.tsx @@ -1,14 +1,9 @@ import { FeesBreakdown } from '@vegaprotocol/market-info'; -import { - addDecimal, - addDecimalsFormatNumber, - formatNumber, - toBigNum, -} from '@vegaprotocol/utils'; +import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils'; import { t } from '@vegaprotocol/i18n'; import { useVegaWallet } from '@vegaprotocol/wallet'; -import { useMemo } from 'react'; -import type { Market, MarketData } from '@vegaprotocol/market-list'; +import type { Market } from '@vegaprotocol/market-list'; +import type { EstimatePositionQuery } from '@vegaprotocol/positions'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import { EST_TOTAL_MARGIN_TOOLTIP_TEXT, @@ -17,58 +12,30 @@ import { MARGIN_DIFF_TOOLTIP_TEXT, DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT, TOTAL_MARGIN_AVAILABLE, + LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT, } from '../constants'; -import { useMarketAccountBalance } from '@vegaprotocol/accounts'; -import { getDerivedPrice } from '../utils/get-price'; -import { useEstimateOrderQuery } from './__generated__/EstimateOrder'; -import type { EstimateOrderQuery } from './__generated__/EstimateOrder'; -export const useFeeDealTicketDetails = ( - order: OrderSubmissionBody['orderSubmission'], - market: Market, - marketData: MarketData +import { useEstimateFeesQuery } from './__generated__/EstimateOrder'; +import type { EstimateFeesQuery } from './__generated__/EstimateOrder'; + +export const useEstimateFees = ( + order?: OrderSubmissionBody['orderSubmission'] ) => { const { pubKey } = useVegaWallet(); - const { accountBalance } = useMarketAccountBalance(market.id); - const price = useMemo(() => { - return getDerivedPrice(order, marketData); - }, [order, marketData]); - - const { data: estMargin } = useEstimateOrderQuery({ - variables: { - marketId: market.id, + const { data } = useEstimateFeesQuery({ + variables: order && { + marketId: order.marketId, partyId: pubKey || '', - price, + price: order.price, size: order.size, side: order.side, timeInForce: order.timeInForce, type: order.type, }, - skip: !pubKey || !market || !order.size || !price, + skip: !pubKey || !order?.size || !order?.price, }); - - const notionalSize = useMemo(() => { - if (price && order.size) { - return toBigNum(order.size, market.positionDecimalPlaces) - .multipliedBy(addDecimal(price, market.decimalPlaces)) - .toString(); - } - return null; - }, [price, order.size, market.decimalPlaces, market.positionDecimalPlaces]); - - const assetSymbol = - market.tradableInstrument.instrument.product.settlementAsset.symbol; - - return useMemo(() => { - return { - market, - assetSymbol, - notionalSize, - accountBalance, - estimateOrder: estMargin?.estimateOrder, - }; - }, [market, assetSymbol, notionalSize, accountBalance, estMargin]); + return data?.estimateFees; }; export interface FeeDetails { @@ -77,42 +44,54 @@ export interface FeeDetails { market: Market; assetSymbol: string; notionalSize: string | null; - estimateOrder: EstimateOrderQuery['estimateOrder'] | undefined; - estimatedInitialMargin: string; - estimatedTotalInitialMargin: string; + feeEstimate: EstimateFeesQuery['estimateFees'] | undefined; currentInitialMargin?: string; currentMaintenanceMargin?: string; + positionEstimate: EstimatePositionQuery['estimatePosition']; } +const emptyValue = '-'; +const formatValue = ( + value: string | number | null | undefined, + formatDecimals: number +): string => { + return isNumeric(value) + ? addDecimalsFormatNumber(value, formatDecimals) + : emptyValue; +}; +const formatRange = ( + min: string | number | null | undefined, + max: string | number | null | undefined, + formatDecimals: number +) => { + const minFormatted = formatValue(min, formatDecimals); + const maxFormatted = formatValue(max, formatDecimals); + if (minFormatted !== maxFormatted) { + return `${minFormatted} - ${maxFormatted}`; + } + if (minFormatted !== emptyValue) { + return minFormatted; + } + return maxFormatted; +}; + export const getFeeDetailsValues = ({ marginAccountBalance, generalAccountBalance, assetSymbol, - estimateOrder, + feeEstimate, market, notionalSize, - estimatedTotalInitialMargin, currentInitialMargin, currentMaintenanceMargin, + positionEstimate, }: FeeDetails) => { + const liquidationEstimate = positionEstimate?.liquidation; + const marginEstimate = positionEstimate?.margin; const totalBalance = BigInt(generalAccountBalance || '0') + BigInt(marginAccountBalance || '0'); const assetDecimals = market.tradableInstrument.instrument.product.settlementAsset.decimals; - const formatValueWithMarketDp = ( - value: string | number | null | undefined - ): string => { - return value && !isNaN(Number(value)) - ? formatNumber(value, market.decimalPlaces) - : '-'; - }; - const formatValueWithAssetDp = ( - value: string | number | null | undefined - ): string => { - return value && !isNaN(Number(value)) - ? addDecimalsFormatNumber(value, assetDecimals) - : '-'; - }; const details: { label: string; value?: string | null; @@ -122,15 +101,15 @@ export const getFeeDetailsValues = ({ }[] = [ { label: t('Notional'), - value: formatValueWithMarketDp(notionalSize), + value: formatValue(notionalSize, assetDecimals), symbol: assetSymbol, labelDescription: NOTIONAL_SIZE_TOOLTIP_TEXT(assetSymbol), }, { label: t('Fees'), value: - estimateOrder?.totalFeeAmount && - `~${formatValueWithAssetDp(estimateOrder?.totalFeeAmount)}`, + feeEstimate?.totalFeeAmount && + `~${formatValue(feeEstimate?.totalFeeAmount, assetDecimals)}`, labelDescription: ( <> @@ -139,7 +118,7 @@ export const getFeeDetailsValues = ({ )} 0 + ? deductionFromCollateralBestCase.toString() + : '0', + deductionFromCollateralWorstCase > 0 + ? deductionFromCollateralWorstCase.toString() + : '0', + assetDecimals ), + symbol: assetSymbol, + labelDescription: DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT(assetSymbol), }); - if (marginAccountBalance) { - const deductionFromCollateral = - BigInt(estimatedTotalInitialMargin) - BigInt(marginAccountBalance); - - details.push({ - indent: true, - label: t('Deduction from collateral'), - value: `~${formatValueWithAssetDp( - deductionFromCollateral > 0 ? deductionFromCollateral.toString() : '0' - )}`, - symbol: assetSymbol, - labelDescription: DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT(assetSymbol), - }); - } - details.push({ label: t('Projected margin'), - value: `~${formatValueWithAssetDp(estimatedTotalInitialMargin)}`, + value: formatRange( + marginEstimate?.bestCase.initialLevel, + marginEstimate?.worstCase.initialLevel, + assetDecimals + ), symbol: assetSymbol, labelDescription: EST_TOTAL_MARGIN_TOOLTIP_TEXT, }); } details.push({ label: t('Current margin allocation'), - value: `${formatValueWithAssetDp(marginAccountBalance)}`, + value: formatValue(marginAccountBalance, assetDecimals), symbol: assetSymbol, labelDescription: MARGIN_ACCOUNT_TOOLTIP_TEXT, }); + + let liquidationPriceEstimate = emptyValue; + + if (liquidationEstimate) { + const liquidationEstimateBestCaseIncludingBuyOrders = BigInt( + liquidationEstimate.bestCase.including_buy_orders.replace(/\..*/, '') + ); + const liquidationEstimateBestCaseIncludingSellOrders = BigInt( + liquidationEstimate.bestCase.including_sell_orders.replace(/\..*/, '') + ); + const liquidationEstimateBestCase = + liquidationEstimateBestCaseIncludingBuyOrders > + liquidationEstimateBestCaseIncludingSellOrders + ? liquidationEstimateBestCaseIncludingBuyOrders + : liquidationEstimateBestCaseIncludingSellOrders; + + const liquidationEstimateWorstCaseIncludingBuyOrders = BigInt( + liquidationEstimate.worstCase.including_buy_orders.replace(/\..*/, '') + ); + const liquidationEstimateWorstCaseIncludingSellOrders = BigInt( + liquidationEstimate.worstCase.including_sell_orders.replace(/\..*/, '') + ); + const liquidationEstimateWorstCase = + liquidationEstimateWorstCaseIncludingBuyOrders > + liquidationEstimateWorstCaseIncludingSellOrders + ? liquidationEstimateWorstCaseIncludingBuyOrders + : liquidationEstimateWorstCaseIncludingSellOrders; + liquidationPriceEstimate = formatRange( + (liquidationEstimateBestCase < liquidationEstimateWorstCase + ? liquidationEstimateBestCase + : liquidationEstimateWorstCase + ).toString(), + (liquidationEstimateBestCase > liquidationEstimateWorstCase + ? liquidationEstimateBestCase + : liquidationEstimateWorstCase + ).toString(), + assetDecimals + ); + } + + details.push({ + label: t('Liquidation price estimate'), + value: liquidationPriceEstimate, + symbol: assetSymbol, + labelDescription: LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT, + }); return details; }; diff --git a/libs/deal-ticket/src/hooks/use-initial-margin.ts b/libs/deal-ticket/src/hooks/use-initial-margin.ts deleted file mode 100644 index 3b0806332..000000000 --- a/libs/deal-ticket/src/hooks/use-initial-margin.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { useMemo } from 'react'; -import { useDataProvider } from '@vegaprotocol/data-provider'; -import { useVegaWallet } from '@vegaprotocol/wallet'; -import { marketDataProvider } from '@vegaprotocol/market-list'; -import { - calculateMargins, - // getDerivedPrice, - volumeAndMarginProvider, -} from '@vegaprotocol/positions'; -import { Side } from '@vegaprotocol/types'; -import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; -import { marketInfoProvider } from '@vegaprotocol/market-info'; - -export const useInitialMargin = ( - marketId: OrderSubmissionBody['orderSubmission']['marketId'], - order?: OrderSubmissionBody['orderSubmission'] -) => { - const { pubKey } = useVegaWallet(); - const { data: marketData } = useDataProvider({ - dataProvider: marketDataProvider, - variables: { marketId }, - }); - const { data: activeVolumeAndMargin } = useDataProvider({ - dataProvider: volumeAndMarginProvider, - variables: { marketId, partyId: pubKey || '' }, - skip: !pubKey, - }); - const { data: marketInfo } = useDataProvider({ - dataProvider: marketInfoProvider, - variables: { marketId }, - }); - let totalMargin = '0'; - let margin = '0'; - if (marketInfo?.riskFactors && marketData && order) { - const { - positionDecimalPlaces, - decimalPlaces, - tradableInstrument, - riskFactors, - } = marketInfo; - const { marginCalculator, instrument } = tradableInstrument; - const { decimals } = instrument.product.settlementAsset; - margin = totalMargin = calculateMargins({ - side: order.side, - size: order.size, - price: marketData.markPrice, // getDerivedPrice(order, marketData), same in positions-data-providers - positionDecimalPlaces, - decimalPlaces, - decimals, - scalingFactors: marginCalculator?.scalingFactors, - riskFactors, - }).initialMargin; - } - - if (activeVolumeAndMargin) { - let sellMargin = BigInt(activeVolumeAndMargin.sellInitialMargin); - let buyMargin = BigInt(activeVolumeAndMargin.buyInitialMargin); - if (order?.side === Side.SIDE_SELL) { - sellMargin += BigInt(totalMargin); - } else { - buyMargin += BigInt(totalMargin); - } - totalMargin = - sellMargin > buyMargin ? sellMargin.toString() : buyMargin.toString(); - } - - return useMemo( - () => ({ - totalMargin, - margin, - }), - [totalMargin, margin] - ); -}; diff --git a/libs/environment/src/hooks/use-node-health.ts b/libs/environment/src/hooks/use-node-health.ts index 1cffd7e6f..b10360943 100644 --- a/libs/environment/src/hooks/use-node-health.ts +++ b/libs/environment/src/hooks/use-node-health.ts @@ -38,7 +38,7 @@ export const useNodeHealth = () => { return; } - if (!('Cypress' in window)) { + if (!('Cypress' in window) && window.location.hostname !== 'localhost') { startPolling(POLL_INTERVAL); } }, [error, startPolling, stopPolling]); diff --git a/libs/network-info/src/network-info.tsx b/libs/network-info/src/network-info.tsx index 63d6c014c..02c84de6f 100644 --- a/libs/network-info/src/network-info.tsx +++ b/libs/network-info/src/network-info.tsx @@ -2,7 +2,6 @@ import { Fragment } from 'react'; import { t } from '@vegaprotocol/i18n'; import { Link, Lozenge } from '@vegaprotocol/ui-toolkit'; import { - NodeSwitcherDialog, useEnvironment, useNodeSwitcherStore, } from '@vegaprotocol/environment'; diff --git a/libs/positions/src/index.ts b/libs/positions/src/index.ts index 99f406606..e6b3b3a92 100644 --- a/libs/positions/src/index.ts +++ b/libs/positions/src/index.ts @@ -2,7 +2,6 @@ export * from './lib/__generated__/Positions'; export * from './lib/positions-container'; export * from './lib/positions-data-providers'; export * from './lib/margin-data-provider'; -export * from './lib/margin-calculator'; export * from './lib/positions-table'; export * from './lib/use-market-margin'; export * from './lib/use-open-volume'; diff --git a/libs/positions/src/lib/Positions.graphql b/libs/positions/src/lib/Positions.graphql index cc80a0aea..425c053f7 100644 --- a/libs/positions/src/lib/Positions.graphql +++ b/libs/positions/src/lib/Positions.graphql @@ -75,3 +75,44 @@ subscription MarginsSubscription($partyId: ID!) { timestamp } } + +query EstimatePosition( + $marketId: ID! + $openVolume: String! + $orders: [OrderInfo!] + $collateralAvailable: String +) { + estimatePosition( + marketId: $marketId + openVolume: $openVolume + orders: $orders + collateralAvailable: $collateralAvailable + ) { + margin { + worstCase { + maintenanceLevel + searchLevel + initialLevel + collateralReleaseLevel + } + bestCase { + maintenanceLevel + searchLevel + initialLevel + collateralReleaseLevel + } + } + liquidation { + worstCase { + open_volume_only + including_buy_orders + including_sell_orders + } + bestCase { + open_volume_only + including_buy_orders + including_sell_orders + } + } + } +} diff --git a/libs/positions/src/lib/__generated__/Positions.ts b/libs/positions/src/lib/__generated__/Positions.ts index 96a130c3a..856053d6b 100644 --- a/libs/positions/src/lib/__generated__/Positions.ts +++ b/libs/positions/src/lib/__generated__/Positions.ts @@ -35,6 +35,16 @@ export type MarginsSubscriptionSubscriptionVariables = Types.Exact<{ export type MarginsSubscriptionSubscription = { __typename?: 'Subscription', margins: { __typename?: 'MarginLevelsUpdate', marketId: string, asset: string, partyId: string, maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, timestamp: any } }; +export type EstimatePositionQueryVariables = Types.Exact<{ + marketId: Types.Scalars['ID']; + openVolume: Types.Scalars['String']; + orders?: Types.InputMaybe | Types.OrderInfo>; + collateralAvailable?: Types.InputMaybe; +}>; + + +export type EstimatePositionQuery = { __typename?: 'Query', estimatePosition?: { __typename?: 'PositionEstimate', margin: { __typename?: 'MarginEstimate', worstCase: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string }, bestCase: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string } }, liquidation?: { __typename?: 'LiquidationEstimate', worstCase: { __typename?: 'LiquidationPrice', open_volume_only: string, including_buy_orders: string, including_sell_orders: string }, bestCase: { __typename?: 'LiquidationPrice', open_volume_only: string, including_buy_orders: string, including_sell_orders: string } } | null } | null }; + export const PositionFieldsFragmentDoc = gql` fragment PositionFields on Position { realisedPNL @@ -220,4 +230,72 @@ export function useMarginsSubscriptionSubscription(baseOptions: Apollo.Subscript return Apollo.useSubscription(MarginsSubscriptionDocument, options); } export type MarginsSubscriptionSubscriptionHookResult = ReturnType; -export type MarginsSubscriptionSubscriptionResult = Apollo.SubscriptionResult; \ No newline at end of file +export type MarginsSubscriptionSubscriptionResult = Apollo.SubscriptionResult; +export const EstimatePositionDocument = gql` + query EstimatePosition($marketId: ID!, $openVolume: String!, $orders: [OrderInfo!], $collateralAvailable: String) { + estimatePosition( + marketId: $marketId + openVolume: $openVolume + orders: $orders + collateralAvailable: $collateralAvailable + ) { + margin { + worstCase { + maintenanceLevel + searchLevel + initialLevel + collateralReleaseLevel + } + bestCase { + maintenanceLevel + searchLevel + initialLevel + collateralReleaseLevel + } + } + liquidation { + worstCase { + open_volume_only + including_buy_orders + including_sell_orders + } + bestCase { + open_volume_only + including_buy_orders + including_sell_orders + } + } + } +} + `; + +/** + * __useEstimatePositionQuery__ + * + * To run a query within a React component, call `useEstimatePositionQuery` and pass it any options that fit your needs. + * When your component renders, `useEstimatePositionQuery` 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 } = useEstimatePositionQuery({ + * variables: { + * marketId: // value for 'marketId' + * openVolume: // value for 'openVolume' + * orders: // value for 'orders' + * collateralAvailable: // value for 'collateralAvailable' + * }, + * }); + */ +export function useEstimatePositionQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(EstimatePositionDocument, options); + } +export function useEstimatePositionLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(EstimatePositionDocument, options); + } +export type EstimatePositionQueryHookResult = ReturnType; +export type EstimatePositionLazyQueryHookResult = ReturnType; +export type EstimatePositionQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/libs/positions/src/lib/estimate-position.mock.ts b/libs/positions/src/lib/estimate-position.mock.ts new file mode 100644 index 000000000..d5536737b --- /dev/null +++ b/libs/positions/src/lib/estimate-position.mock.ts @@ -0,0 +1,40 @@ +import type { PartialDeep } from 'type-fest'; +import merge from 'lodash/merge'; +import type { EstimatePositionQuery } from './__generated__/Positions'; + +export const estimatePositionQuery = ( + override?: PartialDeep +): EstimatePositionQuery => { + const defaultResult: EstimatePositionQuery = { + estimatePosition: { + __typename: 'PositionEstimate', + margin: { + bestCase: { + collateralReleaseLevel: '1000000', + initialLevel: '500000', + maintenanceLevel: '200000', + searchLevel: '300000', + }, + worstCase: { + collateralReleaseLevel: '1100000', + initialLevel: '600000', + maintenanceLevel: '300000', + searchLevel: '400000', + }, + }, + liquidation: { + bestCase: { + including_buy_orders: '1', + including_sell_orders: '1', + open_volume_only: '1', + }, + worstCase: { + including_buy_orders: '1', + including_sell_orders: '1', + open_volume_only: '1', + }, + }, + }, + }; + return merge(defaultResult, override); +}; diff --git a/libs/positions/src/lib/margin-calculator.ts b/libs/positions/src/lib/margin-calculator.ts deleted file mode 100644 index 522d60e73..000000000 --- a/libs/positions/src/lib/margin-calculator.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { toBigNum } from '@vegaprotocol/utils'; -import { Side, MarketTradingMode, OrderType } from '@vegaprotocol/types'; -import type { ScalingFactors, RiskFactor } from '@vegaprotocol/types'; -import type { MarketData } from '@vegaprotocol/market-list'; - -export const isMarketInAuction = (marketTradingMode: MarketTradingMode) => { - return [ - MarketTradingMode.TRADING_MODE_BATCH_AUCTION, - MarketTradingMode.TRADING_MODE_MONITORING_AUCTION, - MarketTradingMode.TRADING_MODE_OPENING_AUCTION, - ].includes(marketTradingMode); -}; - -/** - * Get the market price based on market mode (auction or not auction) - */ -export const getMarketPrice = ({ - marketTradingMode, - indicativePrice, - markPrice, -}: Pick) => { - if (isMarketInAuction(marketTradingMode)) { - // 0 can never be a valid uncrossing price - // as it would require there being orders on the book at that price. - if ( - indicativePrice && - indicativePrice !== '0' && - BigInt(indicativePrice) !== BigInt(0) - ) { - return indicativePrice; - } - } - return markPrice; -}; - -/** - * Gets the price for an order, order limit this is the user - * entered value, for market this will be the mark price or - * if in auction the indicative uncrossing price - */ -export const getDerivedPrice = ( - order: { - type?: OrderType | null; - price?: string; - }, - marketData: Pick< - MarketData, - 'marketTradingMode' | 'indicativePrice' | 'markPrice' - > -) => { - // If order type is market we should use either the mark price - // or the uncrossing price. If order type is limit use the price - // the user has input - - // Use the market price if order is a market order - if (order.type === OrderType.TYPE_LIMIT && order.price) { - return order.price; - } - return getMarketPrice(marketData); -}; - -export const calculateMargins = ({ - size, - side, - price, - decimals, - positionDecimalPlaces, - decimalPlaces, - scalingFactors, - riskFactors, -}: { - size: string; - side: Side; - positionDecimalPlaces: number; - decimalPlaces: number; - decimals: number; - price: string; - scalingFactors?: ScalingFactors; - riskFactors: RiskFactor; -}) => { - const maintenanceMargin = toBigNum(size, positionDecimalPlaces) - .multipliedBy( - side === Side.SIDE_SELL ? riskFactors.short : riskFactors.long - ) - .multipliedBy(toBigNum(price, decimalPlaces)); - return { - maintenanceMargin: maintenanceMargin - .multipliedBy(Math.pow(10, decimals)) - .toFixed(0), - initialMargin: maintenanceMargin - .multipliedBy(scalingFactors?.initialMargin ?? 1) - .multipliedBy(Math.pow(10, decimals)) - .toFixed(0), - }; -}; diff --git a/libs/positions/src/lib/positions-data-providers.ts b/libs/positions/src/lib/positions-data-providers.ts index c01976a49..b29ef4f64 100644 --- a/libs/positions/src/lib/positions-data-providers.ts +++ b/libs/positions/src/lib/positions-data-providers.ts @@ -5,7 +5,6 @@ import sortBy from 'lodash/sortBy'; import type { Account } from '@vegaprotocol/accounts'; import { accountsDataProvider } from '@vegaprotocol/accounts'; import { toBigNum, removePaginationWrapper } from '@vegaprotocol/utils'; -import type { Edge } from '@vegaprotocol/data-provider'; import { makeDataProvider, makeDerivedDataProvider, @@ -28,14 +27,6 @@ import { PositionsSubscriptionDocument, } from './__generated__/Positions'; import { marginsDataProvider } from './margin-data-provider'; -import { calculateMargins } from './margin-calculator'; -import { Side } from '@vegaprotocol/types'; -import { marketInfoProvider } from '@vegaprotocol/market-info'; -import type { MarketInfoQuery } from '@vegaprotocol/market-info'; -import { marketDataProvider } from '@vegaprotocol/market-list'; -import type { MarketData } from '@vegaprotocol/market-list'; -import { activeOrdersProvider } from '@vegaprotocol/orders'; -import type { OrderFieldsFragment } from '@vegaprotocol/orders'; import type { PositionStatus } from '@vegaprotocol/types'; type PositionMarginLevel = Pick< @@ -336,98 +327,3 @@ export const positionsMetricsProvider = makeDerivedDataProvider< return !(previousRow && isEqual(previousRow, row)); }) ); - -export const volumeAndMarginProvider = makeDerivedDataProvider< - { - buyVolume: string; - sellVolume: string; - buyInitialMargin: string; - sellInitialMargin: string; - }, - never, - PositionsQueryVariables & MarketDataQueryVariables ->( - [ - (callback, client, { partyId, marketId }) => - activeOrdersProvider(callback, client, { - partyId, - marketId, - }), - (callback, client, { marketId }) => - marketDataProvider(callback, client, { marketId }), - (callback, client, { marketId }) => - marketInfoProvider(callback, client, { marketId }), - openVolumeDataProvider, - ], - (data) => { - const orders = data[0] as (Edge | null)[] | null; - const marketData = data[1] as MarketData | null; - const marketInfo = data[2] as MarketInfoQuery['market']; - let openVolume = (data[3] as string | null) || '0'; - const shortPosition = openVolume?.startsWith('-'); - if (shortPosition) { - openVolume = openVolume.substring(1); - } - let buyVolume = BigInt(shortPosition ? 0 : openVolume); - let sellVolume = BigInt(shortPosition ? openVolume : 0); - let buyInitialMargin = BigInt(0); - let sellInitialMargin = BigInt(0); - if (marketInfo?.riskFactors && marketData) { - const { - positionDecimalPlaces, - decimalPlaces, - tradableInstrument, - riskFactors, - } = marketInfo; - const { marginCalculator, instrument } = tradableInstrument; - const { decimals } = instrument.product.settlementAsset; - const calculatorParams = { - positionDecimalPlaces, - decimalPlaces, - decimals, - scalingFactors: marginCalculator?.scalingFactors, - riskFactors, - }; - if (openVolume !== '0') { - const { initialMargin } = calculateMargins({ - side: shortPosition ? Side.SIDE_SELL : Side.SIDE_BUY, - size: openVolume, - price: marketData.markPrice, - ...calculatorParams, - }); - if (shortPosition) { - sellInitialMargin += BigInt(initialMargin); - } else { - buyInitialMargin += BigInt(initialMargin); - } - } - orders?.forEach((order) => { - if (!order) { - return; - } - const { side, remaining: size } = order.node; - const initialMargin = BigInt( - calculateMargins({ - side, - size, - price: marketData.markPrice, //getDerivedPrice(order.node, marketData), same use-initial-margin - ...calculatorParams, - }).initialMargin - ); - if (order.node.side === Side.SIDE_BUY) { - buyVolume += BigInt(size); - buyInitialMargin += initialMargin; - } else { - sellVolume += BigInt(size); - sellInitialMargin += initialMargin; - } - }); - } - return { - buyVolume: buyVolume.toString(), - sellVolume: sellVolume.toString(), - buyInitialMargin: buyInitialMargin.toString(), - sellInitialMargin: sellInitialMargin.toString(), - }; - } -); diff --git a/libs/proposals/src/lib/protocol-upgrade-proposals/block-statistics.mock.ts b/libs/proposals/src/lib/protocol-upgrade-proposals/block-statistics.mock.ts new file mode 100644 index 000000000..f49af820e --- /dev/null +++ b/libs/proposals/src/lib/protocol-upgrade-proposals/block-statistics.mock.ts @@ -0,0 +1,17 @@ +import type { BlockStatisticsQuery } from './__generated__/BlockStatistics'; +import merge from 'lodash/merge'; +import type { PartialDeep } from 'type-fest'; + +export const blockStatisticsQuery = ( + override?: PartialDeep +): BlockStatisticsQuery => { + const defaultResult = { + statistics: { + __typename: 'Statistics', + blockHeight: '100', + blockDuration: '100', + }, + }; + + return merge(defaultResult, override); +}; diff --git a/libs/proposals/src/lib/protocol-upgrade-proposals/protocol-statistics-proposals.mock.ts b/libs/proposals/src/lib/protocol-upgrade-proposals/protocol-statistics-proposals.mock.ts new file mode 100644 index 000000000..a11b10106 --- /dev/null +++ b/libs/proposals/src/lib/protocol-upgrade-proposals/protocol-statistics-proposals.mock.ts @@ -0,0 +1,13 @@ +import type { ProtocolUpgradeProposalsQuery } from './__generated__/ProtocolUpgradeProposals'; +import merge from 'lodash/merge'; +import type { PartialDeep } from 'type-fest'; + +export const protocolUpgradeProposalsQuery = ( + override?: PartialDeep +): ProtocolUpgradeProposalsQuery => { + const defaultResult: ProtocolUpgradeProposalsQuery = { + lastBlockHeight: '100', + }; + + return merge(defaultResult, override); +}; diff --git a/libs/proposals/src/lib/protocol-upgrade-proposals/use-next-protocol-upgrade-proposals.ts b/libs/proposals/src/lib/protocol-upgrade-proposals/use-next-protocol-upgrade-proposals.ts index 70bc3bff7..415d648fd 100644 --- a/libs/proposals/src/lib/protocol-upgrade-proposals/use-next-protocol-upgrade-proposals.ts +++ b/libs/proposals/src/lib/protocol-upgrade-proposals/use-next-protocol-upgrade-proposals.ts @@ -1,19 +1,30 @@ -import { useMemo } from 'react'; +import { useMemo, useEffect } from 'react'; import * as Schema from '@vegaprotocol/types'; import { removePaginationWrapper } from '@vegaprotocol/utils'; import { useProtocolUpgradeProposalsQuery } from './__generated__/ProtocolUpgradeProposals'; export const useNextProtocolUpgradeProposals = (since?: number) => { - const { data, loading, error } = useProtocolUpgradeProposalsQuery({ - pollInterval: 5000, - fetchPolicy: 'network-only', - errorPolicy: 'ignore', - variables: { - inState: - Schema.ProtocolUpgradeProposalStatus - .PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED, - }, - }); + const { data, loading, error, startPolling, stopPolling } = + useProtocolUpgradeProposalsQuery({ + fetchPolicy: 'network-only', + errorPolicy: 'ignore', + variables: { + inState: + Schema.ProtocolUpgradeProposalStatus + .PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED, + }, + }); + + useEffect(() => { + if (error) { + stopPolling(); + return; + } + + if (!('Cypress' in window) && window.location.hostname !== 'localhost') { + startPolling(5000); + } + }, [error, startPolling, stopPolling]); const nextUpgrades = useMemo(() => { if (!data) return []; diff --git a/libs/proposals/src/lib/protocol-upgrade-proposals/use-time-to-upgrade.ts b/libs/proposals/src/lib/protocol-upgrade-proposals/use-time-to-upgrade.ts index 10b5a22f5..9a61b99a0 100644 --- a/libs/proposals/src/lib/protocol-upgrade-proposals/use-time-to-upgrade.ts +++ b/libs/proposals/src/lib/protocol-upgrade-proposals/use-time-to-upgrade.ts @@ -8,20 +8,29 @@ const durations = [] as number[]; const useAverageBlockDuration = (polls = DEFAULT_POLLS) => { const [avg, setAvg] = useState(undefined); - const { data } = useBlockStatisticsQuery({ - pollInterval: INTERVAL, + const { data, startPolling, stopPolling, error } = useBlockStatisticsQuery({ fetchPolicy: 'network-only', errorPolicy: 'ignore', skip: durations.length === polls, }); + useEffect(() => { + if (error) { + stopPolling(); + return; + } + + if (!('Cypress' in window) && window.location.hostname !== 'localhost') { + startPolling(INTERVAL); + } + }, [error, startPolling, stopPolling]); + useEffect(() => { if (durations.length < polls && data) { durations.push(parseFloat(data.statistics.blockDuration)); } if (durations.length === polls) { const averageBlockDuration = sum(durations) / durations.length; // ms - console.log('setting avg', averageBlockDuration); setAvg(averageBlockDuration); } }, [data, polls]); diff --git a/libs/utils/src/lib/format/number.ts b/libs/utils/src/lib/format/number.ts index 06b920e84..3cbf5a402 100644 --- a/libs/utils/src/lib/format/number.ts +++ b/libs/utils/src/lib/format/number.ts @@ -32,8 +32,10 @@ export function addDecimal( return toBigNum(value, decimals).toFixed(decimalPrecision); } -export function removeDecimal(value: string, decimals: number): string { - if (!decimals) return value; +export function removeDecimal( + value: string | BigNumber, + decimals: number +): string { return new BigNumber(value || 0).times(Math.pow(10, decimals)).toFixed(0); } From 579c884a5aeeb02c59d6e2f63984918eafd3370e Mon Sep 17 00:00:00 2001 From: "m.ray" <16125548+MadalinaRaicu@users.noreply.github.com> Date: Thu, 11 May 2023 14:43:20 +0300 Subject: [PATCH 10/19] feat(trading): show pegged order offset and reference in the order table (#3675) --- libs/datagrid/src/lib/cells/order-type-cell.tsx | 11 ++++++++++- .../components/order-data-provider/Orders.graphql | 5 +++++ .../order-data-provider/__generated__/Orders.ts | 15 ++++++++++----- .../lib/components/order-list/order-list.spec.tsx | 4 +++- libs/types/src/global-types-mappings.ts | 8 +++++++- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/libs/datagrid/src/lib/cells/order-type-cell.tsx b/libs/datagrid/src/lib/cells/order-type-cell.tsx index cb42b7884..127c6af1b 100644 --- a/libs/datagrid/src/lib/cells/order-type-cell.tsx +++ b/libs/datagrid/src/lib/cells/order-type-cell.tsx @@ -3,6 +3,7 @@ import { useMemo } from 'react'; import { useCallback } from 'react'; import { t } from '@vegaprotocol/i18n'; import * as Schema from '@vegaprotocol/types'; +import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; interface OrderTypeCellProps { value?: Schema.OrderType; @@ -23,7 +24,15 @@ export const OrderTypeCell = ({ } if (!value) return '-'; if (order?.peggedOrder) { - return t('Pegged'); + const reference = + Schema.PeggedReferenceMapping[order.peggedOrder?.reference]; + // the offset (e.g. + 0.001 for a Sell, or -1231.023 for a Buy) + const side = order.side === Schema.Side.SIDE_BUY ? '-' : '+'; + const offset = addDecimalsFormatNumber( + order.peggedOrder?.offset, + order.market.decimalPlaces + ); + return t('%s %s %s Peg limit', [reference, side, offset]); } if (order?.liquidityProvision) { return t('Liquidity provision'); diff --git a/libs/orders/src/lib/components/order-data-provider/Orders.graphql b/libs/orders/src/lib/components/order-data-provider/Orders.graphql index 67ba24909..e20a69734 100644 --- a/libs/orders/src/lib/components/order-data-provider/Orders.graphql +++ b/libs/orders/src/lib/components/order-data-provider/Orders.graphql @@ -21,6 +21,8 @@ fragment OrderFields on Order { } peggedOrder { __typename + reference + offset } } @@ -64,6 +66,7 @@ fragment OrderUpdateFields on OrderUpdate { type side size + remaining status rejectionReason price @@ -75,6 +78,8 @@ fragment OrderUpdateFields on OrderUpdate { liquidityProvisionId peggedOrder { __typename + reference + offset } } diff --git a/libs/orders/src/lib/components/order-data-provider/__generated__/Orders.ts b/libs/orders/src/lib/components/order-data-provider/__generated__/Orders.ts index 6b91e2f07..4bd8fd010 100644 --- a/libs/orders/src/lib/components/order-data-provider/__generated__/Orders.ts +++ b/libs/orders/src/lib/components/order-data-provider/__generated__/Orders.ts @@ -3,14 +3,14 @@ import * as Types from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type OrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null }; +export type OrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null }; export type OrderByIdQueryVariables = Types.Exact<{ orderId: Types.Scalars['ID']; }>; -export type OrderByIdQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null } }; +export type OrderByIdQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } }; export type OrdersQueryVariables = Types.Exact<{ partyId: Types.Scalars['ID']; @@ -20,9 +20,9 @@ export type OrdersQueryVariables = Types.Exact<{ }>; -export type OrdersQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, ordersConnection?: { __typename?: 'OrderConnection', edges?: Array<{ __typename?: 'OrderEdge', cursor?: string | null, node: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null } }> | null, pageInfo?: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } | null } | null } | null }; +export type OrdersQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, ordersConnection?: { __typename?: 'OrderConnection', edges?: Array<{ __typename?: 'OrderEdge', cursor?: string | null, node: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } }> | null, pageInfo?: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } | null } | null } | null }; -export type OrderUpdateFieldsFragment = { __typename?: 'OrderUpdate', id: string, marketId: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, liquidityProvisionId?: string | null, peggedOrder?: { __typename: 'PeggedOrder' } | null }; +export type OrderUpdateFieldsFragment = { __typename?: 'OrderUpdate', id: string, marketId: string, type?: Types.OrderType | null, side: Types.Side, size: string, remaining: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, liquidityProvisionId?: string | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null }; export type OrdersUpdateSubscriptionVariables = Types.Exact<{ partyId: Types.Scalars['ID']; @@ -30,7 +30,7 @@ export type OrdersUpdateSubscriptionVariables = Types.Exact<{ }>; -export type OrdersUpdateSubscription = { __typename?: 'Subscription', orders?: Array<{ __typename?: 'OrderUpdate', id: string, marketId: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, liquidityProvisionId?: string | null, peggedOrder?: { __typename: 'PeggedOrder' } | null }> | null }; +export type OrdersUpdateSubscription = { __typename?: 'Subscription', orders?: Array<{ __typename?: 'OrderUpdate', id: string, marketId: string, type?: Types.OrderType | null, side: Types.Side, size: string, remaining: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, liquidityProvisionId?: string | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null }> | null }; export const OrderFieldsFragmentDoc = gql` fragment OrderFields on Order { @@ -56,6 +56,8 @@ export const OrderFieldsFragmentDoc = gql` } peggedOrder { __typename + reference + offset } } `; @@ -66,6 +68,7 @@ export const OrderUpdateFieldsFragmentDoc = gql` type side size + remaining status rejectionReason price @@ -77,6 +80,8 @@ export const OrderUpdateFieldsFragmentDoc = gql` liquidityProvisionId peggedOrder { __typename + reference + offset } } `; diff --git a/libs/orders/src/lib/components/order-list/order-list.spec.tsx b/libs/orders/src/lib/components/order-list/order-list.spec.tsx index 20f66106e..9986614f5 100644 --- a/libs/orders/src/lib/components/order-list/order-list.spec.tsx +++ b/libs/orders/src/lib/components/order-list/order-list.spec.tsx @@ -213,6 +213,8 @@ describe('OrderListTable', () => { timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC, peggedOrder: { __typename: 'PeggedOrder', + reference: Schema.PeggedReference.PEGGED_REFERENCE_MID, + offset: '100', }, }); @@ -222,7 +224,7 @@ describe('OrderListTable', () => { const amendCell = getAmendCell(); const typeCell = screen.getAllByRole('gridcell')[2]; - expect(typeCell).toHaveTextContent('Pegged'); + expect(typeCell).toHaveTextContent('Mid - 10.0 Peg limit'); expect(amendCell.queryAllByRole('button')).toHaveLength(0); }); diff --git a/libs/types/src/global-types-mappings.ts b/libs/types/src/global-types-mappings.ts index 9eb11448e..159d43f8f 100644 --- a/libs/types/src/global-types-mappings.ts +++ b/libs/types/src/global-types-mappings.ts @@ -1,4 +1,4 @@ -import type { ConditionOperator } from './__generated__/types'; +import type { ConditionOperator, PeggedReference } from './__generated__/types'; import type { AccountType, AuctionTrigger, @@ -474,3 +474,9 @@ export const ConditionOperatorMapping: { [C in ConditionOperator]: string } = { OPERATOR_LESS_THAN: 'Less than', OPERATOR_LESS_THAN_OR_EQUAL: 'Less than or equal to', }; + +export const PeggedReferenceMapping: { [R in PeggedReference]: string } = { + PEGGED_REFERENCE_BEST_ASK: 'Ask', + PEGGED_REFERENCE_BEST_BID: 'Bid', + PEGGED_REFERENCE_MID: 'Mid', +}; From 653cec25921a3f43c5ddf2490950776497d46578 Mon Sep 17 00:00:00 2001 From: dexturr Date: Thu, 11 May 2023 12:07:57 +0000 Subject: [PATCH 11/19] chore: update tranches Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- apps/static/src/assets/mainnet-tranches.json | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/static/src/assets/mainnet-tranches.json b/apps/static/src/assets/mainnet-tranches.json index a79eb3079..90e55863e 100644 --- a/apps/static/src/assets/mainnet-tranches.json +++ b/apps/static/src/assets/mainnet-tranches.json @@ -49,7 +49,7 @@ "tranche_end": "2023-05-20T00:00:00.000Z", "total_added": "19242.125", "total_removed": "1979.64045368475", - "locked_amount": "5608.9383879726076446", + "locked_amount": "5448.4017548225310304875", "deposits": [ { "amount": "188", @@ -4907,7 +4907,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "86666.297", "total_removed": "0", - "locked_amount": "49327.3172923405910546417", + "locked_amount": "49267.8881106870934141481", "deposits": [ { "amount": "86666.297", @@ -4973,7 +4973,7 @@ "tranche_end": "2023-06-01T00:00:00.000Z", "total_added": "2500", "total_removed": "0", - "locked_amount": "284.955770502645375", + "locked_amount": "281.5177299552299", "deposits": [ { "amount": "2500", @@ -5006,7 +5006,7 @@ "tranche_end": "2023-11-01T00:00:00.000Z", "total_added": "15000.000000000000015", "total_removed": "0", - "locked_amount": "14163.9766379830905141639766379830905", + "locked_amount": "14143.5726147343005141435726147343005", "deposits": [ { "amount": "1.5e-14", @@ -5094,7 +5094,7 @@ "tranche_end": "2023-09-01T00:00:00.000Z", "total_added": "17500", "total_removed": "0", - "locked_amount": "10723.00897619766325", + "locked_amount": "10699.20428240740825", "deposits": [ { "amount": "12500", @@ -5361,7 +5361,7 @@ "tranche_end": "2023-08-01T00:00:00.000Z", "total_added": "37500", "total_removed": "18302.01762945", - "locked_amount": "16936.07322360343725", + "locked_amount": "16884.2176949048475", "deposits": [ { "amount": "7500", @@ -5791,7 +5791,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "129999.45", "total_removed": "0", - "locked_amount": "49282.312321912380332265", + "locked_amount": "49222.937361909470971875", "deposits": [ { "amount": "129999.45", @@ -5824,7 +5824,7 @@ "tranche_end": "2024-04-01T00:00:00.000Z", "total_added": "54144.7663", "total_removed": "0", - "locked_amount": "48189.54915726316779685587", + "locked_amount": "48152.52222157082703945313", "deposits": [ { "amount": "54144.7663", @@ -5857,7 +5857,7 @@ "tranche_end": "2023-09-03T00:00:00.000Z", "total_added": "62600", "total_removed": "0", - "locked_amount": "19679.51570903094634", + "locked_amount": "19636.5893708777252", "deposits": [ { "amount": "10000", @@ -6050,7 +6050,7 @@ "tranche_end": "2023-09-17T00:00:00.000Z", "total_added": "5000", "total_removed": "0", - "locked_amount": "1763.627124556063", + "locked_amount": "1760.1985032978185", "deposits": [ { "amount": "5000", @@ -7119,7 +7119,7 @@ "tranche_end": "2023-06-02T00:00:00.000Z", "total_added": "1939928.38", "total_removed": "1709370.7872515768348", - "locked_amount": "115570.728817751808474185", + "locked_amount": "114240.47288112379901012188", "deposits": [ { "amount": "1852091.69", @@ -40991,7 +40991,7 @@ "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "3732368.4671", "total_removed": "715655.108029600523393", - "locked_amount": "202093.2974680882797136777084", + "locked_amount": "200049.157239417195653993231", "deposits": [ { "amount": "1998.95815", @@ -42384,7 +42384,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "15870102.715470999700000001", "total_removed": "873375.18460711694221852", - "locked_amount": "6016297.4428328087189762607645230040375777", + "locked_amount": "6009049.0528282882857238651980333316436875", "deposits": [ { "amount": "16249.93", @@ -59171,7 +59171,7 @@ "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "472355.6199999996", "total_removed": "44544.1737890903416", - "locked_amount": "32022.838198356764871382775241", + "locked_amount": "31698.932494320098793185875900572", "deposits": [ { "amount": "3000", From bf73559c301ae74c8319dc0e6597e80d7b9ae4b9 Mon Sep 17 00:00:00 2001 From: Sam Keen Date: Thu, 11 May 2023 13:39:30 +0100 Subject: [PATCH 12/19] fix(governance): change proposal sort order (#3716) --- .../components/proposals-list/proposals-list.spec.tsx | 4 ---- .../src/routes/proposals/proposals/proposals-container.tsx | 7 +++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/governance/src/routes/proposals/components/proposals-list/proposals-list.spec.tsx b/apps/governance/src/routes/proposals/components/proposals-list/proposals-list.spec.tsx index 6a37b4e72..2016f0633 100644 --- a/apps/governance/src/routes/proposals/components/proposals-list/proposals-list.spec.tsx +++ b/apps/governance/src/routes/proposals/components/proposals-list/proposals-list.spec.tsx @@ -24,7 +24,6 @@ const openProposalClosesNextMonth = generateProposal({ }, terms: { closingDatetime: nextMonth.toString(), - enactmentDatetime: nextMonth.toString(), }, }); @@ -36,7 +35,6 @@ const openProposalClosesNextWeek = generateProposal({ }, terms: { closingDatetime: nextWeek.toString(), - enactmentDatetime: nextWeek.toString(), }, }); @@ -45,7 +43,6 @@ const enactedProposalClosedLastWeek = generateProposal({ state: ProposalState.STATE_ENACTED, terms: { closingDatetime: lastWeek.toString(), - enactmentDatetime: lastWeek.toString(), }, }); @@ -54,7 +51,6 @@ const failedProposalClosedLastMonth = generateProposal({ state: ProposalState.STATE_FAILED, terms: { closingDatetime: lastMonth.toString(), - enactmentDatetime: lastMonth.toString(), }, }); diff --git a/apps/governance/src/routes/proposals/proposals/proposals-container.tsx b/apps/governance/src/routes/proposals/proposals/proposals-container.tsx index 7d63a91f2..29b289d27 100644 --- a/apps/governance/src/routes/proposals/proposals/proposals-container.tsx +++ b/apps/governance/src/routes/proposals/proposals/proposals-container.tsx @@ -20,8 +20,11 @@ import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals'; const orderByDate = (arr: ProposalFieldsFragment[]) => orderBy( arr, - [(p) => new Date(p?.terms?.closingDatetime).getTime(), (p) => p.id], - ['desc', 'desc'] + [ + (p) => new Date(p?.terms?.closingDatetime).getTime(), + (p) => new Date(p?.datetime).getTime(), + ], + ['asc', 'asc'] ); const orderByUpgradeBlockHeight = ( From b641c82ad8744fa2e2710e71b35060c92d747040 Mon Sep 17 00:00:00 2001 From: Sam Keen Date: Thu, 11 May 2023 13:59:28 +0100 Subject: [PATCH 13/19] feat(governance): voting blog link and button title (#3717) --- apps/governance/src/i18n/translations/dev.json | 1 + .../components/vote-details/vote-buttons.spec.tsx | 4 +++- .../components/vote-details/vote-buttons.tsx | 14 ++++++++++++-- .../components/vote-details/vote-details.tsx | 12 ++++++++++-- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/apps/governance/src/i18n/translations/dev.json b/apps/governance/src/i18n/translations/dev.json index d714cc82b..c8f60b63b 100644 --- a/apps/governance/src/i18n/translations/dev.json +++ b/apps/governance/src/i18n/translations/dev.json @@ -202,6 +202,7 @@ "tokenVotes": "Token votes", "liquidityVotes": "Liquidity votes", "castYourVote": "Cast your vote", + "yourVote": "Your vote", "for": "For", "against": "Against", "majorityRequired": "Majority Required", diff --git a/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.spec.tsx b/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.spec.tsx index d4aa90279..7f1ae36b6 100644 --- a/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.spec.tsx +++ b/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.spec.tsx @@ -111,7 +111,9 @@ describe('Vote buttons', () => { ); expect( - screen.getByText('You need some VEGA tokens to participate in governance') + screen.getByText( + 'You need some VEGA tokens to participate in governance.' + ) ).toBeTruthy(); }); diff --git a/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.tsx b/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.tsx index 3101758f6..7b2c16203 100644 --- a/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.tsx +++ b/apps/governance/src/routes/proposals/components/vote-details/vote-buttons.tsx @@ -2,7 +2,12 @@ import { format } from 'date-fns'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet'; -import { AsyncRenderer, Button, ButtonLink } from '@vegaprotocol/ui-toolkit'; +import { + AsyncRenderer, + Button, + ButtonLink, + ExternalLink, +} from '@vegaprotocol/ui-toolkit'; import { addDecimal, toBigNum } from '@vegaprotocol/utils'; import { ProposalState, VoteValue } from '@vegaprotocol/types'; import { @@ -161,7 +166,12 @@ export const VoteButtons = ({ {changeVote || (voteState === VoteState.NotCast && proposalVotable) ? ( <> {currentStakeAvailable.isLessThanOrEqualTo(0) && ( -

{t('noGovernanceTokens')}

+ <> +

{t('noGovernanceTokens')}.

+ + {t('findOutMoreAboutHowToVote')} + + )}
diff --git a/apps/governance/src/routes/proposals/components/vote-details/vote-details.tsx b/apps/governance/src/routes/proposals/components/vote-details/vote-details.tsx index 19746d9c2..a819118a4 100644 --- a/apps/governance/src/routes/proposals/components/vote-details/vote-details.tsx +++ b/apps/governance/src/routes/proposals/components/vote-details/vote-details.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import { formatDistanceToNow } from 'date-fns'; -import { RoundedWrapper, Icon } from '@vegaprotocol/ui-toolkit'; +import { RoundedWrapper, Icon, ExternalLink } from '@vegaprotocol/ui-toolkit'; import { useVegaWallet } from '@vegaprotocol/wallet'; import { ProposalState } from '@vegaprotocol/types'; import { useVoteSubmit, VoteProgress } from '@vegaprotocol/proposals'; @@ -202,7 +202,12 @@ export const VoteDetails = ({ )}
- + {proposal?.state === ProposalState.STATE_OPEN ? ( + + ) : ( + + )} + {pubKey ? ( proposal && (
{t('connectAVegaWalletToVote')}
+ + {t('findOutMoreAboutHowToVote')} +
From f121836b4eced6cc8ee6e65f11efac0f887aa3f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20M=C5=82odzikowski?= Date: Thu, 11 May 2023 15:42:35 +0200 Subject: [PATCH 14/19] feat(ci): fleek updates (#3724) --- .github/workflows/publish-dist.yml | 16 +++++++++++++++ Makefile | 2 +- docker/ipfs.Dockerfile | 29 --------------------------- docker/node-inside-docker.Dockerfile | 2 +- docker/node-outside-docker.Dockerfile | 2 +- 5 files changed, 19 insertions(+), 32 deletions(-) delete mode 100644 docker/ipfs.Dockerfile diff --git a/.github/workflows/publish-dist.yml b/.github/workflows/publish-dist.yml index 6b1ee0686..3d081a1ed 100644 --- a/.github/workflows/publish-dist.yml +++ b/.github/workflows/publish-dist.yml @@ -148,6 +148,7 @@ jobs: ENV_NAME=${{ env.ENV_NAME }} tags: | vegaprotocol/${{ matrix.app }}:${{ github.ref_name }} + vegaprotocol/${{ matrix.app }}:mainnet # bucket creation in github.com/vegaprotocol/terraform//frontend - name: Publish dist to s3 @@ -174,3 +175,18 @@ jobs: if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} with: files: ${{ matrix.app }}-ipfs-hash + + - name: Trigger fleek deployment + if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} + run: | + # display info about app + curl -H "Authorization: $FLEEK_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \ + https://api.fleek.co/graphql + + # trigger new deployment as base image is always set to vegaprotocol/trading:mainnet + curl -H "Authorization: $FLEEK_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \ + https://api.fleek.co/graphql diff --git a/Makefile b/Makefile index c5bda8cb0..e28979c2b 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ recalculate-ipfs: echo "ipfs hash inside the image" docker run --rm ${TAG} cat /ipfs-hash echo "recalculating ipfs hash" - docker run --rm ${TAG} ipfs add -rw /usr/share/nginx/html + docker run --rm ${TAG} ipfs add -r /usr/share/nginx/html .PHONY: eject-ipfs-hash unpack: diff --git a/docker/ipfs.Dockerfile b/docker/ipfs.Dockerfile deleted file mode 100644 index c8c62332b..000000000 --- a/docker/ipfs.Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -# Build container -ARG NODE_VERSION -FROM --platform=amd64 node:${NODE_VERSION}-alpine3.16 as build -WORKDIR /app -# Argument to allow building of different apps -ARG APP -ARG ENV_NAME="" -RUN apk add --update --no-cache \ - python3 \ - make \ - gcc \ - g++ -COPY . ./ -RUN yarn --network-timeout 100000 --pure-lockfile -# work around for different build process in trading -RUN sh docker/docker-build.sh - -# Server environment -# if this fails you need to docker pull nginx:1.23-alpine and pin new SHA -# this is to ensure that we run always same version of alpine to make sure ipfs is indempotent -FROM --platform=amd64 nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629 -# configuration of system -EXPOSE 80 -# Copy dist -WORKDIR /usr/share/nginx/html -COPY docker/nginx.conf /etc/nginx/conf.d/default.conf -RUN rm -rf /usr/share/nginx/html/* -COPY --from=build /app/dist/apps/${APP}/* /usr/share/nginx/html -RUN apk add --no-cache go-ipfs; ipfs init && echo "$(ipfs add -rQ .)" > /ipfs-hash; apk del go-ipfs diff --git a/docker/node-inside-docker.Dockerfile b/docker/node-inside-docker.Dockerfile index e15f15a58..9635d4cbd 100644 --- a/docker/node-inside-docker.Dockerfile +++ b/docker/node-inside-docker.Dockerfile @@ -27,5 +27,5 @@ RUN rm -rf /usr/share/nginx/html/* COPY --from=build /app/dist/apps/${APP}/* /usr/share/nginx/html RUN apk add --no-cache go-ipfs==0.16.0-r6 \ && ipfs init \ - && echo "$(ipfs add -rwQ /usr/share/nginx/html)" > /ipfs-hash \ + && echo "$(ipfs add -rQ /usr/share/nginx/html)" > /ipfs-hash \ && echo "ipfs hash of this build: $(cat /ipfs-hash)" diff --git a/docker/node-outside-docker.Dockerfile b/docker/node-outside-docker.Dockerfile index 52d0d8896..e185fa8bc 100644 --- a/docker/node-outside-docker.Dockerfile +++ b/docker/node-outside-docker.Dockerfile @@ -5,6 +5,6 @@ RUN rm -rf /usr/share/nginx/html/* COPY ./dist-result/ /usr/share/nginx/html/ RUN apk add --no-cache go-ipfs==0.16.0-r6 \ && ipfs init \ - && echo "$(ipfs add -rwQ /usr/share/nginx/html)" > /ipfs-hash \ + && echo "$(ipfs add -rQ /usr/share/nginx/html)" > /ipfs-hash \ && echo "ipfs hash of this build: $(cat /ipfs-hash)" From 8a080d3279f31d6d1fe6e1d81f7de2954fea27d3 Mon Sep 17 00:00:00 2001 From: Edd Date: Thu, 11 May 2023 15:55:00 +0100 Subject: [PATCH 15/19] fix(explorer): fix bug where no votes displayed a yes icon (#3699) --- .../chain-reponse.code.tsx | 10 ++++- .../txs/details/tx-proposal-vote.tsx | 16 +++----- .../src/app/components/txs/tx-order-type.tsx | 16 +++++++- .../txs/txs-infinite-list-item.spec.tsx | 2 +- .../components/txs/txs-infinite-list-item.tsx | 4 +- .../components/vote-icon/vote-icon.spec.tsx | 37 +++++++++++++++++ .../app/components/vote-icon/vote-icon.tsx | 40 +++++++++++++++++++ apps/explorer/src/styles.css | 4 ++ 8 files changed, 113 insertions(+), 16 deletions(-) create mode 100644 apps/explorer/src/app/components/vote-icon/vote-icon.spec.tsx create mode 100644 apps/explorer/src/app/components/vote-icon/vote-icon.tsx diff --git a/apps/explorer/src/app/components/txs/details/chain-response-code/chain-reponse.code.tsx b/apps/explorer/src/app/components/txs/details/chain-response-code/chain-reponse.code.tsx index d1f95db5c..ba4be4ef8 100644 --- a/apps/explorer/src/app/components/txs/details/chain-response-code/chain-reponse.code.tsx +++ b/apps/explorer/src/app/components/txs/details/chain-response-code/chain-reponse.code.tsx @@ -1,3 +1,5 @@ +import { Icon } from '@vegaprotocol/ui-toolkit'; + // https://github.com/vegaprotocol/vega/blob/develop/core/blockchain/response.go export const ErrorCodes = new Map([ [51, 'Transaction failed validation'], @@ -28,7 +30,11 @@ export const ChainResponseCode = ({ }: ChainResponseCodeProps) => { const isSuccess = successCodes.has(code); - const icon = isSuccess ? '✅' : '❌'; + const icon = isSuccess ? ( + + ) : ( + + ); const label = ErrorCodes.get(code) || 'Unknown response code'; // Hack for batches with many errors - see https://github.com/vegaprotocol/vega/issues/7245 @@ -36,7 +42,7 @@ export const ChainResponseCode = ({ error && error.length > 100 ? error.replace(/,/g, ',\r\n') : error; return ( -
+
{t('Awaiting Block Explorer transaction details')}; } - const vote = txData.command.voteSubmission.value ? '👍' : '👎'; + const vote = txData.command.voteSubmission.value === 'VALUE_YES'; + return ( - - {t('Proposal ID')} - {txData.command.voteSubmission.proposalId} - {t('Proposal details')} - - {t('Proposal')} - {txData.command.voteSubmission.proposalId} - {t('Vote')} - {vote} + + + ); diff --git a/apps/explorer/src/app/components/txs/tx-order-type.tsx b/apps/explorer/src/app/components/txs/tx-order-type.tsx index cb11be8d8..1280d8c82 100644 --- a/apps/explorer/src/app/components/txs/tx-order-type.tsx +++ b/apps/explorer/src/app/components/txs/tx-order-type.tsx @@ -1,5 +1,6 @@ import { t } from '@vegaprotocol/i18n'; import type { components } from '../../../types/explorer'; +import { VoteIcon } from '../vote-icon/vote-icon'; interface TxOrderTypeProps { orderType: string; @@ -137,12 +138,15 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => { let type = displayString[orderType] || orderType; let colours = - 'text-white dark:text-white bg-vega-dark-150 dark:bg-vega-dark-150'; + 'text-white dark:text-white bg-vega-dark-150 dark:bg-vega-dark-250'; // This will get unwieldy and should probably produce a different colour of tag if (type === 'Chain Event' && !!command?.chainEvent) { type = getLabelForChainEvent(command.chainEvent); colours = 'text-white dark-text-white bg-vega-pink dark:bg-vega-pink'; + } else if (type === 'Validator Heartbeat') { + colours = + 'text-white dark-text-white bg-vega-light-200 dark:bg-vega-dark-100'; } else if (type === 'Proposal' || type === 'Governance Proposal') { if (command && !!command.proposalSubmission) { type = getLabelForProposal(command.proposalSubmission); @@ -150,6 +154,16 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => { colours = 'text-black bg-vega-yellow'; } + if (type === 'Vote on Proposal') { + return ( + + ); + } + if (type === 'Vote on Proposal' || type === 'Vote Submission') { colours = 'text-black bg-vega-yellow'; } diff --git a/apps/explorer/src/app/components/txs/txs-infinite-list-item.spec.tsx b/apps/explorer/src/app/components/txs/txs-infinite-list-item.spec.tsx index 56bf8f445..b83eb4fc9 100644 --- a/apps/explorer/src/app/components/txs/txs-infinite-list-item.spec.tsx +++ b/apps/explorer/src/app/components/txs/txs-infinite-list-item.spec.tsx @@ -98,6 +98,6 @@ describe('Txs infinite list item', () => { expect(screen.getByTestId('pub-key')).toHaveTextContent('testPubKey'); expect(screen.getByTestId('tx-type')).toHaveTextContent('testType'); expect(screen.getByTestId('tx-block')).toHaveTextContent('1'); - expect(screen.getByTestId('tx-success')).toHaveTextContent('Success: ✅'); + expect(screen.getByTestId('tx-success')).toHaveTextContent('Success'); }); }); diff --git a/apps/explorer/src/app/components/txs/txs-infinite-list-item.tsx b/apps/explorer/src/app/components/txs/txs-infinite-list-item.tsx index 2ce8bcc0f..8f761b01c 100644 --- a/apps/explorer/src/app/components/txs/txs-infinite-list-item.tsx +++ b/apps/explorer/src/app/components/txs/txs-infinite-list-item.tsx @@ -31,7 +31,7 @@ export const TxsInfiniteListItem = ({ return (
- Success:  + Success  {isNumber(code) ? ( diff --git a/apps/explorer/src/app/components/vote-icon/vote-icon.spec.tsx b/apps/explorer/src/app/components/vote-icon/vote-icon.spec.tsx new file mode 100644 index 000000000..b26323803 --- /dev/null +++ b/apps/explorer/src/app/components/vote-icon/vote-icon.spec.tsx @@ -0,0 +1,37 @@ +import { render } from '@testing-library/react'; +import { VoteIcon } from './vote-icon'; + +describe('Vote TX icon', () => { + it('should use the text For by default for yes votes', () => { + const yes = render(); + expect(yes.getByTestId('label')).toHaveTextContent('For'); + }); + + it('should use the yesText for yes votes if specified', () => { + const yes = render(); + expect(yes.getByTestId('label')).toHaveTextContent('Test'); + }); + + it('should display the tick icon for yes votes', () => { + const no = render(); + expect(no.getByRole('img')).toHaveAttribute( + 'aria-label', + 'tick-circle icon' + ); + }); + + it('should use the text Against by default for no votes', () => { + const no = render(); + expect(no.getByTestId('label')).toHaveTextContent('Against'); + }); + + it('should use the noText for no votes if specified', () => { + const no = render(); + expect(no.getByTestId('label')).toHaveTextContent('Test'); + }); + + it('should display the delete icon for no votes', () => { + const no = render(); + expect(no.getByRole('img')).toHaveAttribute('aria-label', 'delete icon'); + }); +}); diff --git a/apps/explorer/src/app/components/vote-icon/vote-icon.tsx b/apps/explorer/src/app/components/vote-icon/vote-icon.tsx new file mode 100644 index 000000000..f7b29e6d7 --- /dev/null +++ b/apps/explorer/src/app/components/vote-icon/vote-icon.tsx @@ -0,0 +1,40 @@ +import { Icon } from '@vegaprotocol/ui-toolkit'; +import type { IconName } from '@vegaprotocol/ui-toolkit'; + +export interface VoteIconProps { + // True is a yes vote, false is undefined or no vorte + vote: boolean; + // Defaults to 'For', but can be any text + yesText?: string; + // Defaults to 'Against', but can be any text + noText?: string; +} + +/** + * Displays a lozenge with an icon representing the way a user voted for a proposal. + * The yes and no text can be overridden + * + * @returns + */ +export function VoteIcon({ + vote, + yesText = 'For', + noText = 'Against', +}: VoteIconProps) { + const label = vote ? yesText : noText; + const bg = vote ? 'bg-vega-green-550' : 'bg-vega-pink-550'; + const icon: IconName = vote ? 'tick-circle' : 'delete'; + const fill = vote ? 'vega-green-300' : 'vega-pink-300'; + const text = vote ? 'vega-green-200' : 'vega-pink-200'; + + return ( +
+ + + {label} + +
+ ); +} diff --git a/apps/explorer/src/styles.css b/apps/explorer/src/styles.css index 594a3d81d..831d10a77 100644 --- a/apps/explorer/src/styles.css +++ b/apps/explorer/src/styles.css @@ -60,3 +60,7 @@ --ag-row-hover-color: theme(colors.neutral[800]); --ag-font-size: 12px; } + +.voteicon svg { + vertical-align: baseline; +} From bca1a98985bf547f4df4982ef43b94a5d4fffa50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20M=C5=82odzikowski?= Date: Thu, 11 May 2023 17:16:28 +0200 Subject: [PATCH 16/19] fix(ci): remove old dockerfile --- docker/dist.Dockerfile | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 docker/dist.Dockerfile diff --git a/docker/dist.Dockerfile b/docker/dist.Dockerfile deleted file mode 100644 index 1e44628a4..000000000 --- a/docker/dist.Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM --platform=amd64 nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629 -EXPOSE 80 -WORKDIR /usr/share/nginx/html -COPY docker/nginx.conf /etc/nginx/conf.d/default.conf -RUN rm -rf /usr/share/nginx/html/* -COPY ./dist-result/ /usr/share/nginx/html/ From 2d430710ab877521c89d2c9a886e87aef7aa8a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20M=C5=82odzikowski?= Date: Thu, 11 May 2023 17:31:12 +0200 Subject: [PATCH 17/19] feat(ci): use actual secret in the script --- .github/workflows/publish-dist.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-dist.yml b/.github/workflows/publish-dist.yml index 3d081a1ed..a30858106 100644 --- a/.github/workflows/publish-dist.yml +++ b/.github/workflows/publish-dist.yml @@ -180,13 +180,13 @@ jobs: if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} run: | # display info about app - curl -H "Authorization: $FLEEK_API_KEY" \ + curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \ -H "Content-Type: application/json" \ -d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \ https://api.fleek.co/graphql # trigger new deployment as base image is always set to vegaprotocol/trading:mainnet - curl -H "Authorization: $FLEEK_API_KEY" \ + curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \ -H "Content-Type: application/json" \ -d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \ https://api.fleek.co/graphql From efeac49d581adafecce2e155100b9cff22b22bd2 Mon Sep 17 00:00:00 2001 From: Sam Keen Date: Thu, 11 May 2023 16:43:27 +0100 Subject: [PATCH 18/19] feat(governance): change status labels for network upgrade proposals (#3711) --- apps/governance/src/i18n/translations/dev.json | 6 +++--- .../protocol-upgrade-proposal-detail-info.spec.tsx | 4 +++- .../protocol-upgrade-proposals-list-item.spec.tsx | 8 +++++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/governance/src/i18n/translations/dev.json b/apps/governance/src/i18n/translations/dev.json index c8f60b63b..e8776b4af 100644 --- a/apps/governance/src/i18n/translations/dev.json +++ b/apps/governance/src/i18n/translations/dev.json @@ -788,9 +788,9 @@ "homeVegaTokenButtonText": "Manage tokens", "downloadProposalJson": "Download proposal as JSON", "networkUpgrade": "Network Upgrade", - "PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED": "Approved", - "PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING": "Pending", - "PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED": "Rejected", + "PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED": "Approved by validators", + "PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING": "Waiting for validator votes", + "PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED": "Declined by validators", "PROTOCOL_UPGRADE_PROPOSAL_STATUS_UNSPECIFIED": "Unspecified", "vegaRelease{release}": "Vega Release {{release}}", "upgradeBlockHeight": "Upgrade block height", diff --git a/apps/governance/src/routes/proposals/components/protocol-upgrade-proposal-detail-info/protocol-upgrade-proposal-detail-info.spec.tsx b/apps/governance/src/routes/proposals/components/protocol-upgrade-proposal-detail-info/protocol-upgrade-proposal-detail-info.spec.tsx index 2ec6b2f65..2e3a4d614 100644 --- a/apps/governance/src/routes/proposals/components/protocol-upgrade-proposal-detail-info/protocol-upgrade-proposal-detail-info.spec.tsx +++ b/apps/governance/src/routes/proposals/components/protocol-upgrade-proposal-detail-info/protocol-upgrade-proposal-detail-info.spec.tsx @@ -32,7 +32,9 @@ describe('ProtocolUpgradeProposalDetailInfo', () => { it('should render the state', () => { const { getByTestId } = renderComponent(); - expect(getByTestId('protocol-upgrade-state')).toHaveTextContent('Pending'); + expect(getByTestId('protocol-upgrade-state')).toHaveTextContent( + 'Waiting for validator votes' + ); }); it('should render the vega release tag', () => { diff --git a/apps/governance/src/routes/proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item.spec.tsx b/apps/governance/src/routes/proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item.spec.tsx index 4d0bdce7f..47a035b29 100644 --- a/apps/governance/src/routes/proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item.spec.tsx +++ b/apps/governance/src/routes/proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item.spec.tsx @@ -26,28 +26,34 @@ describe('ProtocolUpgradeProposalsListItem', () => { status: ProtocolUpgradeProposalStatus.PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED, icon: 'protocol-upgrade-proposal-status-icon-rejected', + text: 'Declined by validators', }, { status: ProtocolUpgradeProposalStatus.PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING, icon: 'protocol-upgrade-proposal-status-icon-pending', + text: 'Waiting for validator votes', }, { status: ProtocolUpgradeProposalStatus.PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED, icon: 'protocol-upgrade-proposal-status-icon-approved', + text: 'Approved by validators', }, { status: ProtocolUpgradeProposalStatus.PROTOCOL_UPGRADE_PROPOSAL_STATUS_UNSPECIFIED, icon: 'protocol-upgrade-proposal-status-icon-unspecified', + text: 'Unspecified', }, ]; - statuses.forEach(({ status, icon }) => { + statuses.forEach(({ status, icon, text }) => { renderComponent({ ...proposal, status }); const statusIcon = screen.getByTestId(icon); + const textContent = screen.getByText(text); expect(statusIcon).toBeInTheDocument(); + expect(textContent).toBeInTheDocument(); }); }); From ad9a3a3400e88494fa44f8a5f89f64e13ebeef75 Mon Sep 17 00:00:00 2001 From: dexturr Date: Thu, 11 May 2023 18:10:08 +0000 Subject: [PATCH 19/19] chore: update tranches Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- apps/static/src/assets/mainnet-tranches.json | 158 +++++++++++++++---- 1 file changed, 129 insertions(+), 29 deletions(-) diff --git a/apps/static/src/assets/mainnet-tranches.json b/apps/static/src/assets/mainnet-tranches.json index 90e55863e..8996c2f93 100644 --- a/apps/static/src/assets/mainnet-tranches.json +++ b/apps/static/src/assets/mainnet-tranches.json @@ -1,4 +1,37 @@ [ + { + "tranche_id": 59, + "tranche_start": "2024-05-01T00:00:00.000Z", + "tranche_end": "2024-11-01T00:00:00.000Z", + "total_added": "15000", + "total_removed": "0", + "locked_amount": "15000", + "deposits": [ + { + "amount": "15000", + "user": "0xA530ac2B576eF27C09B7b55C83b3E163D167e9AE", + "tx": "0x90af73d7321833fc32445850655a1210f0298845b9222e695e1229801f7a95b0" + } + ], + "withdrawals": [], + "users": [ + { + "address": "0xA530ac2B576eF27C09B7b55C83b3E163D167e9AE", + "deposits": [ + { + "amount": "15000", + "user": "0xA530ac2B576eF27C09B7b55C83b3E163D167e9AE", + "tranche_id": 59, + "tx": "0x90af73d7321833fc32445850655a1210f0298845b9222e695e1229801f7a95b0" + } + ], + "withdrawals": [], + "total_tokens": "15000", + "withdrawn_tokens": "0", + "remaining_tokens": "15000" + } + ] + }, { "tranche_id": 58, "tranche_start": "2023-05-11T00:00:00.000Z", @@ -48,8 +81,8 @@ "tranche_start": "2023-04-20T00:00:00.000Z", "tranche_end": "2023-05-20T00:00:00.000Z", "total_added": "19242.125", - "total_removed": "1979.64045368475", - "locked_amount": "5448.4017548225310304875", + "total_removed": "2249.511113406525", + "locked_amount": "5287.07079012345751942375", "deposits": [ { "amount": "188", @@ -238,6 +271,11 @@ "user": "0xDd7a98557586ce21f770662319C2047C5a3bD605", "tx": "0x47f5bf2c758c5270dd1b6519ac649ddabef8199f8a0bae319e36f8ac5c9c142e" }, + { + "amount": "269.870659721775", + "user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756", + "tx": "0x156ef84c345adecdf7b1c55756b1f4326716d1b0191ce1a208f614fc807ce033" + }, { "amount": "202.093666077975", "user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756", @@ -311,6 +349,12 @@ } ], "withdrawals": [ + { + "amount": "269.870659721775", + "user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756", + "tranche_id": 56, + "tx": "0x156ef84c345adecdf7b1c55756b1f4326716d1b0191ce1a208f614fc807ce033" + }, { "amount": "202.093666077975", "user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756", @@ -337,8 +381,8 @@ } ], "total_tokens": "1207.5", - "withdrawn_tokens": "597.002068860225", - "remaining_tokens": "610.497931139775" + "withdrawn_tokens": "866.872728582", + "remaining_tokens": "340.627271418" }, { "address": "0x33Ce1D9E53AFb7367E34749517C086405a651a95", @@ -4907,7 +4951,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "86666.297", "total_removed": "0", - "locked_amount": "49267.8881106870934141481", + "locked_amount": "49208.1648748168474557617", "deposits": [ { "amount": "86666.297", @@ -4973,7 +5017,7 @@ "tranche_end": "2023-06-01T00:00:00.000Z", "total_added": "2500", "total_removed": "0", - "locked_amount": "281.5177299552299", + "locked_amount": "278.062678062677975", "deposits": [ { "amount": "2500", @@ -5006,7 +5050,7 @@ "tranche_end": "2023-11-01T00:00:00.000Z", "total_added": "15000.000000000000015", "total_removed": "0", - "locked_amount": "14143.5726147343005141435726147343005", + "locked_amount": "14123.0676328502415141230676328502415", "deposits": [ { "amount": "1.5e-14", @@ -5048,10 +5092,15 @@ "tranche_id": 46, "tranche_start": "2023-11-01T00:00:00.000Z", "tranche_end": "2024-05-01T00:00:00.000Z", - "total_added": "7500", + "total_added": "22500", "total_removed": "0", - "locked_amount": "7500", + "locked_amount": "22500", "deposits": [ + { + "amount": "15000", + "user": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1", + "tx": "0x959f5eed214f5376e834c2c20ed2a23a75c4465240c2776452ade80afa11ae2e" + }, { "amount": "7500", "user": "0xA530ac2B576eF27C09B7b55C83b3E163D167e9AE", @@ -5060,6 +5109,21 @@ ], "withdrawals": [], "users": [ + { + "address": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1", + "deposits": [ + { + "amount": "15000", + "user": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1", + "tranche_id": 46, + "tx": "0x959f5eed214f5376e834c2c20ed2a23a75c4465240c2776452ade80afa11ae2e" + } + ], + "withdrawals": [], + "total_tokens": "15000", + "withdrawn_tokens": "0", + "remaining_tokens": "15000" + }, { "address": "0xA530ac2B576eF27C09B7b55C83b3E163D167e9AE", "deposits": [ @@ -5094,7 +5158,7 @@ "tranche_end": "2023-09-01T00:00:00.000Z", "total_added": "17500", "total_removed": "0", - "locked_amount": "10699.20428240740825", + "locked_amount": "10675.28180354267275", "deposits": [ { "amount": "12500", @@ -5361,7 +5425,7 @@ "tranche_end": "2023-08-01T00:00:00.000Z", "total_added": "37500", "total_removed": "18302.01762945", - "locked_amount": "16884.2176949048475", + "locked_amount": "16832.105586249231", "deposits": [ { "amount": "7500", @@ -5791,7 +5855,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "129999.45", "total_removed": "0", - "locked_amount": "49222.937361909470971875", + "locked_amount": "49163.268615977288540103", "deposits": [ { "amount": "129999.45", @@ -5824,7 +5888,7 @@ "tranche_end": "2024-04-01T00:00:00.000Z", "total_added": "54144.7663", "total_removed": "0", - "locked_amount": "48152.52222157082703945313", + "locked_amount": "48115.3120774567914603646", "deposits": [ { "amount": "54144.7663", @@ -5857,7 +5921,7 @@ "tranche_end": "2023-09-03T00:00:00.000Z", "total_added": "62600", "total_removed": "0", - "locked_amount": "19636.5893708777252", + "locked_amount": "19593.45063419583921", "deposits": [ { "amount": "10000", @@ -6050,7 +6114,7 @@ "tranche_end": "2023-09-17T00:00:00.000Z", "total_added": "5000", "total_removed": "0", - "locked_amount": "1760.1985032978185", + "locked_amount": "1756.75291730086225", "deposits": [ { "amount": "5000", @@ -7119,7 +7183,7 @@ "tranche_end": "2023-06-02T00:00:00.000Z", "total_added": "1939928.38", "total_removed": "1709370.7872515768348", - "locked_amount": "114240.47288112379901012188", + "locked_amount": "112903.63486887882332299572", "deposits": [ { "amount": "1852091.69", @@ -40991,7 +41055,7 @@ "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "3732368.4671", "total_removed": "715655.108029600523393", - "locked_amount": "200049.157239417195653993231", + "locked_amount": "197994.9026521577907178460714", "deposits": [ { "amount": "1998.95815", @@ -42384,7 +42448,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "15870102.715470999700000001", "total_removed": "873375.18460711694221852", - "locked_amount": "6009049.0528282882857238651980333316436875", + "locked_amount": "6001764.79795761708228590023997882734847254", "deposits": [ { "amount": "16249.93", @@ -59171,7 +59235,7 @@ "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "472355.6199999996", "total_removed": "44544.1737890903416", - "locked_amount": "31698.932494320098793185875900572", + "locked_amount": "31373.424112349038235182155657024", "deposits": [ { "amount": "3000", @@ -88971,7 +89035,7 @@ "tranche_start": "2021-12-05T00:00:00.000Z", "tranche_end": "2022-06-05T00:00:00.000Z", "total_added": "171288.42", - "total_removed": "70140.5995794947989", + "total_removed": "70890.5995794947989", "locked_amount": "0", "deposits": [ { @@ -93196,6 +93260,21 @@ } ], "withdrawals": [ + { + "amount": "250", + "user": "0xcAEbd70D80D5aB92Ae5A2E1c92F479298826548C", + "tx": "0x7ffbc82e96bb7c796feb548a7ca48a7430a47dae3f2e9de859e6d45ac31a4e6c" + }, + { + "amount": "250", + "user": "0xac494D6eC2CcA7C9BD1caD0c1D0516F3706c6b7c", + "tx": "0x85a5d2a4faa6490fc25e080f09dc4d9b5fb3857d762042ba2dcbc0f04de41e0c" + }, + { + "amount": "250", + "user": "0x4eE1C5ED78143f298ae4E5E17e538a99E8512db7", + "tx": "0xcb7b99dc5240cdcaaed2fae06e9fd8172db0387179fe09b5f1e1cefff16c6025" + }, { "amount": "250", "user": "0x0E3407C9A94effa675471afe7A9D37e687C32141", @@ -98054,10 +98133,17 @@ "tx": "0x1c2c084e3efafb2ffa09c0b259bd229cce0d6da04dd092d911c7e6136a7ac8a9" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "250", + "user": "0x4eE1C5ED78143f298ae4E5E17e538a99E8512db7", + "tranche_id": 6, + "tx": "0xcb7b99dc5240cdcaaed2fae06e9fd8172db0387179fe09b5f1e1cefff16c6025" + } + ], "total_tokens": "250", - "withdrawn_tokens": "0", - "remaining_tokens": "250" + "withdrawn_tokens": "250", + "remaining_tokens": "0" }, { "address": "0x1dC24e9601e40013a12CB9976a519860c4eDF359", @@ -98436,10 +98522,17 @@ "tx": "0x1c2c084e3efafb2ffa09c0b259bd229cce0d6da04dd092d911c7e6136a7ac8a9" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "250", + "user": "0xac494D6eC2CcA7C9BD1caD0c1D0516F3706c6b7c", + "tranche_id": 6, + "tx": "0x85a5d2a4faa6490fc25e080f09dc4d9b5fb3857d762042ba2dcbc0f04de41e0c" + } + ], "total_tokens": "250", - "withdrawn_tokens": "0", - "remaining_tokens": "250" + "withdrawn_tokens": "250", + "remaining_tokens": "0" }, { "address": "0xa7137DA63B53138A6DCdC9D9a010F42F951F1113", @@ -98511,10 +98604,17 @@ "tx": "0x1c2c084e3efafb2ffa09c0b259bd229cce0d6da04dd092d911c7e6136a7ac8a9" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "250", + "user": "0xcAEbd70D80D5aB92Ae5A2E1c92F479298826548C", + "tranche_id": 6, + "tx": "0x7ffbc82e96bb7c796feb548a7ca48a7430a47dae3f2e9de859e6d45ac31a4e6c" + } + ], "total_tokens": "250", - "withdrawn_tokens": "0", - "remaining_tokens": "250" + "withdrawn_tokens": "250", + "remaining_tokens": "0" }, { "address": "0x64Aac7Cb63317DE77C331686E0b2dAA41303Adf0",