Compare commits

...
Author SHA1 Message Date
Edd cf6d6e70bc fix(explorer): cache more appropriately 2022-11-25 19:19:36 +00:00
Edd 9e2dc19426 fix(explorer): fix wss urls 2022-11-25 18:54:46 +00:00
Edd 344971d5a9 fix(explorer): remove old urls from default env 2022-11-25 16:57:08 +00:00
macqbatandMadalina Raicu de1f8b5895 chore(2170): console update ledger entries columns (#2221)
* chore: update ledger entries columns

* chore: update ledger entries columns - remove labels from sender and receiver

* chore: update ledger entries columns - remove labels from sender and receiver

* chore: update ledger entries columns - remove labels from sender and receiver

Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2022-11-25 17:17:21 +01:00
Joe Tsang 5b826f89d8 chore: tests passing (#2231) 2022-11-25 15:10:57 +00:00
Art 246c07f355 feat: view proposed market change (#2189) 2022-11-25 15:10:22 +00:00
macqbat 642bc8072b chore: fix removing closed positions (#2230) 2022-11-25 14:56:59 +00:00
m.ray de8e543bf4 fix(#2171): remove user's pubkey from LP query (#2188)
* fix(#2171): remove user's pubkey from LP query

* fix(#2171): add LP partyID in account events

* fix(#2171): add LP partyID in account events

* fix(#2200): handle NotFound GraphQL errors in async renderer

* fix(#2200): data provider filter apollo graphQL not found error

* fix(#2200): update apollo-client to not report not found error link

* fix(#2200): fix log on not found error link

* fix(#2200): fix set error in data provider

* fix(#2200): extensions type access via index signature

* fix: accounts-data-provider.spec.ts had missing partyId

* fix: revert not found error commit

* fix: revert and set error in data prov
2022-11-25 14:38:02 +00:00
m.ray 787a8ea1b3 fix: deal ticket set market price (#2228) 2022-11-25 08:39:14 -05:00
mattrussell36 d28ff4cfe7 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-25 12:07:00 +00:00
mattrussell36 71e1a116c7 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-25 06:06:10 +00:00
mattrussell36 f0fc737e58 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-25 00:10:25 +00:00
m.ray fe447167ca fix(#2200): handle NotFound GraphQL errors in async renderer (#2204)
* fix(#2200): handle NotFound GraphQL errors in async renderer

* fix(#2200): data provider filter apollo graphQL not found error

* fix(#2200): update apollo-client to not report not found error link

* fix(#2200): fix log on not found error link

* fix(#2200): fix set error in data provider

* fix(#2200): extensions type access via index signature

* fix(#2200): log gql errors that are not NotFound and still throw error in data provider

* fix: remove unused import
2022-11-24 15:52:46 -08:00
m.ray 02a8a8d9ec chore: update explorer stagnet3 links (#2227) 2022-11-24 15:48:39 -08:00
mattrussell36 f7bee22ba6 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-24 18:06:14 +00:00
mattrussell36 df6ae6e8fa chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-24 12:06:15 +00:00
mattrussell36 e25391a18c chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-24 06:05:59 +00:00
mattrussell36 c9b71af830 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-24 00:13:58 +00:00
Matthew Russell 9dfce9e723 fix(#2209): make asset dialog use asset id rather than symbol (#2217)
* fix: make asset dialog use asset id rather than symbol

* fix: tests that relied on asset symbol rather than id

* chore: add missing asset id to mocks

* chore: add asset id to mocks for e2e tests

* chore: add missing asset id for orders mock

* chore: fix console-lite build

* chore: add missing asset ids to mocks
2022-11-23 23:42:22 +00:00
mattrussell36 ad7f263811 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-23 18:07:39 +00:00
Edd 2afd182f03 fix(explorer): use getnodes to avoid nesting (#2198) 2022-11-23 14:47:53 +00:00
Dexter Edwards 6134ac9015 fix: withdrawals dialog broken (#2203) 2022-11-23 14:47:47 +00:00
Matthew Russell 0ccf564ee7 fix(#2137,#2197): correct price for estimate order query (#2159)
* fix: correct price for estimate order query

* chore: remove unnecessary optional chaining, accidental added test file

* chore: dont prevent orders for pending market state

* chore: estimate order query so that expiration is set as timestamp otherwise query fails

* chore: add test helper for market, fix tests and add type for order margin
2022-11-23 14:33:37 +00:00
Joe Tsang f212f5bb28 test(1872): add test for validator status (#2193)
* test: add test for validator status

* chore: fix lint
2022-11-23 14:16:51 +00:00
Edd 22c1a4ad6a fix: remove validatingnodes from all queries (#2199)
* fix: remove validatingnodes from all queries

* fix(explorer-e2e): remove assertion on validatingnodes
2022-11-23 13:36:18 +00:00
mattrussell36 0a0d74dcbd chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-23 12:08:45 +00:00
Edd 031cd9258e feat(explorer): add chain event details pages (#2194)
* feat(explorer): chain event views
2022-11-23 11:07:45 +00:00
mattrussell36 be39008b42 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-23 06:06:17 +00:00
mattrussell36 20b663a092 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-23 00:10:24 +00:00
m.rayandMatthew Russell 41646086e4 chore(#2179): update number formatters across frontend-monorepo (#2182)
* chore: update stagnet3 urls

* chore(#2179): remove normalized number formatter functions and update getNumberFormat

* fix(#2179): fix unit tests on all formatters

* fix(#2179): fix some cypress tests

* fix: fix  trading-accounts.cy.ts

* fix: update staking and wallet teardown tests

* chore: add e2e run-all command

* fix: wallet-eth test

* fix: fix tests in explorer and token

* fix: fix common.functions.js

* fix: fix common.functions.js in explorer

* fix(#2179): fix common.functions.js in explorer

* fix(#2179): fix common.functions.js in explorer

* fix(#2179): fix common.functions.js in explorer

Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2022-11-22 18:14:16 +00:00
Bartłomiej Głownia 7c0bed2f14 fix(#2153): improve positions table updates (#2187) 2022-11-22 19:03:09 +01:00
Ciaran McGhie ce62342d9a feat: add tooltips to headers on the LP dashboard and add some new data points (#2064)
* feat: add tooltips to headers on the details view

* feat: add header tooltips to liqudity dashboard markets page

* feat: add fee level and target stake to market summary list

These two data points are already in our health bar, but we want to call
them out more visibly so you don't have to hover to see them.

* feat: add % Target stake column to market list page

Adds a column which calculates what percentage of the target stake is
currently being supplied. We _trim_ this number to the whole percentage
value, so some precision may be lost, which we can add later if we want.

* chore: remove the estimated return/APY column while we dont use it

We can revert this commit later if we want it to return.

* feat: wrap the status pill with a tooltip

Uses the ui-toolkit tooltip to wrap the status pill, providing a bit
more information for what the statuses mean.

* chore: wrap getTooltipDescription in t() translate fn
2022-11-22 15:50:49 +00:00
mattrussell36 9aa672968f chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-22 12:07:15 +00:00
Art 4b7a513e98 feat: propose network parameter change link (578) (#2174)
* feat: propose network parameter change link (578)

* changeg stagnet3 url in trading e2e
2022-11-22 11:52:31 +01:00
Dexter Edwards 1aff7b1437 feat(2056): pending balances (#2185)
* chore: create store

* chore: migrate logic to use new store

* test: fix test typings
2022-11-22 10:13:39 +00:00
macqbat b749a05736 chore(2071): deal ticket data update fixing (#2169)
* chore: update of deal ticket data

* chore: update of deal ticket data

* chore: update of deal ticket data - fix re-render loop

* chore: update of deal ticket data - add marketDealTicketProvider

* chore: update of deal ticket data - add marketDealTicketProvider

* chore: update of deal ticket data - adjust console-lite to the changes

* chore: update of deal ticket data - fix failing unit tests

* chore: update of deal ticket data - fix failing unit tests

* chore: update of deal ticket data - fix linter failings

* chore: update of deal ticket data - adjust console-lite-e2e

* chore: update of deal ticket data - fix build-spec failings

* chore: update of deal ticket data - fix failing e2e tests

* chore: update of deal ticket data - fix failing e2e tests

* chore: update of deal ticket data - fix failing e2e tests

* chore: update of deal ticket data - remove unnecessary gqls

* chore: update of deal ticket data - remove unnecessary gqls

* chore: update of deal ticket data - remove unnecessary gqls

* chore: update of deal ticket data - fix failings build

* chore: update of deal ticket data - remove redundant data provider

* chore: update of deal ticket data - remove redundant data provider

* chore: update of deal ticket data - fix some types
2022-11-22 09:31:26 +01:00
mattrussell36 a5aed85b43 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-22 06:07:52 +00:00
mattrussell36 2c5a4e479b chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-22 00:12:01 +00:00
Matthew Russell d84612028e chore: update stagnet3 urls (#2180) 2022-11-21 15:55:07 -08:00
mattrussell36 fd8bf74cff chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-21 18:06:15 +00:00
263 changed files with 7851 additions and 3114 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -1,11 +1,12 @@
import { connectVegaWallet } from '../support/vega-wallet';
import { aliasQuery } from '@vegaprotocol/cypress';
import {
generateMarket,
generateMarketData,
generateMarketsCandles,
generateMarketsData,
generateSimpleMarkets,
} from '../support/mocks/generate-markets';
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
import { generateMarketTags } from '../support/mocks/generate-market-tags';
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
@@ -27,7 +28,8 @@ describe('market selector', { tags: '@smoke' }, () => {
aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
aliasQuery(req, 'MarketsData', generateMarketsData());
aliasQuery(req, 'DealTicket', generateDealTicket());
aliasQuery(req, 'MarketData', generateMarketData());
aliasQuery(req, 'Market', generateMarket());
aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
@@ -5,8 +5,8 @@ import {
generateMarketsCandles,
generateMarketsData,
generateMarket,
generateMarketData,
} from '../support/mocks/generate-markets';
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
import { generateMarketTags } from '../support/mocks/generate-market-tags';
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
@@ -28,7 +28,6 @@ describe('Market trade', { tags: '@smoke' }, () => {
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
aliasQuery(req, 'MarketsData', generateMarketsData());
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
aliasQuery(req, 'DealTicket', generateDealTicket());
aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
@@ -37,6 +36,7 @@ describe('Market trade', { tags: '@smoke' }, () => {
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
aliasQuery(req, 'MarketDepth', generateMarketDepth());
aliasQuery(req, 'Market', generateMarket());
aliasQuery(req, 'MarketData', generateMarketData());
});
cy.visit('/markets');
cy.wait('@Markets').then((response) => {
@@ -270,7 +270,10 @@ describe('Market trade', { tags: '@smoke' }, () => {
.find('dt')
.eq(3)
.should('have.text', 'Est. Fees (tDAI)');
cy.get('#step-2-panel').find('dd').eq(3).should('have.text', '3 (3.03%)');
cy.get('#step-2-panel')
.find('dd')
.eq(3)
.should('have.text', '3.00 (3.03%)');
}
});
@@ -292,7 +295,10 @@ describe('Market trade', { tags: '@smoke' }, () => {
cy.get('#step-3-panel').find('dd').eq(2).should('have.text', '98.93006');
cy.get('#step-3-panel').find('dd').eq(3).should('have.text', '3 (3.03%)');
cy.get('#step-3-panel')
.find('dd')
.eq(3)
.should('have.text', '3.00 (3.03%)');
cy.get('#step-3-panel').find('dd').eq(4).should('have.text', ' - ');
@@ -116,7 +116,12 @@ export const protoMarket: Market = {
product: {
__typename: 'Future',
quoteName: 'DAI',
settlementAsset: { symbol: 'tDAI', __typename: 'Asset', decimals: 5 },
settlementAsset: {
__typename: 'Asset',
id: 'asset-id',
symbol: 'tDAI',
decimals: 5,
},
},
__typename: 'Instrument',
},
@@ -144,4 +149,8 @@ export const singleMarket: SingleMarketFieldsFragment = {
},
},
},
depth: {
__typename: 'MarketDepth',
lastTrade: { price: '9893006', __typename: 'Trade' },
},
};
@@ -1,52 +0,0 @@
import type { DealTicketQuery } from '@vegaprotocol/deal-ticket';
import { Schema } from '@vegaprotocol/types';
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
export const generateDealTicket = (
override?: PartialDeep<DealTicketQuery>
): DealTicketQuery => {
const defaultResult: DealTicketQuery = {
market: {
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
decimalPlaces: 5,
positionDecimalPlaces: 0,
state: Schema.MarketState.STATE_ACTIVE,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
tradableInstrument: {
instrument: {
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
name: 'AAVEDAI Monthly (30 Jun 2022)',
product: {
quoteName: 'DAI',
settlementAsset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'Future',
},
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
depth: {
lastTrade: { price: '9893006', __typename: 'Trade' },
__typename: 'MarketDepth',
},
fees: {
factors: {
makerFee: '0.0002',
infrastructureFee: '0.0005',
liquidityFee: '0.001',
__typename: 'FeeFactors',
},
__typename: 'Fees',
},
__typename: 'Market',
},
};
return merge(defaultResult, override);
};
@@ -11,6 +11,7 @@ import type {
import { protoMarket, protoCandles, singleMarket } from './commons';
import type { PartialDeep } from 'type-fest';
import type { MarketQuery } from '@vegaprotocol/market-list';
import type { MarketDataQuery } from '@vegaprotocol/market-list';
export const generateSimpleMarkets = (): MarketsQuery => {
const markets: Market[] = [
@@ -38,8 +39,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'XYZalpha',
__typename: 'Asset',
id: 'asset-XYZalpha',
symbol: 'XYZalpha',
decimals: 5,
},
},
@@ -72,8 +74,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'XYZbeta',
__typename: 'Asset',
id: 'asset-XYZbeta',
symbol: 'XYZbeta',
decimals: 5,
},
},
@@ -107,8 +110,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'DAI',
settlementAsset: {
symbol: 'tDAI',
__typename: 'Asset',
id: 'asset-tDAI',
symbol: 'tDAI',
decimals: 5,
},
},
@@ -141,8 +145,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'XYZbeta',
__typename: 'Asset',
id: 'asset-XYZbeta',
symbol: 'XYZbeta',
decimals: 5,
},
},
@@ -174,8 +179,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'tUSDC',
__typename: 'Asset',
id: 'asset-tUSDC',
symbol: 'tUSDC',
decimals: 5,
},
},
@@ -209,8 +215,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'tBTC',
__typename: 'Asset',
id: 'asset-tBTC',
symbol: 'tBTC',
decimals: 5,
},
},
@@ -243,8 +250,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'XYZgamma',
__typename: 'Asset',
id: 'asset-XYZgamma',
symbol: 'XYZgamma',
decimals: 5,
},
},
@@ -278,8 +286,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'tBTC',
__typename: 'Asset',
id: 'asset-tBTC',
symbol: 'tBTC',
decimals: 5,
},
},
@@ -313,8 +322,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'BTC',
settlementAsset: {
symbol: 'tBTC',
__typename: 'Asset',
id: 'asset-tBTC',
symbol: 'tBTC',
decimals: 5,
},
},
@@ -349,8 +359,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'tUSDC',
__typename: 'Asset',
id: 'asset-tUSDC',
symbol: 'tUSDC',
decimals: 5,
},
},
@@ -385,8 +396,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'EURO',
settlementAsset: {
symbol: 'tEURO',
__typename: 'Asset',
id: 'asset-tEURO',
symbol: 'tEURO',
decimals: 5,
},
},
@@ -419,8 +431,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'XYZgamma',
__typename: 'Asset',
id: 'asset-XYZgamma',
symbol: 'XYZgamma',
decimals: 5,
},
},
@@ -454,8 +467,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'tBTC',
__typename: 'Asset',
id: 'asset-tBTC',
symbol: 'tBTC',
decimals: 5,
},
},
@@ -489,8 +503,9 @@ export const generateSimpleMarkets = (): MarketsQuery => {
__typename: 'Future',
quoteName: 'USD',
settlementAsset: {
symbol: 'tBTC',
__typename: 'Asset',
id: 'asset-tBTC',
symbol: 'tBTC',
decimals: 5,
},
},
@@ -1139,52 +1154,51 @@ export const generateFillsMarkets = () => {
};
};
const markets = [
{
data: {
market: {
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
__typename: 'Market',
},
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
staticMidPrice: '0',
indicativePrice: '0',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '0',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '17588787',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
__typename: 'MarketData',
},
__typename: 'Market',
},
{
data: {
market: {
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
__typename: 'Market',
},
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
staticMidPrice: '0',
indicativePrice: '0',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '0',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '84377569',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
__typename: 'MarketData',
},
__typename: 'Market',
},
];
export const generateMarketsData = (
override?: PartialDeep<MarketsDataQuery>
): MarketsDataQuery => {
const markets = [
{
data: {
market: {
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
__typename: 'Market',
},
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
staticMidPrice: '0',
indicativePrice: '0',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '0',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '17588787',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
__typename: 'MarketData',
},
__typename: 'Market',
},
{
data: {
market: {
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
__typename: 'Market',
},
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
staticMidPrice: '0',
indicativePrice: '0',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '0',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '84377569',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
__typename: 'MarketData',
},
__typename: 'Market',
},
];
const defaultResult: MarketsDataQuery = {
marketsConnection: {
__typename: 'MarketConnection',
@@ -1240,9 +1254,10 @@ export const generatePositionsMarkets = () => {
},
product: {
settlementAsset: {
__typename: 'Asset',
id: 'asset-tDAI',
symbol: 'tDAI',
decimals: 5,
__typename: 'Asset',
},
quoteName: 'DAI',
__typename: 'Future',
@@ -1294,9 +1309,10 @@ export const generatePositionsMarkets = () => {
},
product: {
settlementAsset: {
__typename: 'Asset',
id: 'asset-tDAI',
symbol: 'tDAI',
decimals: 5,
__typename: 'Asset',
},
quoteName: 'DAI',
__typename: 'Future',
@@ -1349,9 +1365,10 @@ export const generatePositionsMarkets = () => {
},
product: {
settlementAsset: {
__typename: 'Asset',
id: 'asset-tEURO',
symbol: 'tEURO',
decimals: 5,
__typename: 'Asset',
},
quoteName: 'EURO',
__typename: 'Future',
@@ -1382,3 +1399,34 @@ export const generateMarket = (): MarketQuery => {
},
};
};
export const generateMarketData = (): MarketDataQuery => {
return {
marketsConnection: {
edges: [
{
node: {
data: {
market: {
id: protoMarket.id,
__typename: 'Market',
},
marketTradingMode:
Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
staticMidPrice: '0',
indicativePrice: '0',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '0',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '17588787',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
__typename: 'MarketData',
},
},
},
],
},
};
};
@@ -17,7 +17,7 @@ export const generatePartyBalance = (
balance: '88474051',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
id: 'dai-id',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
@@ -47,7 +47,7 @@ export const generatePartyBalance = (
balance: '3412867',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
id: 'dai-id',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
@@ -62,7 +62,7 @@ export const generatePartyBalance = (
balance: '70007',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
id: 'dai-id',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
+1 -1
View File
@@ -19,7 +19,7 @@ NX_DEPLOY_URL=$DEPLOY_URL
NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
NX_VEGA_CONFIG_URL="https://static.vega.xyz/assets/stagnet3-network.json"
NX_VEGA_ENV=STAGNET3
NX_VEGA_URL="https://api.n01.stagnet3.vega.xyz/graphql"
NX_VEGA_URL="https://api.stagnet3.vega.xyz/graphql"
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -1,20 +1,17 @@
import React from 'react';
import { render } from '@testing-library/react';
import type {
AccountFragment,
DealTicketMarketFragment,
} from '@vegaprotocol/deal-ticket';
import type { AccountFragment } from '@vegaprotocol/deal-ticket';
import { DealTicketBalance } from './deal-ticket-balance';
import { Schema } from '@vegaprotocol/types';
import type { MarketDealTicketAsset } from '@vegaprotocol/market-list';
const tDAI: DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'] =
{
__typename: 'Asset',
id: '1',
symbol: 'tDAI',
name: 'TDAI',
decimals: 2,
};
const tDAI: MarketDealTicketAsset = {
__typename: 'Asset',
id: '1',
symbol: 'tDAI',
name: 'TDAI',
decimals: 2,
};
const accounts: AccountFragment[] = [
{
@@ -1,14 +1,12 @@
import classNames from 'classnames';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import { Schema } from '@vegaprotocol/types';
import type {
AccountFragment,
DealTicketMarketFragment,
} from '@vegaprotocol/deal-ticket';
import type { AccountFragment } from '@vegaprotocol/deal-ticket';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { useSettlementAccount } from '@vegaprotocol/deal-ticket';
interface DealTicketBalanceProps {
settlementAsset: DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'];
settlementAsset: MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
accounts: AccountFragment[];
isWalletConnected: boolean;
className?: string;
@@ -2,16 +2,21 @@ import { useParams } from 'react-router-dom';
import compact from 'lodash/compact';
import {
DealTicketManager,
DealTicketContainer as Container,
usePartyBalanceQuery,
} from '@vegaprotocol/deal-ticket';
import { Loader } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers';
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { DealTicketSteps } from './deal-ticket-steps';
import { DealTicketBalance } from './deal-ticket-balance';
import Baubles from './baubles-decor';
import ConnectWallet from '../wallet-connector';
import { useMemo } from 'react';
import type {
MarketDataUpdateFieldsFragment,
MarketDealTicket,
} from '@vegaprotocol/market-list';
import { marketDealTicketProvider } from '@vegaprotocol/market-list';
const tempEmptyText = (
<p>{t('Please select a market from the markets page')}</p>
@@ -21,52 +26,64 @@ export const DealTicketContainer = () => {
const { marketId } = useParams<{ marketId: string }>();
const { pubKey } = useVegaWallet();
const { data: partyData, loading } = usePartyBalanceQuery({
const { data: partyData } = usePartyBalanceQuery({
variables: { partyId: pubKey || '' },
skip: !pubKey,
});
const variables = useMemo(
() => ({
marketId: marketId || '',
}),
[marketId]
);
const { data, loading } = useDataProvider<
MarketDealTicket,
MarketDataUpdateFieldsFragment
>({
dataProvider: marketDealTicketProvider,
variables,
skip: !marketId,
});
const accounts = compact(partyData?.party?.accountsConnection?.edges).map(
(e) => e.node
);
const loader = <Loader />;
const container = marketId ? (
<Container marketId={marketId}>
{(data) => {
if (!data.market) {
return null as unknown as JSX.Element;
if (marketId && data) {
const balance = (
<DealTicketBalance
className="mb-4"
settlementAsset={
data.tradableInstrument.instrument.product?.settlementAsset
}
accounts={accounts || []}
isWalletConnected={!!pubKey}
/>
);
const accounts = compact(
partyData?.party?.accountsConnection?.edges
).map((e) => e.node);
const balance = (
<DealTicketBalance
className="mb-4"
settlementAsset={
data.market.tradableInstrument.instrument.product?.settlementAsset
}
accounts={accounts || []}
isWalletConnected={!!pubKey}
/>
);
const container = (
<DealTicketManager market={data}>
{loading ? loader : balance}
<DealTicketSteps market={data} />
</DealTicketManager>
);
return (
<DealTicketManager market={data.market}>
{loading ? loader : balance}
<DealTicketSteps market={data.market} />
</DealTicketManager>
);
}}
</Container>
return (
<section className="flex p-4 md:p-6">
<section className="w-full md:w-1/2 md:min-w-[500px]">
{pubKey ? container : <ConnectWallet />}
</section>
<Baubles />
</section>
);
}
return marketId ? (
<Splash>
<p>{t('Could not load market')}</p>
</Splash>
) : (
tempEmptyText
);
return (
<section className="flex p-4 md:p-6">
<section className="w-full md:w-1/2 md:min-w-[500px]">
{pubKey ? container : <ConnectWallet />}
</section>
<Baubles />
</section>
);
};
@@ -3,7 +3,6 @@ import { useNavigate } from 'react-router-dom';
import { useForm, Controller } from 'react-hook-form';
import compact from 'lodash/compact';
import { Stepper } from '../stepper';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import {
getDefaultOrder,
useOrderCloseOut,
@@ -24,7 +23,6 @@ import {
toDecimal,
removeDecimal,
addDecimalsFormatNumber,
addDecimalsNormalizeNumber,
addDecimal,
formatNumber,
} from '@vegaprotocol/react-helpers';
@@ -42,9 +40,10 @@ import ReviewTrade from './review-trade';
import { Schema } from '@vegaprotocol/types';
import { DealTicketSlippage } from './deal-ticket-slippage';
import { useOrderValidation } from './use-order-validation';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
interface DealTicketMarketProps {
market: DealTicketMarketFragment;
market: MarketDealTicket;
}
export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
@@ -71,17 +70,10 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
const step = toDecimal(market.positionDecimalPlaces);
const order = watch();
const { pubKey } = useVegaWallet();
const estMargin = useOrderMargin({
order,
market,
partyId: pubKey || '',
});
const { message: invalidText, isDisabled } = useOrderValidation({
market,
orderType: order.type,
orderTimeInForce: order.timeInForce,
order,
fieldErrors: errors,
estMargin,
});
const { submit, transaction, finalizedOrder, Dialog } = useOrderSubmit();
@@ -130,11 +122,18 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
);
return new BigNumber(market?.depth?.lastTrade?.price)
.multipliedBy(multiplier)
.toNumber();
.toString();
}
return null;
return undefined;
}, [market?.depth?.lastTrade?.price, order.side, slippage]);
const estMargin = useOrderMargin({
order,
market,
partyId: pubKey || '',
derivedPrice: price,
});
const formattedPrice =
price && addDecimalsFormatNumber(price, market.decimalPlaces);
@@ -158,7 +157,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
.decimalPlaces(2)
.toString();
return `${addDecimalsNormalizeNumber(
return `${addDecimalsFormatNumber(
estMargin.totalFees,
assetDecimals
)} (${formatNumber(addDecimal(percentage, assetDecimals), 2)}%)`;
@@ -5,17 +5,17 @@ import {
KeyValueTableRow,
} from '@vegaprotocol/ui-toolkit';
import classNames from 'classnames';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import { DealTicketEstimates } from '@vegaprotocol/deal-ticket';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { SIDE_NAMES } from './side-selector';
import { gql, useQuery } from '@apollo/client';
import { Schema } from '@vegaprotocol/types';
import { MarketExpires } from '@vegaprotocol/market-info';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import type {
MarketTags,
MarketTagsVariables,
} from './__generated__/MarketTags';
import { Schema } from '@vegaprotocol/types';
import { MarketExpires } from '@vegaprotocol/market-info';
export const MARKET_TAGS_QUERY = gql`
query MarketTags($marketId: ID!) {
@@ -32,7 +32,7 @@ export const MARKET_TAGS_QUERY = gql`
`;
interface Props {
market: DealTicketMarketFragment;
market: MarketDealTicket;
isDisabled: boolean;
transactionStatus?: string;
order: OrderSubmissionBody['orderSubmission'];
@@ -3,12 +3,15 @@ import { renderHook } from '@testing-library/react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { MockedProvider } from '@apollo/client/testing';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { MarketStateMapping, Schema } from '@vegaprotocol/types';
import {
MarketStateMapping,
Schema as Types,
Schema,
} from '@vegaprotocol/types';
import type { ValidationProps } from './use-order-validation';
import { marketTranslations, useOrderValidation } from './use-order-validation';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import * as DealTicket from '@vegaprotocol/deal-ticket';
import BigNumber from 'bignumber.js';
jest.mock('@vegaprotocol/wallet');
jest.mock('@vegaprotocol/deal-ticket', () => {
@@ -19,7 +22,7 @@ jest.mock('@vegaprotocol/deal-ticket', () => {
});
type SettlementAsset =
DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'];
MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
const asset: SettlementAsset = {
__typename: 'Asset',
id: 'asset-id',
@@ -28,7 +31,7 @@ const asset: SettlementAsset = {
decimals: 2,
};
const market: DealTicketMarketFragment = {
const market: MarketDealTicket = {
id: 'market-id',
decimalPlaces: 2,
positionDecimalPlaces: 1,
@@ -40,10 +43,17 @@ const market: DealTicketMarketFragment = {
__typename: 'Instrument',
id: 'instrument-id',
name: 'instrument-name',
code: 'instriment-code',
metadata: {
tags: [],
},
product: {
__typename: 'Future',
quoteName: 'quote-name',
settlementAsset: asset,
dataSourceSpecForTradingTermination: {
id: 'dataSource-id',
},
},
},
},
@@ -63,6 +73,25 @@ const market: DealTicketMarketFragment = {
liquidityFee: '3',
},
},
data: {
__typename: 'MarketData',
bestBidPrice: '1605489971',
bestOfferPrice: '1606823730',
markPrice: '1606823730',
trigger: Types.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
staticMidPrice: '1606156850',
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
indicativeVolume: '0',
indicativePrice: '0',
bestStaticBidPrice: '1605489971',
bestStaticOfferPrice: '1606823730',
targetStake: '8561302732',
suppliedStake: '727654170336',
auctionStart: null,
auctionEnd: null,
market: { __typename: 'Market', id: 'market-id' },
},
marketTimestamps: {},
};
const defaultWalletContext = {
@@ -75,19 +104,19 @@ const defaultWalletContext = {
connector: null,
};
const order = {
type: Schema.OrderType.TYPE_MARKET,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
marketId: 'market-id',
side: Schema.Side.SIDE_BUY,
size: '0.1',
};
const defaultOrder = {
market,
market: { ...market },
step: 0.1,
orderType: Schema.OrderType.TYPE_MARKET,
orderTimeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
estMargin: {
margin: '0,000001',
totalFees: '0,000006',
fees: {
makerFee: '0,000003',
liquidityFee: '0,000002',
infrastructureFee: '0,000001',
},
order: {
...order,
},
};
@@ -127,9 +156,9 @@ describe('useOrderValidation', () => {
it('Returns empty string when given valid data', () => {
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
balance: new BigNumber(0),
margin: new BigNumber(100),
asset,
balance: '0',
margin: '100',
balanceError: false,
});
const { result } = setup();
@@ -142,9 +171,9 @@ describe('useOrderValidation', () => {
it('Returns an error message when no keypair found', () => {
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
balance: new BigNumber(0),
margin: new BigNumber(100),
asset,
balance: '0',
margin: '100',
balanceError: false,
});
const { result } = setup(defaultOrder, { pubKey: null });
expect(result.current).toStrictEqual({
@@ -183,9 +212,10 @@ describe('useOrderValidation', () => {
'Returns an error message for market state suspended or pending',
({ state }) => {
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
balance: new BigNumber(0),
margin: new BigNumber(100),
asset,
balance: '0',
margin: '100',
balanceError: false,
// asset,
});
const { result } = setup({
market: {
@@ -193,8 +223,11 @@ describe('useOrderValidation', () => {
state,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
},
orderType: Schema.OrderType.TYPE_LIMIT,
orderTimeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
order: {
...order,
type: Schema.OrderType.TYPE_LIMIT,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
},
});
expect(result.current).toStrictEqual({
isDisabled: false,
@@ -216,7 +249,10 @@ describe('useOrderValidation', () => {
({ tradingMode, errorMessage }) => {
const { result } = setup({
market: { ...defaultOrder.market, tradingMode },
orderType: Schema.OrderType.TYPE_MARKET,
order: {
...order,
type: Schema.OrderType.TYPE_MARKET,
},
});
expect(result.current.isDisabled).toBeTruthy();
expect(result.current.message).toBe(errorMessage);
@@ -239,8 +275,11 @@ describe('useOrderValidation', () => {
({ tradingMode, orderTimeInForce, errorMessage }) => {
const { result } = setup({
market: { ...defaultOrder.market, tradingMode },
orderType: Schema.OrderType.TYPE_LIMIT,
orderTimeInForce,
order: {
...order,
type: Schema.OrderType.TYPE_LIMIT,
timeInForce: orderTimeInForce,
},
});
expect(result.current).toStrictEqual({
isDisabled: true,
@@ -261,7 +300,10 @@ describe('useOrderValidation', () => {
({ fieldName, errorType, section, errorMessage }) => {
const { result } = setup({
fieldErrors: { [fieldName]: { type: errorType } },
orderType: Schema.OrderType.TYPE_LIMIT,
order: {
...order,
type: Schema.OrderType.TYPE_LIMIT,
},
});
expect(result.current).toStrictEqual({
isDisabled: true,
@@ -300,9 +342,9 @@ describe('useOrderValidation', () => {
it('Returns an error message when the estimated margin is higher than collateral', async () => {
const invalidatedMockValue = {
balance: new BigNumber(100),
margin: new BigNumber(200),
asset,
balance: '100',
margin: '200',
balanceError: true,
};
jest
@@ -315,9 +357,9 @@ describe('useOrderValidation', () => {
const testElement = (
<DealTicket.MarginWarning
margin={invalidatedMockValue.margin.toString()}
balance={invalidatedMockValue.balance.toString()}
asset={invalidatedMockValue.asset}
margin={invalidatedMockValue.margin}
balance={invalidatedMockValue.balance}
asset={asset}
/>
);
expect((result.current.message as React.ReactElement)?.props).toEqual(
@@ -6,10 +6,6 @@ import { useVegaWallet } from '@vegaprotocol/wallet';
import { MarketStateMapping, Schema } from '@vegaprotocol/types';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import type {
DealTicketMarketFragment,
OrderMargin,
} from '@vegaprotocol/deal-ticket';
import {
MarketDataGrid,
compileGridData,
@@ -18,6 +14,7 @@ import {
ERROR_SIZE_DECIMAL,
useOrderMarginValidation,
} from '@vegaprotocol/deal-ticket';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
export const DEAL_TICKET_SECTION = {
TYPE: 'sec-type',
@@ -32,11 +29,9 @@ export const ERROR_EXPIRATION_IN_THE_PAST = 'ERROR_EXPIRATION_IN_THE_PAST';
export type ValidationProps = {
step?: number;
market: DealTicketMarketFragment;
orderType: Schema.OrderType;
orderTimeInForce: Schema.OrderTimeInForce;
market: MarketDealTicket;
order: OrderSubmissionBody['orderSubmission'];
fieldErrors?: FieldErrors<OrderSubmissionBody['orderSubmission']>;
estMargin: OrderMargin | null;
};
export const marketTranslations = (marketState: Schema.MarketState) => {
@@ -55,9 +50,7 @@ export type DealTicketSection =
export const useOrderValidation = ({
market,
fieldErrors,
orderType,
orderTimeInForce,
estMargin,
order,
}: ValidationProps): {
message: ReactNode | string;
isDisabled: boolean;
@@ -65,7 +58,7 @@ export const useOrderValidation = ({
} => {
const { pubKey } = useVegaWallet();
const minSize = toDecimal(market.positionDecimalPlaces);
const isInvalidOrderMargin = useOrderMarginValidation({ market, estMargin });
const isInvalidOrderMargin = useOrderMarginValidation({ market, order });
const fieldErrorChecking = useMemo<{
message: ReactNode | string;
@@ -91,7 +84,7 @@ export const useOrderValidation = ({
if (
fieldErrors?.price?.type === 'required' &&
orderType !== Schema.OrderType.TYPE_MARKET
order.type !== Schema.OrderType.TYPE_MARKET
) {
return {
isDisabled: true,
@@ -102,7 +95,7 @@ export const useOrderValidation = ({
if (
fieldErrors?.price?.type === 'min' &&
orderType !== Schema.OrderType.TYPE_MARKET
order.type !== Schema.OrderType.TYPE_MARKET
) {
return {
isDisabled: true,
@@ -151,7 +144,7 @@ export const useOrderValidation = ({
fieldErrors?.price?.type,
fieldErrors?.expiresAt?.type,
fieldErrors?.expiresAt?.message,
orderType,
order.type,
minSize,
market.positionDecimalPlaces,
]);
@@ -210,7 +203,7 @@ export const useOrderValidation = ({
}
if (isMarketInAuction(market)) {
if (orderType === Schema.OrderType.TYPE_MARKET) {
if (order.type === Schema.OrderType.TYPE_MARKET) {
if (
market.tradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
@@ -269,12 +262,12 @@ export const useOrderValidation = ({
};
}
if (
orderType === Schema.OrderType.TYPE_LIMIT &&
order.type === Schema.OrderType.TYPE_LIMIT &&
[
Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
Schema.OrderTimeInForce.TIME_IN_FORCE_GFN,
].includes(orderTimeInForce)
].includes(order.timeInForce)
) {
if (
market.tradingMode ===
@@ -343,17 +336,14 @@ export const useOrderValidation = ({
return fieldErrorChecking;
}
if (
isInvalidOrderMargin.balance.isGreaterThan(0) &&
isInvalidOrderMargin.balance.isLessThan(isInvalidOrderMargin.margin)
) {
if (isInvalidOrderMargin.balanceError) {
return {
isDisabled: false,
message: (
<MarginWarning
margin={isInvalidOrderMargin.margin.toString()}
balance={isInvalidOrderMargin.balance.toString()}
asset={isInvalidOrderMargin.asset}
margin={isInvalidOrderMargin.margin}
balance={isInvalidOrderMargin.balance}
asset={market.tradableInstrument.instrument.product.settlementAsset}
/>
),
section: DEAL_TICKET_SECTION.PRICE,
@@ -386,8 +376,8 @@ export const useOrderValidation = ({
market,
fieldErrorChecking,
isInvalidOrderMargin,
orderType,
orderTimeInForce,
order.type,
order.timeInForce,
]);
return { message, isDisabled, section };
@@ -16,7 +16,7 @@ import { useAccountColumnDefinitions } from '.';
const AccountsManager = () => {
const { partyId = '' } = useOutletContext<{ partyId: string }>();
const { isOpen, symbol, setOpen } = useAssetDetailsDialogStore();
const { isOpen, id, setOpen } = useAssetDetailsDialogStore();
const gridRef = useRef<AgGridReact | null>(null);
const dataRef = useRef<AccountFields[] | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
@@ -66,7 +66,7 @@ const AccountsManager = () => {
/>
</AsyncRenderer>
<AssetDetailsDialog
assetSymbol={symbol}
assetId={id}
open={isOpen}
onChange={(open) => setOpen(open)}
/>
@@ -15,14 +15,14 @@ const useAccountColumnDefinitions = () => {
field: 'asset.symbol',
headerClass: 'uppercase justify-start',
cellClass: 'uppercase flex h-full items-center md:pl-4',
cellRenderer: ({ value }: GroupCellRendererParams) =>
cellRenderer: ({ value, data }: GroupCellRendererParams) =>
value && value.length > 0 ? (
<div className="md:pl-4 grid h-full items-center" title={value}>
<div className="truncate min-w-0">
<button
className="hover:underline"
onClick={() => {
open(value);
open(data.asset.id);
}}
>
{value}
+3 -3
View File
@@ -1,8 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n01.stagnet3.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n01.stagnet3.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
# App flags
+25 -27
View File
@@ -18,22 +18,21 @@ context('Home Page', function () {
const statTitles = {
0: 'Status',
1: 'Height',
2: 'Validating nodes',
3: 'Uptime',
4: 'Total nodes',
5: 'Inactive nodes',
6: 'Total staked',
7: 'Backlog',
8: 'Trades / second',
9: 'Orders / block',
10: 'Orders / second',
11: 'Transactions / block',
12: 'Block time',
13: 'Time',
14: 'App',
15: 'Tendermint',
16: 'Up since',
17: 'Chain ID',
2: 'Uptime',
3: 'Total nodes',
4: 'Inactive nodes',
5: 'Total staked',
6: 'Backlog',
7: 'Trades / second',
8: 'Orders / block',
9: 'Orders / second',
10: 'Transactions / block',
11: 'Block time',
12: 'Time',
13: 'App',
14: 'Tendermint',
15: 'Up since',
16: 'Chain ID',
};
cy.get('[data-testid="stats-title"]')
@@ -41,41 +40,40 @@ context('Home Page', function () {
cy.wrap($list).should('have.text', statTitles[index]);
})
.then(($list) => {
cy.wrap($list).should('have.length', 18);
cy.wrap($list).should('have.length', 17);
});
cy.get(statsValue).eq(0).should('have.text', 'CONNECTED');
cy.get(statsValue).eq(1).should('not.be.empty');
cy.get(statsValue).eq(2).should('have.text', '2');
cy.get(statsValue)
.eq(3)
.eq(2)
.invoke('text')
.should('match', /\d+d \d+h \d+m \d+s/i);
cy.get(statsValue).eq(4).should('have.text', '2');
cy.get(statsValue).eq(5).should('have.text', '0');
cy.get(statsValue).eq(3).should('have.text', '2');
cy.get(statsValue).eq(4).should('have.text', '0');
cy.get(statsValue)
.eq(6)
.eq(5)
.invoke('text')
.should('match', /\d+\.\d\d(?!\d)/i);
cy.get(statsValue).eq(6).should('have.text', '0');
cy.get(statsValue).eq(7).should('have.text', '0');
cy.get(statsValue).eq(8).should('have.text', '0');
cy.get(statsValue).eq(9).should('have.text', '0');
cy.get(statsValue).eq(10).should('have.text', '0');
cy.get(statsValue).eq(10).should('not.be.empty');
cy.get(statsValue).eq(11).should('not.be.empty');
cy.get(statsValue).eq(12).should('not.be.empty');
cy.get(statsValue).eq(13).should('not.be.empty');
if (Cypress.env('NIGHTLY_RUN') != true) {
cy.get(statsValue)
.eq(14)
.eq(13)
.invoke('text')
.should('match', /v\d+\.\d+\.\d+/i);
}
cy.get(statsValue)
.eq(15)
.eq(14)
.invoke('text')
.should('match', /\d+\.\d+\.\d+/i);
cy.get(statsValue).eq(15).should('not.be.empty');
cy.get(statsValue).eq(16).should('not.be.empty');
cy.get(statsValue).eq(17).should('not.be.empty');
});
it('Block height should be updating', function () {
@@ -148,7 +148,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
const parameterName = network_parameter[0];
const parameterValue = network_parameter[1];
if (this.networkParameterFormat.fiveDecimal.includes(parameterName)) {
cy.convert_number_to_four_decimal(parameterValue)
cy.convert_number_to_max_four_decimal(parameterValue)
.add_commas_to_number_if_large_enough()
.then((parameterValueFormatted) => {
cy.get(tableRows)
@@ -179,7 +179,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
if (
this.networkParameterFormat.eighteenDecimal.includes(parameterName)
) {
cy.convert_number_to_eighteen_decimal(parameterValue)
cy.convert_number_to_max_eighteen_decimal(parameterValue)
.add_commas_to_number_if_large_enough()
.then((parameterValueFormatted) => {
cy.get(tableRows)
@@ -212,7 +212,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
const jsonFields = '.hljs';
const sideMenuBackground = '.absolute';
// Engage dark mode if not allready set
// Engage dark mode if not already set
cy.get(sideMenuBackground)
.should('have.css', 'background-color')
.then((background_color) => {
@@ -68,12 +68,19 @@ Cypress.Commands.add(
}
);
Cypress.Commands.add('convert_number_to_eighteen_decimal', (number) => {
// this will take a number like this : 700000000000000000000
// and convert it to a number like this: 700.000000000000000000
return BigNumber((number / 1000000000000000000).toString()).toFixed(18);
Cypress.Commands.add('convert_number_to_max_eighteen_decimal', (number) => {
// this will take a number like this : 700000000000000000001
// and convert it to a number like this: 700.000000000000000001
const value = BigNumber(number / 1000000000000000000).toString();
return parseFloat(value).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 18,
});
});
Cypress.Commands.add('convert_number_to_four_decimal', (number) => {
return parseFloat(number).toFixed(4);
Cypress.Commands.add('convert_number_to_max_four_decimal', (number) => {
return parseFloat(number).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 4,
});
});
+5 -3
View File
@@ -1,12 +1,14 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n01.stagnet3.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n01.stagnet3.vega.xyz/tm/websocket
NX_TENDERMINT_URL=https://tm.be.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_BLOCK_EXPLORER=
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
# App flags
NX_EXPLORER_ASSETS=1
+1
View File
@@ -5,6 +5,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=CUSTOM
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
# App flags
NX_EXPLORER_ASSETS=1
+1
View File
@@ -7,3 +7,4 @@ NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https:
NX_VEGA_ENV=DEVNET
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+2 -1
View File
@@ -1,9 +1,10 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://be.explorer.vega.xyz
NX_TENDERMINT_URL=https://be.explorer.vega.xyz/websocket
NX_TENDERMINT_WEBSOCKET_URL=wss://be.explorer.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=MAINNET
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest/
NX_ETHERSCAN_URL=https://etherscan.io
+1
View File
@@ -8,3 +8,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_TENDERMINT_URL=https://tm.n01.sandbox.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.sandbox.vega.xyz/websocket
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+3 -2
View File
@@ -7,6 +7,7 @@ NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_TENDERMINT_URL=https://tm.be.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+3 -4
View File
@@ -1,9 +1,8 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n01.stagnet3.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n01.stagnet3.vega.xyz/tm/websocket
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_BLOCK_EXPLORER=https://blockexplorer.n01.stagnet3.vega.xyz/rest
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
+3 -2
View File
@@ -1,12 +1,13 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.testnet.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.be.testnet.vega.xyz/
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_VEGA_ENV=TESTNET
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_NETWORKS={}
NX_VEGA_NETWORKS={}
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+1
View File
@@ -5,3 +5,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
NX_VEGA_ENV=CUSTOM
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_BLOCK_EXPLORER=
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+8
View File
@@ -66,6 +66,14 @@
"passWithNoTests": true
}
},
"generate-types": {
"executor": "@nrwl/workspace:run-commands",
"options": {
"commands": [
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.62.1/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
]
}
},
"build-netlify": {
"executor": "@nrwl/workspace:run-commands",
"options": {
@@ -26,7 +26,7 @@ const AssetLink = ({ id, ...props }: AssetLinkProps) => {
}
return (
<Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
<Link className="underline" {...props} to={`/${Routes.ASSETS}#${id}`}>
{label}
</Link>
);
@@ -0,0 +1,33 @@
import React from 'react';
import { DATA_SOURCES } from '../../../config';
export enum EthExplorerLinkTypes {
block = 'block',
address = 'address',
tx = 'tx',
}
export type EthExplorerLinkProps = Partial<typeof HTMLAnchorElement> & {
id: string;
type: EthExplorerLinkTypes;
};
export const EthExplorerLink = ({
id,
type,
...props
}: EthExplorerLinkProps) => {
const link = `${DATA_SOURCES.ethExplorerUrl}/${type}/${id}`;
return (
<a
className="underline external"
target="_blank"
rel="noopener noreferrer"
{...props}
href={link}
>
{id}
</a>
);
};
@@ -19,7 +19,7 @@ const MarketLink = ({ id, ...props }: MarketLinkProps) => {
variables: { id },
});
let label: string = id;
let label = id;
if (data?.market?.tradableInstrument.instrument.name) {
label = data.market.tradableInstrument.instrument.name;
@@ -0,0 +1,14 @@
import { t } from '@vegaprotocol/react-helpers';
interface TimeProps {
date: string | null | undefined;
}
export const Time = ({ date }: TimeProps) => {
if (!date) {
return <>{t('Date unknown')}</>;
}
const timeFormatted = new Date(date).toLocaleString();
return <span>{timeFormatted}</span>;
};
@@ -0,0 +1,75 @@
import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ExplorerNodeVoteQueryVariables = Types.Exact<{
id: Types.Scalars['ID'];
}>;
export type ExplorerNodeVoteQuery = { __typename?: 'Query', withdrawal?: { __typename?: 'Withdrawal', id: string, status: Types.WithdrawalStatus, createdTimestamp: string, withdrawnTimestamp?: string | null, txHash?: string | null, asset: { __typename?: 'Asset', id: string, name: string, decimals: number }, party: { __typename?: 'Party', id: string } } | null, deposit?: { __typename?: 'Deposit', id: string, status: Types.DepositStatus, createdTimestamp: string, creditedTimestamp?: string | null, txHash?: string | null, asset: { __typename?: 'Asset', id: string, name: string, decimals: number }, party: { __typename?: 'Party', id: string } } | null };
export const ExplorerNodeVoteDocument = gql`
query ExplorerNodeVote($id: ID!) {
withdrawal(id: $id) {
id
status
createdTimestamp
withdrawnTimestamp
txHash
asset {
id
name
decimals
}
party {
id
}
}
deposit(id: $id) {
id
status
createdTimestamp
creditedTimestamp
txHash
asset {
id
name
decimals
}
party {
id
}
}
}
`;
/**
* __useExplorerNodeVoteQuery__
*
* To run a query within a React component, call `useExplorerNodeVoteQuery` and pass it any options that fit your needs.
* When your component renders, `useExplorerNodeVoteQuery` 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 } = useExplorerNodeVoteQuery({
* variables: {
* id: // value for 'id'
* },
* });
*/
export function useExplorerNodeVoteQuery(baseOptions: Apollo.QueryHookOptions<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>(ExplorerNodeVoteDocument, options);
}
export function useExplorerNodeVoteLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>(ExplorerNodeVoteDocument, options);
}
export type ExplorerNodeVoteQueryHookResult = ReturnType<typeof useExplorerNodeVoteQuery>;
export type ExplorerNodeVoteLazyQueryHookResult = ReturnType<typeof useExplorerNodeVoteLazyQuery>;
export type ExplorerNodeVoteQueryResult = Apollo.QueryResult<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>;
@@ -0,0 +1,139 @@
import { TxDetailsChainMultisigThreshold } from './tx-multisig-threshold';
import { TxDetailsChainMultisigSigner } from './tx-multisig-signer';
import { TxDetailsChainEventBuiltinDeposit } from './tx-builtin-deposit';
import { TxDetailsChainEventStakeDeposit } from './tx-stake-deposit';
import { TxDetailsChainEventStakeRemove } from './tx-stake-remove';
import { TxDetailsChainEventStakeTotalSupply } from './tx-stake-totalsupply';
import { TxDetailsChainEventBuiltinWithdrawal } from './tx-builtin-withdrawal';
import { TxDetailsChainEventErc20AssetList } from './tx-erc20-asset-list';
import { TxDetailsChainEventErc20AssetLimitsUpdated } from './tx-erc20-asset-limits-updated';
import { TxDetailsChainEventErc20BridgePause } from './tx-erc20-bridge-pause';
import { TxDetailsChainEventDeposit } from './tx-erc20-deposit';
import isUndefined from 'lodash/isUndefined';
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
interface ChainEventProps {
txData: BlockExplorerTransactionResult | undefined;
}
/**
* Inspects the chain event to determine which details view to show. The list of types
* comes from the Swagger document that Block Explorer provides, which can be viewed at
* https://docs.vega.xyz/testnet/api/rest/explorer/block-explorer-list-transactions
*
* This component should have one entry per chain event type, however if there isn't
* a bespoke view for an event the tx-details-shared will still render some basic
* overview and the transaction viewer will still let people view the raw TX.
*
* Most chain events simply render more table rows for the header table
*
* @returns React.JSXElement
*/
export const ChainEvent = ({ txData }: ChainEventProps) => {
const e = txData?.command.chainEvent;
if (!e) {
return null;
}
// Builtin Asset events
if (e.builtin) {
if (e.builtin.deposit) {
return <TxDetailsChainEventBuiltinDeposit deposit={e.builtin.deposit} />;
}
if (e.builtin?.withdrawal) {
return (
<TxDetailsChainEventBuiltinWithdrawal
withdrawal={e.builtin?.withdrawal}
/>
);
}
}
// ERC20 asset events
if (e.erc20) {
if (e.erc20.deposit) {
return <TxDetailsChainEventDeposit deposit={e.erc20.deposit} />;
}
if (e.erc20.withdrawal) {
return (
<TxDetailsChainEventBuiltinWithdrawal withdrawal={e.erc20.withdrawal} />
);
}
if (e.erc20.assetList) {
return (
<TxDetailsChainEventErc20AssetList assetList={e.erc20.assetList} />
);
}
if (e.erc20.assetLimitsUpdated) {
return (
<TxDetailsChainEventErc20AssetLimitsUpdated
assetLimitsUpdated={e.erc20.assetLimitsUpdated}
/>
);
}
const bridgeStopped = e.erc20.bridgeStopped;
const bridgeResumed = e.erc20.bridgeResumed;
if (!isUndefined(bridgeStopped) || !isUndefined(bridgeResumed)) {
const isPaused = bridgeStopped === false || bridgeResumed === true;
return <TxDetailsChainEventErc20BridgePause isPaused={isPaused} />;
}
}
// ERC20 multisig events
if (e.erc20Multisig) {
if (e.erc20Multisig.thresholdSet) {
return (
<TxDetailsChainMultisigThreshold
thresholdSet={e.erc20Multisig.thresholdSet}
/>
);
}
if (e.erc20Multisig.signerAdded) {
return (
<TxDetailsChainMultisigSigner signer={e.erc20Multisig.signerAdded} />
);
}
if (e.erc20Multisig.signerRemoved) {
return (
<TxDetailsChainMultisigSigner signer={e.erc20Multisig.signerRemoved} />
);
}
}
// Staking events
if (e.stakingEvent) {
if (e.stakingEvent.stakeDeposited) {
return (
<TxDetailsChainEventStakeDeposit
deposit={e.stakingEvent.stakeDeposited}
/>
);
}
if (e.stakingEvent.stakeRemoved) {
return (
<TxDetailsChainEventStakeRemove remove={e.stakingEvent.stakeRemoved} />
);
}
if (e.stakingEvent.totalSupply) {
return (
<TxDetailsChainEventStakeTotalSupply
update={e.stakingEvent.totalSupply}
/>
);
}
}
// If we hit this return, tx-shared-details should give a basic overview
return null;
};
@@ -0,0 +1,16 @@
/**
* Returns a reasonably formatted time from unix timestamp of block height
*
* @param date String or null date
* @returns String date in locale time
*/
export function getBlockTime(date?: string) {
if (!date) {
return '-';
}
const timeInSeconds = parseInt(date, 10);
const timeInMs = timeInSeconds * 1000;
return new Date(timeInMs).toLocaleString();
}
@@ -0,0 +1,46 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink, PartyLink } from '../../../links';
interface TxDetailsChainEventBuiltinDepositProps {
deposit: components['schemas']['vegaBuiltinAssetDeposit'];
}
/**
* Someone deposited some of a builtin asset. Builtin assets
* have no value outside the Vega chain and should appear only
* on Test networks.
*/
export const TxDetailsChainEventBuiltinDeposit = ({
deposit,
}: TxDetailsChainEventBuiltinDepositProps) => {
if (!deposit) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain Event type')}</TableCell>
<TableCell>{t('Built-in asset deposit')}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Recipient')}</TableCell>
<TableCell>
<PartyLink id={deposit.partyId || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Asset')}</TableCell>
<TableCell>
<AssetLink id={deposit.vegaAssetId || ''} /> ({t('built in asset')})
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Amount')}</TableCell>
<TableCell>{deposit.amount}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,47 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink, PartyLink } from '../../../links';
interface TxDetailsChainEventBuiltinDepositProps {
withdrawal: components['schemas']['vegaBuiltinAssetWithdrawal'];
}
/**
* Someone withdrew some of a builtin asset. Builtin assets
* have no value outside the Vega chain and should appear only
* on Test networks, so someone withdrawing it is pretty rare
*/
export const TxDetailsChainEventBuiltinWithdrawal = ({
withdrawal,
}: TxDetailsChainEventBuiltinDepositProps) => {
if (!withdrawal) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain Event type')}</TableCell>
<TableCell>{t('Built-in asset withdrawal')}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Recipient')}</TableCell>
<TableCell>
<PartyLink id={withdrawal.partyId || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Asset')}</TableCell>
<TableCell>
<AssetLink id={withdrawal.vegaAssetId || ''} /> ({t('built in asset')}
)
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Amount')}</TableCell>
<TableCell>{withdrawal.amount}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,37 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links';
interface TxDetailsChainEventErc20AssetDelistProps {
assetDelist: components['schemas']['vegaERC20AssetDelist'];
}
/**
* An ERC20 asset was removed from the bridge,
* The link should link to an asset that doesn't exist. Which feels odd
* but I think is better than having no link - in case something
* weird is up and it still exists
*/
export const TxDetailsChainEventErc20AssetDelist = ({
assetDelist,
}: TxDetailsChainEventErc20AssetDelistProps) => {
if (!assetDelist) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain event type')}</TableCell>
<TableCell>{t('ERC20 asset removed')}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Removed Vega asset')}</TableCell>
<TableCell>
<AssetLink id={assetDelist.vegaAssetId || ''} />
</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,65 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links';
import {
EthExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
interface TxDetailsChainEventErc20AssetLimitsUpdatedProps {
assetLimitsUpdated: components['schemas']['vegaERC20AssetLimitsUpdated'];
}
/**
* An ERC20 asset was had its limits changed. The limits are in place
* at first to prevent users depositing large sums while the network
* is still new, as a safety measure.
* - Lifetime limit is how much can be withdrawn of this asset to a
* single ethereum address
* - Withdraw threshold is the size of a withdrawal that will incur
* a delay in processing. The delay is set by a network parameter
*/
export const TxDetailsChainEventErc20AssetLimitsUpdated = ({
assetLimitsUpdated,
}: TxDetailsChainEventErc20AssetLimitsUpdatedProps) => {
if (!assetLimitsUpdated) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain event type')}</TableCell>
<TableCell>{t('ERC20 asset limits updated')}</TableCell>
</TableRow>
{assetLimitsUpdated.sourceEthereumAddress ? (
<TableRow modifier="bordered">
<TableCell>{t('ERC20 asset')}</TableCell>
<TableCell>
<EthExplorerLink
id={assetLimitsUpdated.sourceEthereumAddress}
type={EthExplorerLinkTypes.address}
/>
</TableCell>
</TableRow>
) : null}
<TableRow modifier="bordered">
<TableCell>{t('Vega asset')}</TableCell>
<TableCell>
<AssetLink id={assetLimitsUpdated.vegaAssetId || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Total lifetime limit')}</TableCell>
<TableCell>{assetLimitsUpdated.lifetimeLimits}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Asset withdrawal threshold')}</TableCell>
<TableCell>{assetLimitsUpdated.withdrawThreshold}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,51 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links';
import {
EthExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
interface TxDetailsChainEventErc20AssetListProps {
assetList: components['schemas']['vegaERC20AssetList'];
}
/**
* An ERC20 asset was proposed and then enacted on the bridge,
* a Asset List event will be emitted that tells the core to
* create the asset. That's this event - it's very basic
*/
export const TxDetailsChainEventErc20AssetList = ({
assetList,
}: TxDetailsChainEventErc20AssetListProps) => {
if (!assetList) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain event type')}</TableCell>
<TableCell>{t('ERC20 asset added')}</TableCell>
</TableRow>
{assetList.assetSource ? (
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>
<EthExplorerLink
id={assetList.assetSource}
type={EthExplorerLinkTypes.address}
/>
</TableCell>
</TableRow>
) : null}
<TableRow modifier="bordered">
<TableCell>{t('Added Vega asset')}</TableCell>
<TableCell>
<AssetLink id={assetList.vegaAssetId || ''} />
</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,24 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
interface TxDetailsChainEventErc20BridgePauseProps {
isPaused: boolean;
}
/**
* The bridge was either paused or unpaused, preventing withdrawals
* or deposits from being enacted. This will only happen if the
* validators have signed a multisig bundle requiring it to happen
*/
export const TxDetailsChainEventErc20BridgePause = ({
isPaused,
}: TxDetailsChainEventErc20BridgePauseProps) => {
const event = isPaused ? 'pause' : 'unpaused';
return (
<TableRow modifier="bordered">
<TableCell>{t('Chain event type')}</TableCell>
<TableCell>{t(`ERC20 bridge ${event}`)}</TableCell>
</TableRow>
);
};
@@ -0,0 +1,59 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink, PartyLink } from '../../../links';
import {
EthExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
interface TxDetailsChainEventProps {
deposit: components['schemas']['vegaERC20Deposit'];
}
/**
* Someone deposited some erc20
*/
export const TxDetailsChainEventDeposit = ({
deposit,
}: TxDetailsChainEventProps) => {
if (!deposit) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain event type')}</TableCell>
<TableCell>{t('ERC20 deposit')}</TableCell>
</TableRow>
{deposit.sourceEthereumAddress ? (
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>
<EthExplorerLink
id={deposit.sourceEthereumAddress}
type={EthExplorerLinkTypes.address}
/>
</TableCell>
</TableRow>
) : null}
<TableRow modifier="bordered">
<TableCell>{t('Recipient')}</TableCell>
<TableCell>
<PartyLink id={deposit.targetPartyId || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Asset')}</TableCell>
<TableCell>
<AssetLink id={deposit.vegaAssetId || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Amount')}</TableCell>
<TableCell>{deposit.amount}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,51 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links';
import {
EthExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
interface TxDetailsChainEventWithdrawalProps {
withdrawal: components['schemas']['vegaERC20Withdrawal'];
}
/**
* Someone deposited some erc20
*/
export const TxDetailsChainEventWithdrawal = ({
withdrawal,
}: TxDetailsChainEventWithdrawalProps) => {
if (!withdrawal) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain event type')}</TableCell>
<TableCell>{t('ERC20 withdrawal')}</TableCell>
</TableRow>
{withdrawal.targetEthereumAddress ? (
<TableRow modifier="bordered">
<TableCell>{t('Recipient')}</TableCell>
<TableCell>
<EthExplorerLink
id={withdrawal.targetEthereumAddress}
type={EthExplorerLinkTypes.address}
/>
</TableCell>
</TableRow>
) : null}
<TableRow modifier="bordered">
<TableCell>{t('Asset')}</TableCell>
<TableCell>
<AssetLink id={withdrawal.vegaAssetId || ''} />
</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,50 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { getBlockTime } from './lib/get-block-time';
interface TxDetailsChainMultisigSignerProps {
signer:
| components['schemas']['vegaERC20SignerAdded']
| components['schemas']['vegaERC20SignerRemoved'];
}
/**
* Someone updated multsig signer set, either removing or adding someone
*/
export const TxDetailsChainMultisigSigner = ({
signer,
}: TxDetailsChainMultisigSignerProps) => {
if (!signer) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const blockTime = getBlockTime(signer.blockTime);
const target =
'newSigner' in signer
? signer.newSigner
: 'oldSigner' in signer
? signer.oldSigner
: '';
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain Event type')}</TableCell>
{'newSigner' in signer
? t('Add ERC20 bridge multisig signer')
: t('Remove ERC20 bridge multsig signer')}
</TableRow>
<TableRow modifier="bordered">
<TableCell>
{'newSigner' in signer ? t('Add signer') : t('Remove signer')}
</TableCell>
<TableCell>{target}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Signer change at')}</TableCell>
<TableCell>{blockTime}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,59 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import isNumber from 'lodash/isNumber';
/**
* Returns a reasonably formatted time from unix timestamp of block height
*
* @param date String or null date
* @returns String date in locale time
*/
function getBlockTime(date?: string) {
if (!date) {
return '-';
}
const timeInSeconds = parseInt(date, 10);
const timeInMs = timeInSeconds * 1000;
return new Date(timeInMs).toLocaleString();
}
interface TxDetailsChainMultisigThresholdProps {
thresholdSet: components['schemas']['vegaERC20MultiSigEvent']['thresholdSet'];
}
/**
* Someone updated multsig threshold value on the smart contract.
* It's a percentage, with 1000 being 100% and 0 being 0%.
*/
export const TxDetailsChainMultisigThreshold = ({
thresholdSet,
}: TxDetailsChainMultisigThresholdProps) => {
if (!thresholdSet) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const blockTime = getBlockTime(thresholdSet.blockTime);
const threshold = isNumber(thresholdSet.newThreshold)
? thresholdSet.newThreshold / 10
: '-';
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain Event type')}</TableCell>
<TableCell>{t('ERC20 multisig threshold set')}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Threshold')}</TableCell>
<TableCell>{threshold}%</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Threshold set from')}</TableCell>
<TableCell>{blockTime}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,49 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { PartyLink } from '../../../links';
interface TxDetailsChainEventStakeDepositProps {
deposit: components['schemas']['vegaStakeDeposited'];
}
/**
* Someone addedd some stake for a particular party
* This should link to the Governance asset, but doesn't
* as that would require checking the Network Paramters
* Ethereum address should also be a link to an ETH block explorer
*/
export const TxDetailsChainEventStakeDeposit = ({
deposit,
}: TxDetailsChainEventStakeDepositProps) => {
if (!deposit) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain Event type')}</TableCell>
<TableCell>{t('Stake deposited')}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>{deposit.ethereumAddress || ''}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Recipient')}</TableCell>
<TableCell>
<PartyLink id={deposit.vegaPublicKey || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Amount')}</TableCell>
<TableCell>{deposit.amount}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Deposited at')}</TableCell>
<TableCell>{deposit.amount}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,49 @@
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { PartyLink } from '../../../links';
interface TxDetailsChainEventStakeRemoveProps {
remove: components['schemas']['vegaStakeRemoved'];
}
/**
* Someone addedd some stake for a particular party
* This should link to the Governance asset, but doesn't
* as that would require checking the Network Parameters
* Ethereum address should also be a link to an ETH block explorer
*/
export const TxDetailsChainEventStakeRemove = ({
remove,
}: TxDetailsChainEventStakeRemoveProps) => {
if (!remove) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain Event type')}</TableCell>
<TableCell>{t('Stake removed')}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>{remove.ethereumAddress || ''}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Recipient')}</TableCell>
<TableCell>
<PartyLink id={remove.vegaPublicKey || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Amount')}</TableCell>
<TableCell>{remove.amount}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Deposited at')}</TableCell>
<TableCell>{remove.blockTime}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,54 @@
import { formatNumber, t, toBigNum } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import {
EthExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
interface TxDetailsChainEventStakeTotalSupplyProps {
update: components['schemas']['vegaStakeTotalSupply'];
}
/**
* Chain event set the total supply of the governance asset
* Happens whenever the total supply changes, or when the chain
* restarts and the total supply is detected.
*/
export const TxDetailsChainEventStakeTotalSupply = ({
update,
}: TxDetailsChainEventStakeTotalSupplyProps) => {
if (!update) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
let totalSupply = update.totalSupply || '';
if (totalSupply.length > 0) {
totalSupply = formatNumber(toBigNum(totalSupply, 18));
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Chain Event type')}</TableCell>
<TableCell>{t('Stake total supply update')}</TableCell>
</TableRow>
{update.tokenAddress ? (
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>
<EthExplorerLink
id={update.tokenAddress}
type={EthExplorerLinkTypes.address}
/>
</TableCell>
</TableRow>
) : null}
<TableRow modifier="bordered">
<TableCell>{t('Total supply')}</TableCell>
<TableCell>{totalSupply}</TableCell>
</TableRow>
</>
);
};
@@ -0,0 +1,32 @@
query ExplorerNodeVote($id: ID!) {
withdrawal(id: $id) {
id
status
createdTimestamp
withdrawnTimestamp
txHash
asset {
id
name
decimals
}
party {
id
}
}
deposit(id: $id) {
id
status
createdTimestamp
creditedTimestamp
txHash
asset {
id
name
decimals
}
party {
id
}
}
}
@@ -1,4 +1,3 @@
import React from 'react';
import { t } from '@vegaprotocol/react-helpers';
import { TableRow, TableCell } from '../../../table';
import { BlockLink, PartyLink } from '../../../links/';
@@ -6,6 +5,7 @@ import { TimeAgo } from '../../../time-ago';
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../../routes/blocks/tendermint-blocks-response';
import { Time } from '../../../time';
interface TxDetailsSharedProps {
txData: BlockExplorerTransactionResult | undefined;
@@ -29,11 +29,6 @@ export const TxDetailsShared = ({
const time: string = blockData?.result.block.header.time || '';
const height: string = blockData?.result.block.header.height || '';
let timeFormatted = '';
if (time) {
timeFormatted = new Date(time).toLocaleString();
}
return (
<>
@@ -56,7 +51,9 @@ export const TxDetailsShared = ({
<TableCell>
{time ? (
<div>
<span className="mr-5">{timeFormatted} </span>
<span className="mr-5">
<Time date={time} />
</span>
<span>
<TimeAgo date={time} />
</span>
@@ -1,9 +1,5 @@
import React from 'react';
import { t } from '@vegaprotocol/react-helpers';
import type {
BlockExplorerTransactionResult,
BatchMarketInstructions,
} from '../../../routes/types/block-explorer-response';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableWithTbody, TableRow, TableCell } from '../../table';
@@ -26,16 +22,17 @@ export const TxDetailsBatch = ({
pubKey,
blockData,
}: TxDetailsBatchProps) => {
if (!txData) {
if (!txData || !txData.command.batchMarketInstructions) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const cmd = txData.command as BatchMarketInstructions;
const batchSubmissions = cmd.batchMarketInstructions.submissions.length;
const batchAmendments = cmd.batchMarketInstructions.amendments.length;
const batchCancellations = cmd.batchMarketInstructions.cancellations.length;
const batchTotal = batchSubmissions + batchAmendments + batchCancellations;
const countSubmissions =
txData.command.batchMarketInstructions.submissions?.length || 0;
const countAmendments =
txData.command.batchMarketInstructions.amendments?.length || 0;
const countCancellations =
txData.command.batchMarketInstructions.cancellations?.length || 0;
const countTotal = countSubmissions + countAmendments + countCancellations;
return (
<TableWithTbody>
@@ -43,7 +40,7 @@ export const TxDetailsBatch = ({
<TableRow modifier="bordered">
<TableCell>{t('Batch size')}</TableCell>
<TableCell>
<span>{batchTotal}</span>
<span>{countTotal}</span>
</TableCell>
</TableRow>
<TableRow modifier="bordered">
@@ -51,7 +48,7 @@ export const TxDetailsBatch = ({
<span className="ml-5">{t('Submissions')}</span>
</TableCell>
<TableCell>
<span>{batchSubmissions}</span>
<span>{countSubmissions}</span>
</TableCell>
</TableRow>
<TableRow modifier="bordered">
@@ -59,7 +56,7 @@ export const TxDetailsBatch = ({
<span className="ml-5">{t('Amendments')}</span>
</TableCell>
<TableCell>
<span>{batchAmendments}</span>
<span>{countAmendments}</span>
</TableCell>
</TableRow>
<TableRow modifier="bordered">
@@ -67,7 +64,7 @@ export const TxDetailsBatch = ({
<span className="ml-5">{t('Cancellations')}</span>
</TableCell>
<TableCell>
<span>{batchCancellations}</span>
<span>{countCancellations}</span>
</TableCell>
</TableRow>
</TableWithTbody>
@@ -1,13 +1,10 @@
import React from 'react';
import { t } from '@vegaprotocol/react-helpers';
import type {
BlockExplorerTransactionResult,
ChainEvent,
} from '../../../routes/types/block-explorer-response';
import { AssetLink, PartyLink } from '../../links';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table';
import { TableWithTbody } from '../../table';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { ChainEvent } from './chain-events';
interface TxDetailsChainEventProps {
txData: BlockExplorerTransactionResult | undefined;
@@ -20,10 +17,10 @@ interface TxDetailsChainEventProps {
* Multiple events will relay the same data, from each validator, so that the
* deposit/withdrawal can be verified independently.
*
* Design considerations so far:
* - The ethereum address should be a link to an Ethereum explorer
* - Sender and recipient are shown because they are easy
* - Amount is not shown because there is no formatter by asset component
* There are so many chain events that the specific components have been broken
* out in to individual components. `getChainEventComponent` determines which
* is the most appropriate based on the transaction shape. See that function
* for more information.
*/
export const TxDetailsChainEvent = ({
txData,
@@ -33,32 +30,11 @@ export const TxDetailsChainEvent = ({
if (!txData) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const cmd = txData.command as ChainEvent;
const assetId = cmd.chainEvent.erc20.deposit.vegaAssetId;
const sender = cmd.chainEvent.erc20.deposit.sourceEthereumAddress;
const recipient = cmd.chainEvent.erc20.deposit.targetPartyId;
return (
<TableWithTbody>
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
<TableRow modifier="bordered">
<TableCell>{t('Asset')}</TableCell>
<TableCell>
<AssetLink id={assetId} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Sender')}</TableCell>
<TableCell>
<span>{sender}</span>
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Recipient')}</TableCell>
<TableCell>
<PartyLink id={recipient} />
</TableCell>
</TableRow>
<ChainEvent txData={txData} />
</TableWithTbody>
);
};
@@ -1,4 +1,4 @@
import React, { useMemo } from 'react';
import { useMemo } from 'react';
import { DATA_SOURCES } from '../../../config';
import { t, useFetch } from '@vegaprotocol/react-helpers';
import { TxDetailsOrder } from './tx-order';
@@ -10,11 +10,10 @@ import { TxDetailsGeneric } from './tx-generic';
import { TxDetailsBatch } from './tx-batch';
import { TxDetailsChainEvent } from './tx-chain-event';
import { TxContent } from '../../../routes/txs/id/tx-content';
type resultOrNull = BlockExplorerTransactionResult | undefined;
import { TxDetailsNodeVote } from './tx-node-vote';
interface TxDetailsWrapperProps {
txData: resultOrNull;
txData: BlockExplorerTransactionResult | undefined;
pubKey: string | undefined;
height: string;
}
@@ -27,7 +26,8 @@ export const TxDetailsWrapper = ({
const {
state: { data: blockData },
} = useFetch<TendermintBlocksResponse>(
`${DATA_SOURCES.tendermintUrl}/block?height=${height}`
`${DATA_SOURCES.tendermintUrl}/block?height=${height}`,
{ cache: 'force-cache' }
);
const child = useMemo(() => getTransactionComponent(txData), [txData]);
@@ -61,7 +61,7 @@ export const TxDetailsWrapper = ({
* @param txData
* @returns JSX.Element
*/
function getTransactionComponent(txData: resultOrNull) {
function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
if (!txData) {
return TxDetailsGeneric;
}
@@ -77,6 +77,8 @@ function getTransactionComponent(txData: resultOrNull) {
return TxDetailsBatch;
case 'Chain Event':
return TxDetailsChainEvent;
case 'Node Vote':
return TxDetailsNodeVote;
default:
return TxDetailsGeneric;
}
@@ -1,4 +1,3 @@
import React from 'react';
import { t } from '@vegaprotocol/react-helpers';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
@@ -1,9 +1,5 @@
import React from 'react';
import { t } from '@vegaprotocol/react-helpers';
import type {
BlockExplorerTransactionResult,
ValidatorHeartbeat,
} from '../../../routes/types/block-explorer-response';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import { BlockLink, NodeLink } from '../../links/';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
@@ -56,11 +52,12 @@ export const TxDetailsHeartbeat = ({
pubKey,
blockData,
}: TxDetailsHeartbeatProps) => {
if (!txData) {
if (!txData || !txData.command.validatorHeartbeat) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const cmd = txData.command as ValidatorHeartbeat;
const nodeId = txData.command.validatorHeartbeat.nodeId || '';
const blockHeight = txData.command.blockHeight || '';
return (
<TableWithTbody>
@@ -68,18 +65,18 @@ export const TxDetailsHeartbeat = ({
<TableRow modifier="bordered">
<TableCell>{t('Node')}</TableCell>
<TableCell>
<NodeLink id={cmd.validatorHeartbeat.nodeId} />
<NodeLink id={nodeId} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Signed block height')}</TableCell>
<TableCell>
<BlockLink height={cmd.blockHeight} />
<BlockLink height={blockHeight} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Freshness (lower is better)')}</TableCell>
<TableCell>{scoreFreshness(txData.block, cmd.blockHeight)}</TableCell>
<TableCell>{scoreFreshness(txData.block, blockHeight)}</TableCell>
</TableRow>
</TableWithTbody>
);
@@ -1,9 +1,5 @@
import React from 'react';
import { t } from '@vegaprotocol/react-helpers';
import type {
AmendLiquidityProvisionOrder,
BlockExplorerTransactionResult,
} from '../../../routes/types/block-explorer-response';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import { MarketLink } from '../../links/';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
@@ -29,7 +25,7 @@ export const TxDetailsLPAmend = ({
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const cmd = txData.command as AmendLiquidityProvisionOrder;
const marketId = txData.command.liquidityProvisionAmendment?.marketId || '';
return (
<TableWithTbody>
@@ -37,7 +33,7 @@ export const TxDetailsLPAmend = ({
<TableRow modifier="bordered">
<TableCell>{t('Market')}</TableCell>
<TableCell>
<MarketLink id={cmd.liquidityProvisionAmendment.marketId} />
<MarketLink id={marketId} />
</TableCell>
</TableRow>
</TableWithTbody>
@@ -0,0 +1,144 @@
import { t } from '@vegaprotocol/react-helpers';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table';
import type { ExplorerNodeVoteQueryResult } from './__generated___/node-vote';
import { useExplorerNodeVoteQuery } from './__generated___/node-vote';
import { PartyLink } from '../../links';
import { Time } from '../../time';
interface TxDetailsNodeVoteProps {
txData: BlockExplorerTransactionResult | undefined;
pubKey: string | undefined;
blockData: TendermintBlocksResponse | undefined;
}
/**
* If there is not yet a custom component for a transaction, just display
* the basic details. This allows someone to view the decoded transaction.
*/
export const TxDetailsNodeVote = ({
txData,
pubKey,
blockData,
}: TxDetailsNodeVoteProps) => {
const id = txData?.command.nodeVote?.reference || '';
const { data } = useExplorerNodeVoteQuery({
variables: {
id,
},
// Required as one of these queries will needlessly error
errorPolicy: 'ignore',
});
if (!txData) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
return (
<TableWithTbody>
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
{data && !!data.deposit
? TxDetailsNodeVoteDeposit({ deposit: data })
: data && !!data.withdrawal
? TxDetailsNodeVoteWithdrawal({ withdrawal: data })
: null}
</TableWithTbody>
);
};
interface TxDetailsNodeVoteDepositProps {
deposit: ExplorerNodeVoteQueryResult['data'];
}
export function TxDetailsNodeVoteDeposit({
deposit,
}: TxDetailsNodeVoteDepositProps) {
if (!deposit) {
return null;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Witnessed Event type')}</TableCell>
{deposit?.deposit?.txHash ? (
<TableCell>{t('ERC20 deposit')}</TableCell>
) : (
<TableCell>{t('Built-in asset deposit')}</TableCell>
)}
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('To party')}:</TableCell>
<TableCell>
<PartyLink id={deposit?.deposit?.party?.id || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Credited on')}:</TableCell>
<TableCell>
<Time date={deposit?.deposit?.creditedTimestamp} />
</TableCell>
{deposit?.deposit?.txHash ? (
<TxHash hash={deposit?.deposit?.txHash} />
) : null}
</TableRow>
</>
);
}
interface TxDetailsNodeVoteWithdrawalProps {
withdrawal: ExplorerNodeVoteQueryResult['data'];
}
export function TxDetailsNodeVoteWithdrawal({
withdrawal,
}: TxDetailsNodeVoteWithdrawalProps) {
if (!withdrawal) {
return null;
}
return (
<>
<TableRow modifier="bordered">
<TableCell>{t('Witnessed Event type')}</TableCell>
{withdrawal?.withdrawal?.txHash ? (
<TableCell>{t('ERC20 withdrawal')}</TableCell>
) : (
<TableCell>{t('Built-in asset withdrawal')}</TableCell>
)}
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('From party')}:</TableCell>
<TableCell>
<PartyLink id={withdrawal?.deposit?.party?.id || ''} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Withdrawn on')}:</TableCell>
<TableCell>
<Time date={withdrawal?.withdrawal?.withdrawnTimestamp} />
</TableCell>
{withdrawal?.withdrawal?.txHash ? (
<TxHash hash={withdrawal?.withdrawal?.txHash} />
) : null}
</TableRow>
</>
);
}
interface TxDetailsEthTxHashProps {
hash: string;
}
export function TxHash({ hash }: TxDetailsEthTxHashProps) {
if (!hash) {
return null;
}
return (
<TableRow modifier="bordered">
<TableCell>Ethereum TX:</TableCell>
<TableCell>{hash}</TableCell>
</TableRow>
);
}
@@ -1,9 +1,5 @@
import React from 'react';
import { t } from '@vegaprotocol/react-helpers';
import type {
BlockExplorerTransactionResult,
SubmitOrder,
} from '../../../routes/types/block-explorer-response';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import { MarketLink } from '../../links/';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
@@ -26,11 +22,10 @@ export const TxDetailsOrder = ({
pubKey,
blockData,
}: TxDetailsOrderProps) => {
if (!txData) {
if (!txData || !txData.command.orderSubmission) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const cmd = txData.command as SubmitOrder;
const marketId = txData.command.orderSubmission.marketId || '-';
return (
<TableWithTbody>
@@ -38,7 +33,7 @@ export const TxDetailsOrder = ({
<TableRow modifier="bordered">
<TableCell>{t('Market')}</TableCell>
<TableCell>
<MarketLink id={cmd.orderSubmission.marketId} />
<MarketLink id={marketId} />
</TableCell>
</TableRow>
</TableWithTbody>
@@ -1,5 +1,9 @@
import { t } from '@vegaprotocol/react-helpers';
import type { components } from '../../../types/explorer';
interface TxOrderTypeProps {
orderType: string;
chainEvent?: components['schemas']['v1ChainEvent'];
className?: string;
}
@@ -32,13 +36,73 @@ const displayString: StringMap = {
ValidatorHeartbeat: 'Validator Heartbeat',
};
export const TxOrderType = ({ orderType }: TxOrderTypeProps) => {
/**
* Given a chain event, will try to provide a more useful label
* @param chainEvent
* @returns
*/
export function getLabelForChainEvent(
chainEvent: components['schemas']['v1ChainEvent']
): string {
if (chainEvent.builtin) {
if (chainEvent.builtin.deposit) {
return t('Built-in deposit');
} else if (chainEvent.builtin.withdrawal) {
return t('Built-in withdraw');
}
return t('Built-in event');
} else if (chainEvent.erc20) {
if (chainEvent.erc20.assetDelist) {
return t('ERC20 delist');
} else if (chainEvent.erc20.assetList) {
return t('ERC20 list');
} else if (chainEvent.erc20.bridgeResumed) {
return t('Bridge resume');
} else if (chainEvent.erc20.bridgeStopped) {
return t('Bridge pause');
} else if (chainEvent.erc20.deposit) {
return t('ERC20 deposit');
} else if (chainEvent.erc20.withdrawal) {
return t('ERC20 withdraw');
}
return t('ERC20 event');
} else if (chainEvent.stakingEvent) {
if (chainEvent.stakingEvent.stakeDeposited) {
return t('Stake add');
} else if (chainEvent.stakingEvent.stakeRemoved) {
return t('Stake remove');
}
return t('Staking event');
} else if (chainEvent.erc20Multisig) {
if (chainEvent.erc20Multisig.signerAdded) {
return t('Signer adde');
} else if (chainEvent.erc20Multisig.signerRemoved) {
return t('Signer remove');
} else if (chainEvent.erc20Multisig.thresholdSet) {
return t('Signer threshold');
}
return t('Multisig update');
}
return t('Chain Event');
}
export const TxOrderType = ({ orderType, chainEvent }: TxOrderTypeProps) => {
let type = displayString[orderType] || orderType;
let colours = 'text-white dark:text-white bg-zinc-800 dark:bg-zinc-800';
// This will get unwieldy and should probably produce a different colour of tag
if (type === 'Chain Event' && !!chainEvent) {
type = getLabelForChainEvent(chainEvent);
colours =
'text-white dark-text-white bg-vega-pink-dark dark:bg-vega-pink-dark';
}
return (
<div
data-testid="tx-type"
className="text-sm rounded-md leading-none px-2 py-2 inline-block text-white dark:text-white bg-zinc-800 dark:bg-zinc-800 "
className={`text-sm rounded-md leading-none px-2 py-2 inline-block ${colours}`}
>
{displayString[orderType] || orderType}
{type}
</div>
);
};
@@ -13,6 +13,7 @@ export const TxsInfiniteListItem = ({
type,
block,
index,
command,
}: Partial<BlockExplorerTransactionResult>) => {
if (
!hash ||
@@ -54,7 +55,7 @@ export const TxsInfiniteListItem = ({
/>
</div>
<div className="text-sm col-span-5 xl:col-span-2 leading-none flex items-center">
<TxOrderType orderType={type} />
<TxOrderType orderType={type} chainEvent={command?.chainEvent} />
</div>
<div
className="text-sm col-span-3 xl:col-span-1 leading-none flex items-center"
@@ -26,7 +26,7 @@ const generateTxs = (number: number): BlockExplorerTransactionResult[] => {
expiresAt: '1664966445481288736',
type: 'TYPE_LIMIT',
reference: 'traderbot',
peggedOrder: null,
peggedOrder: undefined,
},
},
}));
@@ -93,7 +93,7 @@ export const TxsInfiniteList = ({
{({ onItemsRendered, ref }) => (
<List
className="List"
height={595}
height={995}
itemCount={itemCount}
itemSize={isStacked ? 134 : 72}
onItemsRendered={onItemsRendered}
@@ -42,7 +42,9 @@ export const TxsPerBlock = ({ blockHeight }: TxsPerBlockProps) => {
</TableRow>
</thead>
<tbody>
{decodedBlockData.map(({ TxHash, PubKey, Type }) => {
{decodedBlockData.map(({ TxHash, PubKey, Type, Command }) => {
const chainEvent = JSON.parse(Command || '');
return (
<TableRow
modifier="bordered"
@@ -66,7 +68,7 @@ export const TxsPerBlock = ({ blockHeight }: TxsPerBlockProps) => {
/>
</TableCell>
<TableCell modifier="bordered">
<TxOrderType orderType={Type} />
<TxOrderType orderType={Type} chainEvent={chainEvent} />
</TableCell>
</TableRow>
);
+1
View File
@@ -16,6 +16,7 @@ export const ENV = {
blockExplorerUrl: windowOrDefault('NX_BLOCK_EXPLORER'),
tendermintUrl: windowOrDefault('NX_TENDERMINT_URL'),
tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'),
ethExplorerUrl: windowOrDefault('NX_ETHERSCAN_URL'),
},
flags: {
assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')),
+27 -21
View File
@@ -3,41 +3,47 @@ import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type AssetsFieldsFragment = { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string }, infrastructureFeeAccount?: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string } | null } | null };
export type ExplorerAssetsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ExplorerAssetsQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string }, infrastructureFeeAccount?: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string } | null } | null } } | null> | null } | null };
export const AssetsFieldsFragmentDoc = gql`
fragment AssetsFields on Asset {
id
name
symbol
decimals
source {
... on ERC20 {
contractAddress
}
... on BuiltinAsset {
maxFaucetAmountMint
}
}
infrastructureFeeAccount {
type
balance
market {
id
}
}
}
`;
export const ExplorerAssetsDocument = gql`
query ExplorerAssets {
assetsConnection {
edges {
node {
id
name
symbol
decimals
source {
... on ERC20 {
contractAddress
}
... on BuiltinAsset {
maxFaucetAmountMint
}
}
infrastructureFeeAccount {
type
balance
market {
id
}
}
...AssetsFields
}
}
}
}
`;
${AssetsFieldsFragmentDoc}`;
/**
* __useExplorerAssetsQuery__
@@ -1,26 +1,31 @@
fragment AssetsFields on Asset {
id
name
symbol
decimals
source {
... on ERC20 {
contractAddress
}
... on BuiltinAsset {
maxFaucetAmountMint
}
}
infrastructureFeeAccount {
type
balance
market {
id
}
}
}
query ExplorerAssets {
assetsConnection {
edges {
node {
id
name
symbol
decimals
source {
... on ERC20 {
contractAddress
}
... on BuiltinAsset {
maxFaucetAmountMint
}
}
infrastructureFeeAccount {
type
balance
market {
id
}
}
...AssetsFields
}
}
}
@@ -1,16 +1,15 @@
import { t } from '@vegaprotocol/react-helpers';
import { getNodes, t } from '@vegaprotocol/react-helpers';
import React from 'react';
import { RouteTitle } from '../../components/route-title';
import { SubHeading } from '../../components/sub-heading';
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { useExplorerAssetsQuery } from './__generated__/assets';
import type { AssetsFieldsFragment } from './__generated__/assets';
const Assets = () => {
const { data } = useExplorerAssetsQuery();
const assets = data?.assetsConnection?.edges?.map((n) => {
return n?.node;
});
const assets = getNodes<AssetsFieldsFragment>(data?.assetsConnection);
if (!assets || assets.length === 0) {
return <section></section>;
@@ -44,7 +44,7 @@ const Blocks = () => {
refetch,
} = useFetch<TendermintBlockchainResponse>(
`${DATA_SOURCES.tendermintUrl}/blockchain`,
undefined,
{ cache: 'no-cache' },
false
);
@@ -23,7 +23,8 @@ const Block = () => {
const {
state: { data: blockData, loading, error },
} = useFetch<TendermintBlocksResponse>(
`${DATA_SOURCES.tendermintUrl}/block?height=${block}`
`${DATA_SOURCES.tendermintUrl}/block?height=${block}`,
{ cache: 'force-cache' }
);
return (
@@ -1,3 +1,4 @@
import type { components } from '../../../types/explorer';
import type { UnknownObject } from '../../components/nested-data-list';
export interface BlockExplorerTransactionResult {
@@ -8,13 +9,7 @@ export interface BlockExplorerTransactionResult {
type: string;
code: number;
cursor: string;
command:
| ValidatorHeartbeat
| SubmitOrder
| StateVariableProposal
| AmendLiquidityProvisionOrder
| BatchMarketInstructions
| ChainEvent;
command: components['schemas']['v1InputData'];
}
export interface BlockExplorerTransactions {
@@ -103,16 +98,23 @@ export interface BatchCancellationInstruction {
export interface ChainEvent {
blockHeight: string;
nonce: string;
chainEvent: {
erc20: {
deposit: ERC20Deposit;
};
chainEvent: components['schemas']['v1ChainEvent'];
}
export interface ChainEventErc20Multisig {
erc20Multisig: {
block: string;
index: string;
};
}
export interface ERC20Deposit {
vegaAssetId: string;
sourceEthereumAddress: string;
targetPartyId: string;
amount: string;
export interface ChainEventErc20Deposit {
erc20: {
deposit: {
vegaAssetId: string;
sourceEthereumAddress: string;
targetPartyId: string;
amount: string;
};
};
}
File diff suppressed because it is too large Load Diff
+1
View File
@@ -13,6 +13,7 @@
"noFallthroughCasesInSwitch": true,
"lib": ["es5", "es6", "dom", "dom.iterable"]
},
"exclude": ["./src/types/explorer.d.ts"],
"include": [],
"references": [
{
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -8,8 +8,17 @@ import type {
} from 'ag-grid-community';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { t, addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
import { Icon, AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import {
t,
addDecimalsFormatNumber,
formatNumberPercentage,
toBigNum,
} from '@vegaprotocol/react-helpers';
import {
Icon,
AsyncRenderer,
TooltipCellComponent,
} from '@vegaprotocol/ui-toolkit';
import type { Market } from '@vegaprotocol/liquidity';
import {
useMarketsLiquidity,
@@ -50,9 +59,11 @@ export const MarketList = () => {
sortable: true,
unSortIcon: true,
cellClass: ['flex', 'flex-col', 'justify-center'],
tooltipComponent: TooltipCellComponent,
}}
getRowId={getRowId}
isRowClickable
tooltipShowDelay={500}
>
<AgGridColumn
headerName={t('Market (futures)')}
@@ -78,6 +89,7 @@ export const MarketList = () => {
}}
minWidth={100}
flex="1"
headerTooltip={t('The market name and settlement asset')}
/>
<AgGridColumn
@@ -90,10 +102,11 @@ export const MarketList = () => {
.decimals
)} (${displayChange(data.volumeChange)})`
}
headerTooltip={t('The trade volume over the last 24h')}
/>
<AgGridColumn
headerName={t('Committed bond/stake')}
headerName={t('Committed bond')}
field="liquidityCommitted"
valueFormatter={({ value, data }: ValueFormatterParams) =>
formatWithAsset(
@@ -101,6 +114,47 @@ export const MarketList = () => {
data.tradableInstrument.instrument.product.settlementAsset
)
}
headerTooltip={t(
'The amount of funds allocated to provide liquidity'
)}
/>
<AgGridColumn
headerName={t('Target stake')}
field="target"
valueFormatter={({ value, data }: ValueFormatterParams) =>
formatWithAsset(
value,
data.tradableInstrument.instrument.product.settlementAsset
)
}
headerTooltip={t(
'The ideal committed liquidity to operate the market. If total commitment currently below this level then LPs can set the fee level with new commitment.'
)}
/>
<AgGridColumn
headerName={t('% Target stake met')}
valueFormatter={({ data }: ValueFormatterParams) => {
const roundedPercentage =
parseInt(
(data.liquidityCommitted / parseFloat(data.target)).toFixed(0)
) * 100;
const display = Number.isNaN(roundedPercentage)
? 'N/A'
: formatNumberPercentage(toBigNum(roundedPercentage, 2));
return display;
}}
headerTooltip={t('% Target stake met')}
/>
<AgGridColumn
headerName={t('Fee levels')}
field="fees"
valueFormatter={({ value, data }: ValueFormatterParams) =>
`${value.factors.liquidityFee}%`
}
headerTooltip={t('Fee level for this market')}
/>
<AgGridColumn
@@ -117,6 +171,9 @@ export const MarketList = () => {
<Status trigger={data.data?.trigger} tradingMode={value} />
);
}}
headerTooltip={t(
'The current market status - those below the target stake mark are most in need of liquidity'
)}
/>
<AgGridColumn
@@ -154,7 +211,6 @@ export const MarketList = () => {
sortable={false}
cellStyle={{ overflow: 'unset' }}
/>
<AgGridColumn headerName={t('Est. return / APY')} field="apy" />
</Grid>
<HealthDialog
@@ -11,6 +11,7 @@ import type {
import { formatWithAsset } from '@vegaprotocol/liquidity';
import { Grid } from '../../grid';
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
const formatToHours = ({ value }: { value?: string | null }) => {
if (!value) {
@@ -39,11 +40,14 @@ export const LPProvidersGrid = ({
return (
<Grid
rowData={liquidityProviders}
tooltipShowDelay={500}
defaultColDef={{
resizable: true,
sortable: true,
unSortIcon: true,
cellClass: ['flex', 'flex-col', 'justify-center'],
tooltipComponent: TooltipCellComponent,
minWidth: 100,
}}
getRowId={getRowId}
rowHeight={92}
@@ -53,11 +57,13 @@ export const LPProvidersGrid = ({
field="party.id"
flex="1"
minWidth={100}
headerTooltip={t('Liquidity providers')}
/>
<AgGridColumn
headerName={t('Time in market')}
headerName={t('Duration')}
valueFormatter={formatToHours}
field="createdAt"
headerTooltip={t('Time in market')}
/>
<AgGridColumn
headerName={t('Equity-like share')}
@@ -67,23 +73,50 @@ export const LPProvidersGrid = ({
? `${parseFloat(parseFloat(value).toFixed(2)) * 100}%`
: '';
}}
headerTooltip={t(
'The share of the markets liquidity held - the earlier you commit liquidity the greater % fees you earn'
)}
minWidth={140}
/>
<AgGridColumn
headerName={t('committed bond/stake')}
headerName={t('committed bond')}
field="commitmentAmount"
valueFormatter={({ value }: { value?: string | null }) =>
value ? formatWithAsset(value, settlementAsset) : '0'
}
headerTooltip={t('The amount of funds allocated to provide liquidity')}
minWidth={140}
/>
<AgGridColumn
headerName={t('Margin Req.')}
field="margin"
headerTooltip={t(
'Margin required for arising positions based on liquidity commitment'
)}
/>
<AgGridColumn
headerName={t('24h Fees')}
field="fees"
headerTooltip={t(
'Total fees earned by the liquidity provider in the last 24 hours'
)}
/>
<AgGridColumn headerName={t('Margin Req.')} field="margin" />
<AgGridColumn headerName={t('24h Fees')} field="fees" />
<AgGridColumn
headerName={t('Fee level')}
valueFormatter={({ value }: { value?: string | null }) => `${value}%`}
field="fee"
headerTooltip={t(
"The market's liquidity fee, or the percentage of a trade's value which is collected from the price taker for every trade"
)}
/>
<AgGridColumn headerName={t('APY')} field="apy" />
<AgGridColumn
headerName={t('APY')}
field="apy"
headerTooltip={t(
'An annualised estimate based on the total liquidity provision fees and maker fees collected by liquidity providers, the maximum margin needed and maximum commitment (bond) over the course of 7 epochs'
)}
/>
</Grid>
);
};
@@ -1,4 +1,4 @@
import { Lozenge } from '@vegaprotocol/ui-toolkit';
import { Lozenge, Tooltip } from '@vegaprotocol/ui-toolkit';
import classNames from 'classnames';
import {
@@ -6,6 +6,7 @@ import {
AuctionTriggerMapping,
Schema,
} from '@vegaprotocol/types';
import { t } from '@vegaprotocol/react-helpers';
import { Indicator } from '../indicator';
@@ -33,17 +34,46 @@ export const Status = ({
return MarketTradingModeMapping[tradingMode];
};
const status = getStatus();
const tooltipDescription = t(getTooltipDescription(status));
return (
<div
className={classNames('inline-flex whitespace-normal', {
'text-base': size === 'large',
'text-sm': size === 'small',
})}
>
<Lozenge className="border border-greys-light-300 bg-greys-light-100 flex items-center">
<Indicator status={tradingMode} />
{getStatus()}
</Lozenge>
<div>
<Tooltip description={tooltipDescription}>
<div
className={classNames('inline-flex whitespace-normal', {
'text-base': size === 'large',
'text-sm': size === 'small',
})}
>
<Lozenge className="border border-greys-light-300 bg-greys-light-100 flex items-center">
<Indicator status={tradingMode} />
{status}
</Lozenge>
</div>
</Tooltip>
</div>
);
};
const getTooltipDescription = (status: string) => {
let tooltipDescription = '';
switch (status) {
case MarketTradingModeMapping.TRADING_MODE_CONTINUOUS:
tooltipDescription =
'This is the standard trading mode where trades are executed whenever orders are received';
break;
case `${MarketTradingModeMapping.TRADING_MODE_MONITORING_AUCTION} - ${AuctionTriggerMapping.AUCTION_TRIGGER_LIQUIDITY}`:
tooltipDescription =
'This market is in auction until it reaches sufficient liquidity';
break;
case MarketTradingModeMapping.TRADING_MODE_OPENING_AUCTION:
tooltipDescription =
'This is a new market in an opening auction to determine a fair mid-price before starting continuous trading.';
break;
default:
break;
}
return tooltipDescription;
};
+1 -1
View File
@@ -1,4 +1,4 @@
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,3 +1,3 @@
{
"hosts": ["https://api.n01.stagnet3.vega.xyz/graphql"]
"hosts": ["https://api.stagnet3.vega.xyz/graphql"]
}
+1 -1
View File
@@ -1,3 +1,3 @@
# App configuration variables
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3;
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_ENV=STAGNET3
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -644,7 +644,7 @@ context(
it('Unable to create a proposal - when no tokens are associated', function () {
cy.vega_wallet_teardown();
cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
'0.000000000000000000',
'0.00',
txTimeout
);
cy.go_to_make_new_proposal(governanceProposalType.RAW);
@@ -759,7 +759,7 @@ context(
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.999900000000000000'
'0.9999'
);
});
cy.navigate_to('governance');
@@ -804,7 +804,7 @@ context(
cy.get(connectToVegaWalletButton).should('not.exist');
// 3001-VOTE-100
cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
'1.000000000000000000',
'1.00',
txTimeout
);
cy.vote_for_proposal('against');
@@ -116,7 +116,7 @@ context(
cy.get(newProposalSubmitButton).click();
cy.get(feedbackError).should(
'have.text',
'proposal_submission.terms.closing_timestamp: cannot be after enactment time'
'Invalid params: proposal_submission.terms.closing_timestamp (cannot be after enactment time)'
);
cy.get(dialogCloseButton).click();
cy.get(minVoteDeadline).click();
@@ -157,7 +157,7 @@ context(
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should(
'have.text',
'*: unknown field "signers" in vega.DataSourceDefinition'
'Invalid params: the transaction is malformed'
);
});
@@ -554,7 +554,7 @@ context(
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.000000000000000000'
'0.00'
);
});
@@ -608,7 +608,7 @@ context(
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.000000000000000000'
'0.00'
);
});
@@ -656,7 +656,7 @@ context(
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'2.000000000000000000'
'2.00'
);
});
@@ -819,7 +819,7 @@ context(
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'12.000000000000000000'
'12.00'
);
});
@@ -28,7 +28,6 @@ context(
before('visit staking tab and connect vega wallet', function () {
cy.visit('/');
cy.verify_page_header('The $VEGA token');
cy.vega_wallet_connect();
cy.vega_wallet_set_specified_approval_amount('1000');
});
@@ -109,7 +108,7 @@ context(
cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort)
.parent()
.should('contain', '1,001.000000000000000000', txTimeout);
.should('contain', '1,001.00', txTimeout);
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('1,001.00', txTimeout)
@@ -118,7 +117,7 @@ context(
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'1,001.000000000000000000'
'1,001.00'
);
});
});
@@ -43,10 +43,6 @@ context(
it('Able to open withdrawal form with vega wallet connected', function () {
// needs to reload page for withdrawal form to be displayed in ci - not reproducible outside of ci
cy.getByTestId(withdraw).should('be.visible').click();
cy.visit('/');
cy.navigate_to('withdrawals');
cy.ethereum_wallet_connect();
cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(selectAsset)
.find('option')
.should('have.length.at.least', 2);
@@ -79,7 +75,7 @@ context(
cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(selectAsset).select(usdtName);
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(withdrawalThreshold).should('have.text', '100,000.00000T');
cy.getByTestId(withdrawalThreshold).should('have.text', '100,000.00T');
cy.getByTestId(delayTime).should('have.text', 'None');
cy.getByTestId(amountInput).click().type('100');
cy.getByTestId(submitWithdrawalButton).click();
@@ -94,7 +90,7 @@ context(
.should('have.attr', 'href')
.and('contain', '/txs/');
cy.getByTestId(withdrawalAssetSymbol).should('have.text', usdcSymbol);
cy.getByTestId(withdrawalAmount).should('have.text', '100.00000');
cy.getByTestId(withdrawalAmount).should('have.text', '100.00');
cy.getByTestId(withdrawalRecipient)
.should('have.text', truncatedWithdrawalEthAddress)
.and('have.attr', 'href')
@@ -118,7 +114,7 @@ context(
.parent()
.within(() => {
cy.get('[col-id="asset.symbol"]').should('have.text', usdcSymbol);
cy.get('[col-id="amount"]').should('have.text', '100.00000');
cy.get('[col-id="amount"]').should('have.text', '100.00');
cy.get('[col-id="details.receiverAddress"]')
.find('a')
.should('have.attr', 'href')
@@ -163,7 +159,7 @@ context(
.parent()
.within(() => {
cy.get('[col-id="asset.symbol"]').should('have.text', usdcSymbol);
cy.get('[col-id="amount"]').should('have.text', '100.00000');
cy.get('[col-id="amount"]').should('have.text', '100.00');
cy.get('[col-id="details.receiverAddress"]')
.find('a')
.should('have.attr', 'href')
@@ -4,6 +4,7 @@ const validatorTitle = '[data-testid="validator-node-title"]';
const validatorId = '[data-testid="validator-id"]';
const validatorPubKey = '[data-testid="validator-public-key"]';
const ethAddressLink = '[data-testid="link"]';
const validatorStatus = '[data-testid="validator-status"]';
const totalStake = '[data-testid="total-stake"]';
const pendingStake = '[data-testid="pending-stake"]';
const stakedByOperator = '[data-testid="staked-by-operator"]';
@@ -162,6 +163,10 @@ context('Staking Page - verify elements on page', function () {
});
// TODO validators missing url for more information about them 2001-STKE-09
it('Should be able to see validator status', function () {
cy.get(validatorStatus).should('have.text', 'Consensus');
});
// 2001-STKE-012
it('Should be able to see total stake', function () {
cy.get(totalStake).invoke('text').should('match', stakeNumberRegex);
@@ -141,7 +141,7 @@ context(
cy.get(currencyValue)
.should('be.visible')
.invoke('text')
.should('match', /\d{0,3}(,\d{3})*\.\d{18}$/);
.should('match', /\d{0,3}(,\d{3})*\.\d{2}$/);
});
});
@@ -210,7 +210,7 @@ context(
cy.get(currencyValue)
.should('be.visible')
.invoke('text')
.should('match', /\d{0,3}(,\d{3})*\.\d{18}$/);
.should('match', /\d{0,3}(,\d{3})*\.\d{2}$/);
});
});
@@ -197,18 +197,14 @@ context(
{ tags: '@smoke' },
function () {
cy.get(walletContainer).within(() => {
cy.get(currencyValue)
.should('be.visible')
.and('have.text', `0.000000000000000000`);
cy.get(currencyValue).should('be.visible').and('have.text', `0.00`);
});
}
);
it('should have Unstaked value visible', { tags: '@smoke' }, function () {
cy.get(walletContainer).within(() => {
cy.get(vegaUnstaked)
.should('be.visible')
.and('have.text', `0.000000000000000000`);
cy.get(vegaUnstaked).should('be.visible').and('have.text', `0.00`);
});
});
@@ -331,7 +327,7 @@ context(
.contains(currency.id)
.parent()
.siblings()
.within(() => cy.contains_exactly('10.00000').should('be.visible'));
.within(() => cy.contains_exactly('10.00').should('be.visible'));
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
@@ -351,7 +347,7 @@ context(
.contains(currency.id)
.parent()
.siblings()
.within(() => cy.contains_exactly('6.00000').should('be.visible'));
.within(() => cy.contains_exactly('6.00').should('be.visible'));
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
@@ -371,7 +367,7 @@ context(
.contains(currency.id)
.parent()
.siblings()
.within(() => cy.contains_exactly('8.00000').should('be.visible'));
.within(() => cy.contains_exactly('8.00').should('be.visible'));
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
@@ -391,7 +387,7 @@ context(
.contains(currency.id)
.parent()
.siblings()
.within(() => cy.contains_exactly('2.00000').should('be.visible'));
.within(() => cy.contains_exactly('2.00').should('be.visible'));
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
@@ -208,7 +208,7 @@ Cypress.Commands.add(
if (parseFloat(unstakedBalance) != parseFloat(tokenAmount)) {
cy.vega_wallet_teardown();
cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
'0.000000000000000000',
'0.00',
txTimeout
);
cy.staking_page_associate_tokens(tokenAmount);
@@ -93,19 +93,24 @@ Cypress.Commands.add('faucet_asset', function (assetEthAddress) {
Cypress.Commands.add('vega_wallet_teardown', function () {
cy.get(vegaWalletContainer).within(() => {
cy.get(vegaWalletAssociatedBalance)
.first()
.invoke('text')
.then((balance) => {
if (balance != '0.000000000000000000') {
if (balance != '0.00') {
cy.vega_wallet_teardown_vesting(this.vestingContract);
cy.vega_wallet_teardown_staking(this.stakingBridgeContract);
}
});
cy.get('[data-test-id="associated-amount"]', { timeout: 30000 }).should(
'contain.text',
'0.00'
);
});
cy.get(vegaWalletContainer).within(() => {
cy.get(vegaWalletAssociatedBalance, { timeout: transactionTimeout }).should(
'contain',
'0.000000000000000000',
'0.00',
{ timeout: transactionTimeout }
);
});
+1 -1
View File
@@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV=STAGNET3
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false
+2 -2
View File
@@ -1,8 +1,8 @@
# App configuration variables
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_EXPLORER_URL=https://staging3.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
+2
View File
@@ -29,6 +29,7 @@ import {
import { createConnectors } from './lib/web3-connectors';
import { ENV } from './config/env';
import type { InMemoryCacheConfig } from '@apollo/client';
import { WithdrawalDialog } from '@vegaprotocol/withdraws';
const cache: InMemoryCacheConfig = {
typePolicies: {
@@ -97,6 +98,7 @@ const Web3Container = ({
</div>
<VegaWalletDialogs />
<TransactionModal />
<WithdrawalDialog />
</>
</BalanceManager>
</AppLoader>

Some files were not shown because too many files have changed in this diff Show More