Compare commits

..
Author SHA1 Message Date
Edd 35a52f00da chore(explorer): add missing tests 2024-02-01 15:57:22 +00:00
Edd 567345e7aa feat(explorer): extend proposal summary to summarise batch items 2024-02-01 15:44:11 +00:00
Edd 5ba4d57f1f chore(explorer): add batch to filter and fix preview 2024-02-01 11:29:34 +00:00
Edd 7563c92df2 feat(explorer): quick hack batch proposal 2024-02-01 10:47:32 +00:00
Art 2002731c52 feat(trading): gas fee estimation for withdraw transaction (#5668) 2024-02-01 09:07:13 +01:00
a49139f127 fix(trading): closed markets filter (#5691) (#5697)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Edd <edd@vega.xyz>
2024-01-31 14:34:43 +00:00
Edd e216b23472 feat(explorer): updatemarginmode tx view (#5690) 2024-01-31 14:26:35 +00:00
e52ae97233 feat(trading): competitions (#5621)
Co-authored-by: asiaznik <artur@vegaprotocol.io>
Co-authored-by: Ben <ben@vega.xyz>
2024-01-31 14:21:29 +00:00
1780f6fa7f feat(trading): margin estimate update (#5664)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
Co-authored-by: daro-maj <119658839+daro-maj@users.noreply.github.com>
2024-01-31 14:05:30 +00:00
Ben 8b91592b93 chore(trading): update to preview 7 binaries (#5689) 2024-01-31 12:42:29 +01:00
m.ray 508274268d fix(trading): show user inactive lose streak in remaining epochs (#5667) 2024-01-31 10:54:16 +00:00
Edd 2a40d9ec4d feat(explorer): support for more external chains (#5687) 2024-01-31 10:36:58 +00:00
Art efb746f373 fix(candles-chart): ignore candles from before market open date (#5678) 2024-01-30 14:32:55 +00:00
Ben 6d2f367987 chore(trading): update vega binaries to v0.74.0-preview.6 (#5686) 2024-01-30 13:31:06 +00:00
m.ray 6b7bbc9c94 fix(trading): market id use text-xs in key details (#5684) 2024-01-29 15:02:03 +00:00
Art 9153677a33 fix(markets): key details panel crashing (#5683) 2024-01-29 13:22:17 +00:00
m.ray cff1818940 chore(trading, governance, explorer): add liquidation strategy to market info (#5642) 2024-01-29 13:13:19 +01:00
Zohar Etzioni d05dd6e4cb Merge pull request #5669 from vegaprotocol/feat/use-camelCase-marketId-in-updateMarginMode-tx
feat(trading): use camel case marketId in updateMarginMode tx
2024-01-25 14:46:54 +00:00
Bartłomiej Głownia 4ef789e00a feat(trading): use camel case marketId in updateMarginMode tx 2024-01-25 15:09:09 +01:00
m.ray 0bd13a5f7b fix(trading): adjust full screen for mobile dialogs (#5666) 2024-01-25 13:32:14 +00:00
67d38ff03e fix(trading): error guards not working when poll interval is supplied (#5661)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2024-01-25 07:59:40 +00:00
Matthew Russell 6aea10c27b chore(trading, governance, explorer): 0.74.0 type regen (#5619) 2024-01-24 22:34:11 +00:00
Edd 27a9d5f247 fix(explorer): update tx navigation for 0.74.0 (#5662) 2024-01-24 16:31:56 +00:00
261f32aa5b feat(trading): margin mode selector (#5660)
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2024-01-24 13:17:22 +00:00
Edd 053775bef6 fix(governance): handle an expected error (#5653) 2024-01-24 11:41:40 +00:00
Matthew Russellandbwallacee 0660eda334 chore(trading): store all chart state (#5627)
Co-authored-by: bwallacee <ben@vega.xyz>
2024-01-24 10:21:33 +00:00
Matthew Russell f22a3bc2d2 Revert "feat(trading): margin mode selector (#5575)"
This reverts commit fde77ebccb.
2024-01-23 08:46:16 -08:00
Bartłomiej GłowniaandDariusz Majcherczyk fde77ebccb feat(trading): margin mode selector (#5575)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2024-01-23 16:19:49 +00:00
e309669736 fix(trading): typo translation full featured link (#5659)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Edd <edd@vega.xyz>
2024-01-23 16:05:51 +00:00
b1621d1191 chore(trading): fix monitoring bounds (#5655) (#5657)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Edd <edd@vega.xyz>
2024-01-23 15:45:05 +00:00
ArtandDexter Edwards 39907f07db feat(wallet): new browser wallet connection model (#5572)
Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com>
2024-01-23 15:32:23 +00:00
3dab5f3d9b chore(trading): merge main back in develop (#5654)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Edd <edd@vega.xyz>
2024-01-23 14:57:20 +00:00
Edd 3cf9ae7582 fix(governance): handle null validator scores properly (#5459) 2024-01-23 14:46:19 +00:00
Ben 557894e2ef chore(trading): turn off parallel (#5650) 2024-01-23 14:43:51 +00:00
m.rayandbwallacee baf9875c69 feat(trading): filter out suspended transfers (#5640)
Co-authored-by: bwallacee <ben@vega.xyz>
2024-01-23 09:38:09 +00:00
Art 51199b02ce feat(governance): update market proposal header with copy and open buttons (#5648) 2024-01-23 10:13:56 +01:00
m.ray bb826c88f0 fix(trading): set trading view as default (#5632) 2024-01-22 16:09:18 +00:00
Edd 0da20b750f feat(explorer): referral and team transaction support (#5623) 2024-01-22 10:53:53 +00:00
m.rayandDariusz Majcherczyk e16c447564 chore(trading): remove quadratic slippage factor (#5641)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2024-01-22 10:17:16 +00:00
Bartłomiej GłowniaandDariusz Majcherczyk a2170d27d6 feat(ui-toolkit): update slider design (#5645)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2024-01-22 08:30:57 +01:00
Ben 00d840b7b3 chore(trading): delete and move some tests to jest (#5633) 2024-01-19 14:15:53 +00:00
Ben 2a4a05630f chore(trading): fix skipped tests (#5638) 2024-01-19 08:20:52 +00:00
Ben 97f1f40f2c chore(trading): remove waits and tests (#5637) 2024-01-18 13:20:58 +00:00
Bartłomiej GłowniaandMatthew Russell a8e6963521 feat(deposits): if wrong network dont show the form and prompt switching to the correct network (#5571)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2024-01-18 10:41:19 +01:00
m.ray a2bffa1dfd fix(trading): alphabetically order translations in trading.json (#5635) 2024-01-17 21:28:20 +00:00
Ben 9253e8067a chore(trading): market-sim branch parralel fix (#5630) 2024-01-17 14:44:11 +00:00
Bartłomiej Głownia 58972f0a11 feat(ui-toolkit): add leverage slider component (#5594) 2024-01-17 13:46:11 +00:00
Ben a3c55fd7c3 chore(trading): update vega-market-sim to use to 0.74.0-preview.2 (#5603) 2024-01-17 12:19:52 +00:00
Matthew Russell c63cba1071 chore(trading): enable trading view on mainnet (#5628) 2024-01-16 18:16:58 +00:00
m.ray bc9d87fe30 chore(trading): clean up triggering ratio (#5604) 2024-01-16 18:10:32 +01:00
m.ray 6a21862378 fix(trading): use No trading instead of Trading terminated (#5624) 2024-01-16 18:30:42 +02:00
Ben 0fb4348e9c chore(trading): upload market-sim logs (#5622) 2024-01-15 20:56:52 +00:00
m.ray b751bcf17d feat(trading): mobile responsiveness tweaks (#5613) 2024-01-15 15:26:13 +00:00
m.ray d32f27fcb1 feat(trading): mobile responsiveness - market selector (#5582) 2024-01-11 11:23:48 +00:00
m.ray d05cd6a2ed fix(trading): tiny scroll for rewards (#5586) 2024-01-10 15:49:58 +00:00
m.ray c003e5fa30 fix(trading): liquidity table improve readability and remove grouping (#5598) 2024-01-10 15:49:35 +00:00
Ben f62d3289ab chore(trading): retry on http error (#5601) 2024-01-10 15:44:01 +00:00
Ben a3d3d18c5c chore(trading): fix price monitoring test (#5600) 2024-01-10 14:56:17 +00:00
77ca101781 chore(trading): merge main back in develop (#5597)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Edd <edd@vega.xyz>
2024-01-10 10:31:15 +00:00
Ben d238c37d0c chore(trading): vesting test (#5595) 2024-01-10 10:07:59 +00:00
Edd 79feb485f6 fix(governance): improve error message for configuration error (#5589) 2024-01-09 17:21:56 +00:00
Ben 6aa5c3b6e3 chore(trading): rewards page e2e (#5578) 2024-01-09 15:54:40 +00:00
Ben 82abc13fda chore(trading): skip test due to issue (#5583) 2024-01-08 16:16:03 +00:00
Edd 933f07cddf fix(explorer): minor tidyup of deterministic order view (#5573) 2024-01-08 13:25:03 +00:00
Matthew Russell c8067669c2 fix(trading): ensure fees queries always fetch on mount and poll (#5566) 2024-01-05 12:43:30 +00:00
78f5a9c520 feat(trading): activity streaks, reward hoarder bonus and active rewards (#5491)
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: bwallacee <ben@vega.xyz>
2024-01-05 11:16:59 +00:00
Ben 462066959d chore(trading): update vega (#5563) 2024-01-03 12:00:00 +00:00
daro-maj f12f5ab961 chore(trading): fix volume issue for market selector tests (#5564) 2024-01-03 12:04:49 +01:00
98b2460d8b fix(trading): mobile friendly referral and fees views (#5530)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2024-01-02 15:50:04 +00:00
Matthew Russell 67c182f3de chore(trading-view): minor tv chart tweaks (#5545) 2024-01-02 13:20:01 +00:00
68e0009ab0 feat(trading,markets,proposals): market banners (#5494)
Co-authored-by: bwallacee <ben@vega.xyz>
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2024-01-02 11:04:43 +00:00
Bartłomiej Głownia ad74b12908 feat(trading): do not show error message if there is no faucet tx error (#5539) 2024-01-02 10:19:10 +01:00
Matthew Russell 7fff33e493 feat(trading): competition feature flag and team page (#5549) 2023-12-29 15:50:51 +00:00
daro-maj e7cb2c8276 chore(trading): fix fees tests (#5548) 2023-12-29 15:25:33 +00:00
4adaeea40a feat(trading): pane settings view (#5509)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-12-28 12:33:18 +00:00
Matthew Russell d47d894147 fix(deal-ticket): stray curly in stop order deal ticket (#5547) 2023-12-28 12:27:56 +00:00
Bartłomiej Głownia 515932d401 fix(trading): use correct interpolation prefix in market info label (#5537) 2023-12-27 18:47:19 +00:00
daro-maj 723ff2805d chore(trading): check e2e tests issue (#5544) 2023-12-27 14:07:27 +01:00
Ben 424cced4be chore(trading): vegaservice import (#5536) 2023-12-27 08:17:20 +00:00
Daniel b2c7ee82c5 feat(ci): validators testnet deployment (#5541) 2023-12-22 18:05:31 +00:00
m.rayandDaniel 4cc63be4f9 chore(trading): update validator testnet pipelines (#5543)
Co-authored-by: Daniel <daniel.1302@gmail.com>
2023-12-22 18:03:45 +00:00
Jeremy Letang 9fbb7a13e6 Merge pull request #5526 from vegaprotocol/5409-funding-countdown
feat(trading): poll market info, and last fundingPeriod
2023-12-22 15:21:40 +01:00
Dariusz Majcherczyk 1874095222 feat: skip test 2023-12-22 14:36:38 +01:00
Dariusz Majcherczyk e459e92127 feat: update sim version 2023-12-22 13:58:20 +01:00
Bartłomiej Głownia 4dd65b4923 feat: rollback using market.data as a source of current fundingPeriod startTime 2023-12-22 12:01:32 +01:00
Bartłomiej Głownia 5d792d2458 feat: pool market info, use market data as source of current funding period startTime 2023-12-21 16:42:25 +00:00
Ben 59b2f75b13 chore(trading): update market-sim (#5535) 2023-12-21 13:51:34 +00:00
ArtandMatthew Russell 95775679ca fix(trading): reward pot total value (#5531)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-12-21 13:41:37 +00:00
m.ray 4cffee29f8 chore(trading): rollback current traded volume change (#5527) 2023-12-21 10:38:09 +00:00
Edd bd70b0c233 fix(governance): fix lp vote counts (#5521) 2023-12-21 09:30:23 +00:00
Ben 145792f216 chore(trading): static vega port trading e2e (#5520) 2023-12-20 15:49:10 +00:00
m.ray 10add7c236 fix(trading): update copy on tooltips fills update (#5512) 2023-12-20 08:12:35 +00:00
Edd 362a2031c7 fix(explorer): pass through tendermint error responses from usefetch (#5507) 2023-12-20 08:08:56 +00:00
Edd 5aaeb87059 feat(governance): enable snaps (#5511) 2023-12-19 18:38:49 +00:00
Matthew Russell d240dddab5 fix(trading): alpha lyrae font (#5518) 2023-12-19 16:52:56 +00:00
Ben 0af1d0ba82 chore(trading): fees e2e tests (#5496) 2023-12-19 12:22:15 +00:00
Bartłomiej Głownia 665ab6693a feat(trading): show commission earned on referrer stats from last 30 days (#5467) 2023-12-18 15:33:40 +01:00
Ben 902ee2696c chore(trading): black formatting and removed double fixtures (#5506) 2023-12-18 10:54:40 +00:00
Art 3beeb0140c feat(wallet): disconnect if wallet unreachable (#5501) 2023-12-18 10:39:18 +00:00
m.ray 4b208e90bf fix(trading): internal timestamp date unix formatting (#5505) 2023-12-14 15:10:17 +00:00
Bartłomiej Głownia ec837854cf chore(trading): avoid portfolio and market page re-rendering on sidebar view change (#5499) 2023-12-14 14:12:19 +00:00
Bartłomiej Głownia 8b94a75ba4 feat(positions): improve tooltips (#5481) 2023-12-13 14:36:57 +00:00
Ben 08c57b6759 chore(trading): run against local console (#5500) 2023-12-13 12:46:16 +00:00
Ben bb2184498f chore(trading): update vega version (#5498) 2023-12-13 11:16:52 +00:00
Bartłomiej Głownia 8b07ce3024 fix(trading): fix tabs covered by orderbook splash (#5497) 2023-12-13 09:10:54 +00:00
Bartłomiej Głownia 8a110584dd feat(trading): improve desposit and withraw asset selection (#5493) 2023-12-13 08:47:22 +00:00
Bartłomiej Głownia b82615a3d8 fix(trading): do not add candles if they are older than requested date range (#5484) 2023-12-13 08:06:02 +00:00
Matthew Russell f178b85846 feat(trading): trading view (#5348) 2023-12-12 17:33:41 -08:00
Bartłomiej Głownia 0796f2b31f feat(environment): users controlled feature flags (#5425) 2023-12-12 13:53:20 +01:00
dalebennett1992 67be224138 Merge pull request #5492 from vegaprotocol/test/referrals2
test: add referrals tests
2023-12-12 10:33:57 +00:00
dalebennett1992 51c426ef4b test: test ids 2023-12-12 10:16:47 +00:00
dalebennett1992 fa28d31ef3 test: add referrals tests 2023-12-12 10:15:20 +00:00
m.ray 201a586b05 chore(trading): enable close position (#5490) 2023-12-11 15:51:22 +00:00
m.ray 7d96d9bcd1 chore(trading): update env trading (#5478) 2023-12-08 15:44:55 +00:00
Art 345be81142 fix(trading): rewordings in referrals, qusd tooltip, onboarding (#5477) 2023-12-08 14:48:12 +00:00
Matthew Russell 2221e9faca fix(trading): referrals page final commission value and onboarding dialog (#5474) 2023-12-08 09:14:59 +00:00
Ben 7c0139e107 chore(trading): e2e test fix (#5466) 2023-12-07 11:12:56 +00:00
Witoldandbwallacee a157ff1e05 fix(trading): amend formula for max leverage calc (#5462)
Co-authored-by: bwallacee <ben@vega.xyz>
2023-12-06 09:58:59 -08:00
Art 2e9fa0c52e chore(trading): referrals text and ui tweaks, bug fixes (#5408) 2023-12-06 17:51:39 +00:00
Ben c0790c1e93 chore(trading): update market-sim (#5463) 2023-12-06 16:31:44 +00:00
Bartłomiej Głownia 13c1044f8e chore(i18n): sync json translation files with locize (#5444) 2023-12-06 14:58:17 +00:00
Matthew Russell cf9f313e4c feat(trading): error boundaries for panes, sidebars, pages (#5438) 2023-12-06 13:31:40 +00:00
Art f56d34fe6e fix(environment): node switcher on mobile (#5455) 2023-12-06 13:31:08 +00:00
m.rayandcandida-d 1379366caa chore(trading): update LP table tooltips (#5442)
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
2023-12-06 13:30:22 +00:00
Art 8958c12fe3 fix(governance): markdown link styling, referral details type error, contracts provider error (#5460) 2023-12-06 14:18:44 +01:00
m.ray fef13874db chore(trading): update generic data provider (#5431) 2023-12-06 12:32:51 +00:00
Edd 40f02ecf89 feat(explorer): add type details to orders in tx list and details (#5432) 2023-12-06 10:45:35 +00:00
Bartłomiej Głownia 41cd6b1455 fix(trading): avoid funding LineChart recreate instance on FundingContainer re-render (#5454) 2023-12-06 10:37:44 +00:00
m.rayandMatthew Russell 3cd393dac0 fix(trading): rewards page updates (#5437)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-12-05 20:05:45 -08:00
Matthew Russell a52e60d6a2 Merge pull request #5453 from vegaprotocol/chore/sync-main
chore(trading): sync main
2023-12-05 12:35:31 -08:00
Matthew Russell bc13f1b359 Merge branch 'main' into chore/sync-main 2023-12-05 12:01:32 -08:00
m.ray eb81f4ae44 fix(trading): required vol shown if current is zero (#5449) 2023-12-05 11:36:25 -08:00
m.rayandMatthew Russell 51ab02a2e2 fix(trading): missing party ID when there is no SLA data (#5446)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-12-05 11:36:02 -08:00
Ben ffada1b93d feat(trading): auction uncross fees test (#5445) 2023-12-05 15:33:03 +00:00
BenandMatthew Russell 9dda3f712b chore(trading): market python tests to jest (#5346)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-12-05 10:29:01 +00:00
m.ray df20dbeee0 chore(trading): revert moving rewards container to portfolio (#5441) 2023-12-05 10:19:42 +00:00
m.ray cdfd8a2d00 fix(trading): revert disabling sortable as it breaks view (#5435) 2023-12-04 18:12:13 +00:00
m.ray 1e5c523bc4 chore(trading): disable trades table sorting (#5423) 2023-12-04 15:40:32 +00:00
m.ray 37cd69ba6e chore(trading): move rewards to portfolio part 1 (#5402) 2023-12-04 15:40:14 +00:00
Ben 2c11045dd9 feat(trading): perp market tests (#5426) 2023-12-04 14:29:00 +00:00
ArtandMadalina Raicu 9aef41a119 fix(governance): update asset proposal (#5417)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-12-04 15:20:07 +01:00
m.ray 80ab8821d0 fix(trading): live time fraction zero redundant check (#5420) 2023-12-02 11:36:58 +00:00
m.ray 8a3657a9b9 fix(trading): live time fraction zero (#5419) 2023-12-02 11:06:20 +00:00
Art 7100b0e9fc chore(accounts): no assets avaiable in transfer form (#5358) 2023-12-01 17:05:22 +00:00
614a83b7d6 chore(trading): merge main back in develop (fees discounts, discount stats from prev epoch) (#5415)
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
Co-authored-by: asiaznik <artur@vegaprotocol.io>
2023-12-01 17:03:41 +00:00
m.ray 3dc77b0eff chore(trading): add close position button back to console (#5407) 2023-12-01 16:38:32 +00:00
m.ray a59f7dfd29 fix(trading): fills fees maker discounts (#5406) 2023-12-01 16:34:22 +00:00
Bartłomiej Głowniaandasiaznik 61471228aa fix(trading): use discount stats only from previous epoch (#5411)
Co-authored-by: asiaznik <artur@vegaprotocol.io>
2023-12-01 16:34:05 +00:00
Art 127e784ceb chore(trading): don't redirect to inactive markets (#5359) 2023-12-01 14:42:26 +01:00
m.ray 70d748fb15 fix(trading): fills fees fixes for maker (#5405) 2023-12-01 11:23:04 +00:00
EddandMadalina Raicu e06f4818fc feat(explorer): add signature viewer (#5264)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-11-30 11:54:18 +00:00
Bartłomiej Głownia 8182da3b31 feat(deal-ticket): fix postOnly mapping in mapFormValuesToOrderSubmission (#5375) 2023-11-30 11:25:25 +01:00
Ben c8c56307bb chore(trading): update vega version (#5396) 2023-11-30 09:52:05 +00:00
Ben a8cd7f157f chore(trading): migrate cypress tests to python (#5367) 2023-11-30 09:42:57 +00:00
Bartłomiej Głownia 4f18caa486 feat(trading): upgrade i18n, fix plurals (#5331) 2023-11-30 07:31:44 +00:00
Matthew Russell 5c7c626bbc Merge pull request #5393 from vegaprotocol/chore/sync-main
chore(trading, datagrid, liquidity, proposals, ui-toolkit): sync main
2023-11-29 18:08:50 -08:00
Matthew Russell e4c4c20631 fix: duplicate props in ag-grid-themed 2023-11-29 14:09:08 -08:00
Matthew Russell 0697302d07 Merge branch 'main' into chore/sync-main 2023-11-29 14:06:45 -08:00
ArtandMadalina Raicu 2d926c0ce0 fix(governance): sensible vote numbers (#5384)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-11-29 10:38:41 -08:00
Art f57d6a7c7b fix(trading): missing volume discount program issue, inverted tiers (#5378) 2023-11-29 17:23:14 +00:00
m.ray 15f905046f fix(trading): fees accrued tooltip (#5387) 2023-11-29 17:17:44 +00:00
Bartłomiej Głownia 4f7918f64e feat(trading): remove proposal warning from market header (#5385) 2023-11-29 17:05:53 +00:00
Bartłomiej Głownia 52ab0562b0 feat(trading): refactor ledger export form validation (#5379) 2023-11-29 15:27:00 +00:00
m.ray 4e2b0d1b1d fix(trading): fix ag-grid transparent filters (#5377) 2023-11-29 15:24:37 +00:00
m.ray 0b0bcad9b3 fix(trading): ag-grid compactness adjustment (#5382) 2023-11-29 14:29:02 +00:00
Bartłomiej GłowniaandMatthew Russell bcf17bb34e feat(trading): i18n language switcher (#5320)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-29 15:16:17 +01:00
Bartłomiej Głownia a2b9b0da05 feat(deal-ticket): enhance for fee discounts (#5353) 2023-11-29 12:59:42 +00:00
Bartłomiej Głownia 7588d0cd11 feat(trading): refactor ledger export form validation (#5362) 2023-11-29 13:28:31 +01:00
m.ray 5ee1748495 fix(trading): ag-grid styling updates and filter fixes (#5368) 2023-11-28 22:13:12 +00:00
Art 73a118978f feat(trading): referral code eligibility (#5325) 2023-11-28 16:08:21 +01:00
m.ray eac26c1966 fix(trading): empty connect wallet dialog (#5356) 2023-11-28 14:43:31 +00:00
Matthew Russell d615587564 Merge pull request #5361 from vegaprotocol/chore/backmerge-main
chore(trading): back merge main
2023-11-27 22:33:19 -08:00
Matthew Russell ba4ce1ce88 fix: botched merge in gitignore 2023-11-27 22:06:46 -08:00
Matthew Russell 3bbacc1aa0 fix: fix broken test after removal of formatting 2023-11-27 21:22:30 -08:00
Matthew Russell de5371435d Merge branch 'main' into chore/backmerge-main 2023-11-27 20:08:08 -08:00
m.rayandMatthew Russell 12cb5e10b6 chore(trading): merge main in develop (#5352)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-27 15:49:26 -08:00
Art ee2909cc84 fix(wallet): empty connect dialog (#5354) 2023-11-27 16:15:18 +00:00
Bartłomiej Głownia 068d6abf1b feat(trading): show percentage sign on y axis in funding rate chart (#5342) 2023-11-27 13:39:20 +00:00
m.ray e5d4d2b0b8 chore(trading): temporarily disable close position (#5350) 2023-11-27 10:48:29 +00:00
m.ray d4e801cfc6 feat(trading): reset console to default (#5344) 2023-11-27 10:42:47 +00:00
Bartłomiej Głownia 964deb2f23 feat(trading): update title on rewards and fees pages (#5347) 2023-11-27 08:18:59 +00:00
Art 6669125dd3 feat(trading): copy apply referral link from code tile (#5338) 2023-11-24 10:20:37 +00:00
m.ray 129b6c4e89 feat(trading): referral initial state when no sets are available (#5294) 2023-11-23 17:08:26 +00:00
Ben ca418cabfe chore(trading): migrate python tests to jest (#5339) 2023-11-23 15:56:29 +00:00
Ben 192af844c4 chore(trading): fix change keys edge case (#5337) 2023-11-23 09:12:45 +00:00
Ben 6a841f226a chore(ci): reduce number of runners for python tests (#5333) 2023-11-22 16:00:29 +00:00
Ben 76426baa2a chore(ci): create traces dir (#5327) 2023-11-22 15:52:59 +00:00
Ben 6fdac2419c chore(trading): move python stop order tests to jest (#5329) 2023-11-22 15:10:19 +00:00
Art 87807d2088 chore(governance): sensible vote numbers (#5332) 2023-11-22 15:30:16 +01:00
m.rayandbwallacee a5f2533a66 feat(trading): market list snags and disable column removal (#5324)
Co-authored-by: bwallacee <ben@vega.xyz>
2023-11-22 13:51:39 +00:00
Ben 1e9251c9c0 chore(trading): python tests update vega version (#5313) 2023-11-22 09:39:40 +00:00
Ben 2a27e124d7 chore(ci): increase number of tests in parallel (#5322) 2023-11-22 08:17:22 +00:00
Ben 4ee85720ab chore(ci): specific ganache image (#5321) 2023-11-22 08:02:47 +00:00
BenandBartłomiej Głownia a19da4c408 chore(trading): cypress to python tests (#5319)
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
2023-11-21 14:44:41 +00:00
BenandMatthew Russell 65ad4fffda chore(trading): migrate LP cypress tests (#5286)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-21 14:36:02 +00:00
Bartłomiej GłowniaandMatthew Russell 11317cdb2e feat(withdraws): use i18next (#5285)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-21 13:49:10 +00:00
Bartłomiej GłowniaandMatthew Russell c98870f27d feat(wallet): use i18next (#5299)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-21 13:48:53 +00:00
Bartłomiej Głowniaandbwallacee c0c56e4c48 feat(trading): fix markets i18n namespace, add missing label, preload all namespaces (#5312)
Co-authored-by: bwallacee <ben@vega.xyz>
2023-11-21 12:08:33 +01:00
Matthew Russell d9dc43b359 chore(deal-ticket): re-enable margin estimates for perps (#5317) 2023-11-20 13:57:18 -08:00
m.rayandMatthew Russell 06a6fe6d67 fix(accounts): remove account balance formatting in transfer form (#5315)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-20 13:07:17 -08:00
Bartłomiej GłowniaandMatthew Russell a9ca215276 feat(proposals): use i18next (#5284)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-19 21:49:39 -08:00
Bartłomiej GłowniaandMatthew Russell 61a9eb2f5c feat(ui-toolkit): use i18next (#5289)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-19 15:27:52 -08:00
Bartłomiej GłowniaandMatthew Russell bb47747501 feat(utils): use i18next (#5269)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-19 14:00:45 -08:00
Bartłomiej GłowniaandMatthew Russell 5827b87f89 feat(trades): use i18next (#5268)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-19 13:51:08 -08:00
Bartłomiej Głownia 19b95832c4 feat(market-depth): use i18next (#5267) 2023-11-19 13:13:03 -08:00
Bartłomiej GłowniaandMatthew Russell 48e4ab53a1 feat(orders): use i18next (#5263)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-19 13:12:35 -08:00
Bartłomiej Głownia cefcff040f feat(positions): use i18next (#5266) 2023-11-17 19:49:19 -08:00
Bartłomiej Głownia c3ef639daf feat(web3): use i18next (#5256) 2023-11-17 16:44:30 -08:00
Bartłomiej Głownia b6052bc3e5 feat(markets): use i18next (#5255) 2023-11-17 12:01:18 -08:00
Bartłomiej Głownia 6e8894936e feat(ledger): use i18next (#5248) 2023-11-17 11:55:10 -08:00
Bartłomiej Głownia 66f55855ae feat(liquidity): use i18next (#5247) 2023-11-17 11:54:17 -08:00
Matthew Russell 5725b824ad Merge pull request #5309 from vegaprotocol/chore/sync-main
chore(governance,trading): sync with mainnet fixes
2023-11-17 11:51:03 -08:00
Matthew Russell 9344a2abc0 fix: no t function 2023-11-17 11:10:18 -08:00
Matthew Russell fae66ca4ce Merge branch 'main' into chore/sync-main 2023-11-17 10:56:19 -08:00
Matthew Russell 4b7338ed94 chore(deal-ticket,markets): dont show margin estimate for perps (#5305) 2023-11-17 10:33:24 -08:00
Edd 2983c6c6ba feat(governance): enable volume discount update view (#5304) (#5307) 2023-11-17 10:25:30 -08:00
Edd 31524ac7a7 feat(governance): enable volume discount update view (#5304) 2023-11-17 17:29:42 +00:00
Matthew Russellandasiaznik 70f42c1c7e fix(trading): fees page fixes for mainnet (#5303)
Co-authored-by: asiaznik <artur@vegaprotocol.io>
2023-11-17 08:53:21 -08:00
m.ray 2304ce9763 fix(proposals): perpetual proposed markets (#5290) 2023-11-17 12:00:19 +00:00
m.ray 79a16b8562 fix(trading): show deal ticket in sidebar by default (#5292) 2023-11-16 09:08:20 -08:00
Ben ea3e5a7651 chore(trading): update vega-market-sim (#5288) 2023-11-16 15:48:36 +00:00
Ben b062339682 chore(trading): delete duplicate cypress tests (#5287) 2023-11-16 14:22:24 +00:00
Ben 824bcf89bd feat(trading): perps markets in trading python tests (#5283) 2023-11-16 13:16:36 +00:00
Ben f315917094 chore(trading): remove some redundant capsule tests (#5281) 2023-11-16 13:14:47 +00:00
Matthew Russell 5661b74082 fix(trading): do not use stakeToCcyVolume to format fees value (#5280) 2023-11-16 09:34:38 +00:00
Ben 8e898cfd78 chore(trading): remove wait for graphql (#5265) 2023-11-16 08:11:48 +00:00
Bartłomiej GłowniaandMatthew Russell f377e07996 feat(trading): use i18next (#5238)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-15 19:10:39 -08:00
Matthew Russell 090d340364 feat(trading): rewards page (#5222) 2023-11-15 13:46:19 -08:00
Matthew Russell 6d32fa7362 chore(ci): remove unused netlify configs (#5278) 2023-11-15 13:40:26 -08:00
ArtandMadalina Raicu 1a7682c3c9 chore(governance): vesting balances (#5237)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-11-15 18:15:05 +00:00
Ben 3294c0cabe chore(trading): fix tests from i18n (#5259) 2023-11-15 13:45:36 +00:00
Edd c10084d441 feat(explorer): simplify party accounts page (#5240) 2023-11-15 11:15:25 +00:00
Edd 96658134ee fix(explorer): improve chain event tx view for contract calls (#5243) 2023-11-15 11:15:07 +00:00
Bartłomiej GłowniaandMatthew Russell a070504d2e feat(trading): i18n (#5126)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-14 21:10:06 -08:00
Matthew Russell f891caf08b chore(trading,governance,explorer): disable prettier tailwind plugin (#5258) 2023-11-14 18:09:29 -08:00
Matthew Russell 69bdc637e5 chore(trading,governance,explorer): disable prettier tailwind plugin 2023-11-14 17:21:09 -08:00
Matthew Russell 78add88014 chore(trading,governance,explorer): comply with eslint type import rules (#5257) 2023-11-14 16:43:36 -08:00
02c425f304 chore(trading): add playwright and market sim testing framework (#5199)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: dalebennett1992 <dalebennett1992@hotmail.co.uk>
2023-11-14 10:05:07 -08:00
m.ray 06769f25cf feat(trading): referral preview update (#5251) 2023-11-14 15:31:00 +01:00
Matthew RussellandEdd b3014bb98a chore(trading,governance,explorer): nx migration to latest (#5246)
Co-authored-by: Edd <edd@vega.xyz>
2023-11-14 15:25:29 +01:00
Matthew Russell 132f2e4b2b chore(trading): add git hash and tag into settings view (#5207) 2023-11-13 21:17:17 -08:00
m.ray 374890dc08 fix(trading): fix percentage formatter rounding in liquidity table (#… (#5254) 2023-11-13 16:20:48 +00:00
m.ray 22703d937e fix(trading): fix percentage formatter rounding in liquidity table (#5250) 2023-11-13 16:14:18 +00:00
m.ray 7f95ba577e fix(trading): display funding rate when market in monitoring auction (#5218) 2023-11-10 13:01:24 +00:00
m.ray 2f7e53e282 feat(trading): close position stopped and IOC behaviour update (#5211) 2023-11-09 22:31:18 +00:00
Matthew Russell 568dcd5305 fix(trading,governance,explorer): update codeowners 2023-11-09 12:43:50 -08:00
Matthew Russell 9605b0e7fa chore(trading,governance,explorer): add specific rules for qa reviews 2023-11-09 12:37:32 -08:00
Art 0776332ba7 fix(trading): fees page issues (#5217) 2023-11-09 16:50:50 +01:00
Matthew RussellandMadalina Raicu f780013846 feat(accounts): transfer form improvements to handle transfers from vesting accounts (#5212)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-11-08 23:52:30 -08:00
Ben 73f37c2477 chore(ci): fix prepare dist (#5214) 2023-11-08 09:43:36 +00:00
Art 607ad06971 fix(environment): missing block height in node switcher (#5210) 2023-11-08 09:47:23 +01:00
Matthew Russell 7aee2a3a7b chore(candles-chart): update pennant package so chart draws at 60 fps (#5213) 2023-11-07 21:49:09 -08:00
Bartłomiej Głownia 1fdf519780 feat(trading): fee discounts tweaks (#5205) 2023-11-07 16:15:54 +01:00
ArtandMatthew Russell 9233778e85 feat(governance,accounts): vesting and vested accound in wallet card, fix transfer form to account (#5206)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-11-06 12:42:42 -08:00
m.ray 7a91f48bcb fix(trading): update LP table on Updating next epoch (#5204) 2023-11-06 15:47:08 +01:00
Edd b43ea0f60b feat(explorer): update liquidity submission view (#5187) 2023-11-03 15:52:27 +00:00
Matthew Russell 6e31fb03ae fix(accounts): fix key selection and validation, and add use max to transfers (#5184) 2023-11-03 15:12:40 +00:00
Matthew Russell d76fa13c5d chore(trading): fees page use window length in label (#5186) 2023-11-03 15:11:51 +00:00
Edd 89aeed6305 feat(explorer): new labels for proposals (#5190) 2023-11-03 14:58:56 +00:00
Edd 6e677084a3 feat(explorer): explorer oracle section rework (#5135) 2023-11-03 14:01:33 +00:00
m.ray 8069aa5ee7 fix(trading): hide funding tabs if market is not perp (#5181) 2023-11-03 10:49:31 +00:00
Matthew Russell b0169a0d39 fix(accounts): dont add vesting account balances to used total (#5182) 2023-11-02 16:56:56 -07:00
Edd 06cfd79415 feat(explorer): add timestamp to tx list (#5174) 2023-11-02 13:22:37 +00:00
Edd 443220283c fix(explorer): format new network params correctly (#5172) 2023-11-02 13:17:11 +00:00
Matthew Russell a642bf8ce4 chore(trading): misc changes to trades and transfer (#5175) 2023-11-01 15:57:38 -07:00
Matthew Russell 20233db706 fix(deal-ticket): fees breakdown rendering issues (#5173) 2023-11-01 13:32:51 -07:00
m.ray d4f50eb70c fix(trading): pagination limit for candles (#5169) 2023-11-01 12:21:36 -07:00
Matthew Russell e5d3f90d45 feat(trading): transfer to and from accounts on same key (#5161) 2023-11-01 11:11:17 +00:00
Bartłomiej Głownia 673c896e2f feat(deal-ticket): get discounts for estimation from previous epoch (#5163) 2023-11-01 10:09:56 +00:00
Matthew Russell deea63fa5e fix(trading): empty items loaded text (#5158) 2023-11-01 10:08:16 +00:00
Matthew Russell d31333538b chore(trading): ignore .next from lint (#5162) 2023-11-01 10:06:53 +00:00
Matthew Russell 4af9979a21 chore(trading): referrals stats tweaks (#5160) 2023-11-01 10:06:36 +00:00
m.ray 6421cf87c6 feat(trading): liquidity provision current and pending on update (#5152) 2023-10-31 11:24:18 +00:00
Matthew Russell 0ebfab64ff fix(ui-toolkit): sparkline appearing to go up when the price moved down (#5137) 2023-10-31 11:20:48 +00:00
Edd 142f08343b feat(governance): add update benefit tiers table (#5146) 2023-10-31 10:20:38 +00:00
m.ray 61aa45a9ed feat(trading): show fees paid across whole market (#5154) 2023-10-30 18:16:49 -07:00
Bartłomiej GłowniaandMatthew Russell 4c95db5fb3 feat(deal-ticket): calculate fees and discount base on volumeDiscountStats and referralSetStats (#5147)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-10-30 18:13:26 -07:00
ArtandMatthew Russell 3072b7824f fix(trading): referrer stats tiles (#5143)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-10-30 18:12:59 -07:00
Bartłomiej Głownia 0580e90171 feat(funding-payments): add load more button to the funding payments table (#5150) 2023-10-30 15:57:43 -07:00
Bartłomiej Głownia c440abc77d feat(trading): show full history of orders, fills and trades (#5105) 2023-10-27 14:21:26 +01:00
Matthew Russell fbafc726a4 feat(candles-chart): combine overlays and studies into indicators dropdown (#5129) 2023-10-27 14:21:14 +01:00
Joe Tsang dd1890d8c6 chore(cypress): fix failing assertions (#5132) 2023-10-27 14:21:02 +01:00
Matthew Russell c8e624eaba chore(trading): update fee factor with discount calculation (#5138) 2023-10-27 14:20:45 +01:00
Art cc6629ad27 fix(trading): referrals next tier tiles (#5139) 2023-10-27 13:48:43 +02:00
Art 9838efa00e feat(proposals): generic proposal toasts (#5134) 2023-10-27 13:17:51 +02:00
m.ray dac7142a98 feat(trading): add earmarked fees (#5123) 2023-10-27 13:09:01 +02:00
Matthew Russell 1397aafd25 fix(ui-toolkit): sparkline red shaded area color 2023-10-26 10:19:05 -07:00
Matthew Russell b192603e57 feat(ui-toolkit): sparkline shaded area (#5131) 2023-10-26 10:06:05 -07:00
Matthew Russell 8c2c8d987c feat(trading): add row click for fees table (#5130) 2023-10-26 08:38:52 -07:00
Matthew Russell 52c96794f7 feat(trading): fees page (#5055) 2023-10-25 14:59:30 -07:00
Ben 58ce016d4d chore(trading): suspend market test to console test (#5128) 2023-10-25 16:21:11 +01:00
Ben ac16eb06f5 chore(trading): delete fills cypress tests (#5122) 2023-10-25 14:02:43 +01:00
Ben 3319871617 chore(trading): delete dupe transfer tests (#5121) 2023-10-25 12:29:21 +00:00
Bartłomiej Głownia 37e850304a feat(trading): upgrade pennant@1.14.0 (#5120) 2023-10-25 12:44:23 +01:00
daro-maj 655131c744 test(trading): fix capsule test (#5116) 2023-10-25 12:39:18 +01:00
m.ray f1cb1b9408 fix(trading): quote base unit for size (#5124) 2023-10-25 12:36:57 +01:00
m.ray 891ac527a2 feat(trading): add tooltips for iceberg and post or reduce only (#5119) 2023-10-25 12:18:52 +01:00
Art 546087fb9f chore(trading): referrals with sidebar (#5117) 2023-10-25 11:14:00 +02:00
BenandMatthew Russell f7a82d33ba chore(trading): withdraw tests to jest (#5109)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-10-25 08:45:58 +01:00
Matthew Russell d85f413e41 chore(trading,positions): update estimatePosition query to use market decimals for liquidation price (#5005) 2023-10-24 17:30:17 -07:00
Edd c7d0025b4f feat(explorer): add determinsitic id to transfer tx (#5112) 2023-10-24 16:48:17 +01:00
Art 6c9272cd53 chore(trading): i18n-friendly referrals (#5113) 2023-10-24 17:43:33 +02:00
m.rayandasiaznik 82fb29d541 feat(trading): add liquidity provision new SLA parameters to liquidity tables (#5032)
Co-authored-by: asiaznik <artur@vegaprotocol.io>
2023-10-24 10:32:07 +01:00
Art 43cd170c77 feat(trading): referrals (Mk2), referrals stats, apply preview (#5021) 2023-10-23 16:57:18 +02:00
Edd 1d39f81dfc fix(governance): remove restricted route from navigation (#5106) 2023-10-23 14:16:07 +00:00
Bartłomiej Głownia f5868b6f1b feat(trading): show when a market may be closed through governance (#5057) 2023-10-23 13:42:37 +02:00
m.ray 20e1522088 chore(trading): use quantum for liquidity supplied (#5099) 2023-10-23 10:24:26 +01:00
Radosław Szpiech ae02b153f8 chore(trading): fix cancel all button and move trading orders tests (#5100) 2023-10-23 08:34:50 +02:00
Maciek fee5f862a7 chore(trading): remove account history tab (#5098) 2023-10-20 15:08:19 +02:00
Edd c25362b084 feat(governance): add restricted page (#5097) 2023-10-20 11:27:14 +00:00
Edd 7c105d2c6b feat(explorer): add restricted route (#5094) 2023-10-19 18:28:33 +00:00
Maciek 2dfcb02d1e chore(orders): 4970 add no rows and error info (#5076) 2023-10-19 14:45:55 +01:00
Sam Keen a98ab775c3 feat(governance): transfers destination field can fallback to type (#5092) 2023-10-19 11:16:00 +01:00
Maciek 097bf7c08c chore(trading): add button for copying asset id (#5075) 2023-10-18 17:02:34 +02:00
Bartłomiej Głowniaandbwallacee 236e35a92b feat(trading): show successor banner if market is settled or successor market exists (#5056)
Co-authored-by: bwallacee <ben@vega.xyz>
2023-10-18 14:48:52 +02:00
Maciek abf84b9d45 chore(ui-toolkit): 4970 async renderer - improve error handling (#5063) 2023-10-18 11:11:05 +02:00
m.ray 6d2a2ea0a0 chore(trading): update snap version to 0.3.1 (#5059) 2023-10-18 09:56:50 +01:00
Matthew Russell 6ac79e9f6d chore(trading,explorer,governance): update codeowners so dev team only is required for reviews 2023-10-17 20:14:48 -07:00
Matthew Russell 835ee64243 fix(trading): hydration error due to loader (#5043) 2023-10-17 20:05:53 -07:00
Matthew Russell e7c3b5054c fix(trading): market selector dropdown not updating (#5027) 2023-10-17 09:56:48 -07:00
Maciek 9dc9588a14 chore(ledger): 4895 refactor ledger csv extract (#5053) 2023-10-17 17:15:38 +02:00
Ben a0844d41bf chore(trading): move transfer test to jest (#5058) 2023-10-17 10:56:21 +01:00
m.ray 3d1aa74128 fix(trading): liquidation price tooltip link (#5050) 2023-10-17 10:44:49 +01:00
Ben 2376bfe58f chore(trading): deposit test to jest (#5036) 2023-10-16 11:44:37 -07:00
Matthew Russell 72ccf96523 fix(trading): remove additional page for closed markets (#5042) 2023-10-16 11:18:26 -07:00
Matthew Russell f416fa4a25 chore(trading,explorer,governance): adjust codeowners to require reviews from both teams (#5054) 2023-10-16 16:11:19 +01:00
Matthew Russell a24e3646cc fix(trading): glitchy waterfall loading (#5039) 2023-10-16 07:49:23 -07:00
Art 55b092b216 fix(trading): update referral program proposal changes (#5030) 2023-10-16 16:45:00 +02:00
Matthew Russell ef4cf6a87e chore(assets): add testnet deny list (#5044) 2023-10-16 07:41:31 -07:00
Sam Keen c9860a3412 fix(governance): governance initiated transfers fixes (#5025) 2023-10-16 12:02:06 +01:00
m.ray 127bd3faf3 chore(trading): code owners fix for two reviewers (#5046) 2023-10-16 12:00:20 +01:00
Bartłomiej Głownia 1791b3ca6a feat(trading): adjust layout for funding payments (#5034) 2023-10-16 11:19:08 +02:00
Matthew Russell 6044b86ff4 chore(trading): add background to sidebar and minor tweaks (#5037) 2023-10-13 11:30:04 -07:00
Matthew Russell 341d78e761 chore(trading): fix hydration errors and improve loading experience (#5038) 2023-10-13 16:02:33 +02:00
1299 changed files with 75906 additions and 28722 deletions
+3 -1
View File
@@ -73,9 +73,11 @@
"error",
{
"prefer": "type-imports",
"disallowTypeAnnotations": true
"disallowTypeAnnotations": true,
"fixStyle": "inline-type-imports"
}
],
"@typescript-eslint/no-useless-constructor": 0,
"curly": ["error", "multi-line"]
}
},
+1
View File
@@ -1,3 +1,4 @@
* text eol=lf
*.png binary
*.ico binary
*.woff2 binary
+6 -6
View File
@@ -34,7 +34,7 @@ jobs:
${{ runner.os }}-cache-node-modules-
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
if: steps.cache.outputs.cache-hit != 'true'
with:
node-version-file: '.nvmrc'
@@ -57,7 +57,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
@@ -96,7 +96,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: yarn
@@ -128,7 +128,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: yarn
@@ -182,7 +182,7 @@ jobs:
run: |
if [[ "${{ github.base_ref }}" == "develop" ]]; then
echo "e2e-needed=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.base_ref }}" == "main" ]]; then
elif [[ "${{ github.base_ref }}" == "main" ]]; then
echo "e2e-needed=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/"* ]]; then
echo "e2e-needed=true" >> $GITHUB_OUTPUT
@@ -205,7 +205,7 @@ jobs:
console-e2e:
needs: [build-sources, check-e2e-needed]
name: '(CI) console python'
name: '(CI) trading e2e python'
uses: ./.github/workflows/console-test-run.yml
secrets: inherit
if: needs.check-e2e-needed.outputs.run-tests == 'true' && contains(needs.build-sources.outputs.projects, 'trading')
+64 -24
View File
@@ -10,7 +10,7 @@ on:
inputs:
console-test-branch:
type: choice
description: 'main: v0.72.14, develop: v0.73.0-preview7'
description: 'main: v0.73.5, develop: v0.73.5'
options:
- main
- develop
@@ -19,7 +19,7 @@ jobs:
create-docker-image:
name: Create docker image for console-test
runs-on: ubuntu-22.04
timeout-minutes: 20
timeout-minutes: 45
steps:
#----------------------------------------------
# check-out frontend-monorepo
@@ -32,9 +32,9 @@ jobs:
# cache node modules
#----------------------------------------------
- name: setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: '16'
node-version-file: '.nvmrc'
cache: yarn
- name: Cache node modules
@@ -138,7 +138,7 @@ jobs:
name: run-tests
runs-on: 8-cores
needs: [create-docker-image, console-test-branch]
timeout-minutes: 20
timeout-minutes: 45
steps:
#----------------------------------------------
# load docker image
@@ -153,25 +153,19 @@ jobs:
run: |
docker load --input /tmp/console-image.tar
docker image ls -a
#----------------------------------------------
# check-out tests repo
# check-out frontend-monorepo
#----------------------------------------------
- name: Checkout console test repo
- name: Checkout frontend-monorepo
uses: actions/checkout@v3
with:
repository: vegaprotocol/console-test
ref: ${{ needs.console-test-branch.outputs.console-branch }}
- name: Load console test envs
id: console-test-env
uses: falti/dotenv-action@v1.0.4
with:
path: '.env.${{ needs.console-test-branch.outputs.console-branch }}'
export-variables: true
keys-case: upper
log-variables: true
ref: ${{ inputs.github-sha || github.sha }}
#----------------------------------------------
# get vega version
#----------------------------------------------
- name: Set VEGA_VERSION from .env
id: set_vega_version
run: echo "VEGA_VERSION=$(grep VEGA_VERSION apps/trading/e2e/.env | cut -d '=' -f2)" >> $GITHUB_ENV
#----------------------------------------------
# ----- Setup python -----
#----------------------------------------------
@@ -194,22 +188,25 @@ jobs:
#----------------------------------------------
- name: Install dependencies
run: poetry install --no-interaction --no-root
working-directory: apps/trading/e2e
#----------------------------------------------
# install vega binaries
#----------------------------------------------
- name: Install vega binaries
run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
working-directory: apps/trading/e2e
#----------------------------------------------
# install playwright
# install playwrightworking-directory: apps/trading/e2e
#----------------------------------------------
- name: install playwright
run: poetry run playwright install --with-deps chromium
working-directory: apps/trading/e2e
#----------------------------------------------
# run tests
#----------------------------------------------
- name: Run tests
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v --numprocesses 1 --dist loadfile --durations=45
working-directory: apps/trading/e2e
#----------------------------------------------
# upload traces
#----------------------------------------------
@@ -218,7 +215,7 @@ jobs:
if: always()
with:
name: playwright-trace
path: ./traces/
path: apps/trading/e2e/traces/
retention-days: 15
#----------------------------------------------
# ----- upload logs -----
@@ -230,3 +227,46 @@ jobs:
name: worker-logs
path: ./logs/
retention-days: 15
#----------------------------------------------
# ----- upload market-sim logs -----
#----------------------------------------------
- name: Prepare and Zip market-sim-logs
if: always()
run: |
parent_dir="/tmp/market-sim-logs"
echo "Creating parent directory at $parent_dir"
mkdir -p "$parent_dir"
echo "Waiting for vega-sim-* folders to be created..."
sleep 10 # Waits 10 seconds to ensure all folders are created
echo "Before searching for vega-sim-* folders in /tmp..."
folders=$(find /tmp -mindepth 1 -type d -name 'vega-sim-*' -print) || echo "Find command failed with exit code $?"
echo "After searching for vega-sim-* folders in /tmp..."
if [ -z "$folders" ]; then
echo "No vega-sim-* folders found."
exit 0
fi
echo "Moving vega-sim-* folders to $parent_dir"
echo "$folders" | xargs -I {} mv {} "$parent_dir/"
echo "Checking if $parent_dir is not empty..."
if [ "$(ls -A $parent_dir)" ]; then
echo "Zipping the parent directory..."
zip -r market-sim-logs.zip "$parent_dir" && echo "Zip file created successfully."
else
echo "$parent_dir is empty. No zip file created."
exit 0
fi
shell: /usr/bin/bash -e {0}
- name: Upload market-sim-logs
uses: actions/upload-artifact@v3
if: always()
with:
name: market-sim-logs
path: market-sim-logs.zip
retention-days: 15
+3 -3
View File
@@ -18,11 +18,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js 16
- name: Use Node.js 20
id: Node
uses: actions/setup-node@v2
uses: actions/setup-node@v4
with:
node-version: 16.15.1
node-version-file: '.nvmrc'
- name: Run Cypress tests
uses: cypress-io/github-action@v4
+8
View File
@@ -57,6 +57,14 @@ jobs:
path: './frontend-monorepo'
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: './frontend-monorepo/.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
cache-dependency-path: './frontend-monorepo/yarn.lock'
# Restore node_modules from cache if possible
- name: Restore node_modules from cache
id: cache-node-modules
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
+3 -3
View File
@@ -18,13 +18,13 @@ jobs:
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 16
node-version-file: '.nvmrc'
- name: Install dependencies
run: |
rm package.json
rm package.json
npm install --no-save @commitlint/cli @commitlint/config-conventional @commitlint/config-nx-scopes nx
- name: Check PR title
+1 -1
View File
@@ -93,7 +93,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
+9 -1
View File
@@ -48,7 +48,15 @@ cypress.env.json
# Next.js
.next
#cypress
# cypress
/apps/**/cypress/reports/
/apps/**/cypress/downloads/
/apps/**/fixtures/wallet/node**
# apps/trading/e2e
__pycache__/
apps/trading/e2e/logs/
apps/trading/e2e/.pytest_cache/
apps/trading/e2e/traces/
.nx/
+3
View File
@@ -1,5 +1,8 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Auto-format all files
yarn nx format:write
# Lint all staged files
yarn lint-staged
+3 -3
View File
@@ -1,8 +1,8 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Lint all staged files
yarn nx format:check
# Lint all staged files - this brings more value as pre-commit
# yarn nx format:check
# Test all projects with changes
yarn nx affected -t test --exclude trading
# yarn nx affected -t test --exclude trading
+1 -1
View File
@@ -1 +1 @@
16.20.2
20.9.0
+13
View File
@@ -1,6 +1,7 @@
# Add files here to ignore them from prettier formatting
/dist
/dist-result
/coverage
__generated__
__generated___
@@ -8,3 +9,15 @@ __generated___
apps/static/src/assets/devnet-tranches.json
apps/static/src/assets/mainnet-tranches.json
apps/static/src/assets/testnet-tranches.json
/apps/**/cypress/reports/
/apps/**/cypress/downloads/
/.nx/cache
# apps/trading/e2e
__pycache__/
apps/trading/e2e/logs/
apps/trading/e2e/.pytest_cache/
apps/trading/e2e/traces/
.pytest_cache/
+2 -1
View File
@@ -1,3 +1,4 @@
* @vegaprotocol/frontend
* @vegaprotocol/frontend-qa
apps/ @vegaprotocol/frontend-qa
libs/ @vegaprotocol/frontend-qa
*.graphql @vegaprotocol/core
+1 -1
View File
@@ -136,7 +136,7 @@ The [`docker`](./docker) subfolder has some docker configurations for easily set
Using multistage dockerfile dist is compiled using [node](https://hub.docker.com/_/node) image and later packed to nginx as in [dist build](#dist-build). The multistage builds ensures consistent CPU architecture and build toolchains are used so that the result will be identical.
```bash
docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=16.5.1 --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=20.9.1 --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
```
### Computing ipfs-hash of the build
+3 -1
View File
@@ -4,7 +4,9 @@
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
"rules": {
"cypress/unsafe-to-chain-command": 0
}
}
]
}
+1 -1
View File
@@ -17,7 +17,7 @@
}
},
"lint": {
"executor": "@nx/linter:eslint",
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/explorer-e2e/**/*.{js,ts}"]
@@ -39,7 +39,6 @@ context('Market page', { tags: '@regression' }, function () {
cy.contains('Test market 1').click();
cy.getByTestId(marketHeaders).should('have.text', 'Test market 1');
cy.validate_element_from_table('Name', 'Test market 1');
cy.validate_element_from_table('Market ID', this.createdMarketId);
cy.validate_element_from_table('Trading Mode', 'Opening auction');
cy.validate_element_from_table('Market Decimal Places', '5');
cy.validate_element_from_table('Position Decimal Places', '5');
@@ -1,68 +0,0 @@
context('Oracle page', { tags: '@smoke' }, () => {
describe('Verify elements on page', () => {
before('create market and navigate to oracle page', () => {
cy.createMarket();
cy.visit('/oracles');
});
it('should see oracle data', () => {
cy.getByTestId('oracle-details').should('have.length.at.least', 2);
cy.getByTestId('oracle-details')
.should('exist')
.eq(0)
.within(() => {
cy.get('tr')
.eq(0)
.within(() => {
cy.get('th').should('have.text', 'ID');
cy.get('a').invoke('text').should('have.length', 64);
cy.get('a')
.should('have.attr', 'href')
.and('contain', '/oracles/');
});
cy.get('tr')
.eq(1)
.within(() => {
cy.get('th').should('have.text', 'Type');
cy.get('td').should('have.text', 'External data');
});
cy.get('tr')
.eq(2)
.within(() => {
cy.get('th').should('have.text', 'Signer');
cy.getByTestId('keytype').should('have.text', 'Vega');
cy.get('a').invoke('text').should('have.length', 64);
cy.get('a')
.should('have.attr', 'href')
.and('contain', '/parties/');
});
cy.get('tr')
.eq(3)
.within(() => {
cy.get('th').should('have.text', 'Settlement for');
cy.get('a').invoke('text').should('have.length', 64);
cy.get('a')
.should('have.attr', 'href')
.and('contain', '/markets/');
});
cy.get('tr')
.eq(4)
.within(() => {
cy.get('th').should('have.text', 'Matched data');
cy.get('td').should('have.text', '❌');
});
cy.get('details')
.eq(0)
.within(() => {
cy.contains('Filter').click();
cy.get('.language-json').should('exist');
});
cy.get('details')
.eq(1)
.within(() => {
cy.contains('JSON').click();
cy.get('.language-json').should('exist');
});
});
});
});
});
@@ -44,7 +44,7 @@ context('Proposal page', { tags: '@smoke' }, function () {
cy.getByTestId('icon-cross').click();
});
it.skip('Proposal page displayed on mobile', function () {
it('Proposal page displayed on mobile', function () {
const proposalTitle = 'Add Lorem Ipsum market';
cy.common_switch_to_mobile_and_click_toggle();
@@ -55,7 +55,7 @@ context('Proposal page', { tags: '@smoke' }, function () {
});
});
it('Able to view new asset proposal', function () {
it.skip('Able to view new asset proposal', function () {
const proposalTitle = 'Test new asset proposal';
const newAssetProposalBody = getNewAssetTxBody();
cy.VegaWalletSubmitProposal(newAssetProposalBody);
-2
View File
@@ -1,5 +1,4 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.rocks
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
@@ -9,7 +8,6 @@ NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.rocks/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_VEGA_GOVERNANCE_URL=https://governance.stagnet1.vega.rocks
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
-1
View File
@@ -1,6 +1,5 @@
# App configuration variables
NX_VEGA_ENV=CUSTOM
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
-1
View File
@@ -2,7 +2,6 @@
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_ENV=DEVNET
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://dev.governance.vega.xyz
NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
-1
View File
@@ -4,7 +4,6 @@ NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/maste
NX_VEGA_URL=https://api.vega.community/graphql
NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.vega.community/rest
NX_ETHERSCAN_URL=https://etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
-1
View File
@@ -4,7 +4,6 @@ NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-inter
NX_VEGA_URL=https://api.mainnet-mirror.vega.rocks/graphql
NX_VEGA_ENV=MAINNET_MIRROR
NX_BLOCK_EXPLORER=https://be.mainnet-mirror.vega.rocks/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.mainnet-mirror.vega.rocks
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks/
-1
View File
@@ -4,7 +4,6 @@ NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-inter
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
-1
View File
@@ -4,7 +4,6 @@ NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/maste
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
-1
View File
@@ -3,7 +3,6 @@ NX_TENDERMINT_URL=http://localhost:26607/
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
NX_VEGA_ENV=CUSTOM
NX_BLOCK_EXPLORER=
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
-4
View File
@@ -1,4 +0,0 @@
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
+3 -19
View File
@@ -53,7 +53,7 @@
}
},
"lint": {
"executor": "@nx/linter:eslint",
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/explorer/**/*.{ts,tsx,js,jsx}"]
@@ -63,30 +63,14 @@
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/apps/explorer"],
"options": {
"jestConfig": "apps/explorer/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
"jestConfig": "apps/explorer/jest.config.ts"
}
},
"generate-types": {
"executor": "nx:run-commands",
"options": {
"commands": [
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.72.3/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
]
}
},
"build-netlify": {
"executor": "nx:run-commands",
"options": {
"commands": [
"cp apps/explorer/netlify.toml netlify.toml",
"nx build explorer"
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.73.1/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
]
}
},
+25 -16
View File
@@ -1,6 +1,7 @@
import '../i18n';
import {
AppFailure,
NetworkLoader,
NodeFailure,
NodeGuard,
NodeSwitcherDialog,
useEnvironment,
@@ -11,7 +12,8 @@ import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-web
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
import { RouterProvider } from 'react-router-dom';
import { router } from './routes/router-config';
import { useRouterConfig } from './routes/router-config';
import { createBrowserRouter } from 'react-router-dom';
import { t } from '@vegaprotocol/i18n';
import { Suspense } from 'react';
@@ -28,20 +30,27 @@ function App() {
);
return (
<TendermintWebsocketProvider>
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
<NodeGuard
skeleton={<div>{t('Loading')}</div>}
failure={<AppFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
>
<Suspense fallback={splashLoading}>
<RouterProvider router={router} fallbackElement={splashLoading} />
</Suspense>
</NodeGuard>
<NodeSwitcherDialog
open={nodeSwitcherOpen}
setOpen={setNodeSwitcherOpen}
/>
</NetworkLoader>
<Suspense fallback={splashLoading}>
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
<NodeGuard
skeleton={<div>{t('Loading')}</div>}
failure={
<NodeFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />
}
>
<Suspense fallback={splashLoading}>
<RouterProvider
router={createBrowserRouter(useRouterConfig())}
fallbackElement={splashLoading}
/>
</Suspense>
</NodeGuard>
<NodeSwitcherDialog
open={nodeSwitcherOpen}
setOpen={setNodeSwitcherOpen}
/>
</NetworkLoader>
</Suspense>
</TendermintWebsocketProvider>
);
}
@@ -1,5 +1,5 @@
import { useAssetDataProvider } from '@vegaprotocol/assets';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { addDecimalsFixedFormatNumber } from '@vegaprotocol/utils';
import { AssetLink } from '../links';
export type AssetBalanceProps = {
@@ -23,12 +23,12 @@ const AssetBalance = ({
const label =
!loading && asset && asset.decimals
? addDecimalsFormatNumber(price, asset.decimals)
? addDecimalsFixedFormatNumber(price, asset.decimals)
: price;
return (
<div className="inline-block">
<span>{label}</span>{' '}
<span className="font-mono">{label}</span>{' '}
{showAssetLink && asset?.id ? (
<AssetLink showAssetSymbol={showAssetSymbol} assetId={assetId} />
) : null}
@@ -1,24 +1,30 @@
import { useMemo } from 'react';
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
import {
useAssetTypeMapping,
useAssetStatusMapping,
type AssetFieldsFragment,
} from '@vegaprotocol/assets';
import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { type AgGridReact } from 'ag-grid-react';
import { AgGrid } from '@vegaprotocol/datagrid';
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
import { type VegaICellRendererParams } from '@vegaprotocol/datagrid';
import { useRef, useLayoutEffect } from 'react';
import { BREAKPOINT_MD } from '../../config/breakpoints';
import { useNavigate } from 'react-router-dom';
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
import { type ColDef } from 'ag-grid-community';
import type { RowClickedEvent } from 'ag-grid-community';
type AssetsTableProps = {
data: AssetFieldsFragment[] | null;
};
export const AssetsTable = ({ data }: AssetsTableProps) => {
const assetTypeMapping = useAssetTypeMapping();
const assetStatusMapping = useAssetStatusMapping();
const navigate = useNavigate();
const ref = useRef<AgGridReact>(null);
const showColumnsOnDesktop = () => {
ref.current?.columnApi.setColumnsVisible(
ref.current?.api.setColumnsVisible(
['id', 'type', 'status'],
window.innerWidth > BREAKPOINT_MD
);
@@ -47,14 +53,14 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
field: 'source.__typename',
hide: window.innerWidth < BREAKPOINT_MD,
valueFormatter: ({ value }: { value?: string }) =>
value ? AssetTypeMapping[value].value : '',
value ? assetTypeMapping[value].value : '',
},
{
headerName: t('Status'),
field: 'status',
hide: window.innerWidth < BREAKPOINT_MD,
valueFormatter: ({ value }: { value?: string }) =>
value ? AssetStatusMapping[value].value : '',
value ? assetStatusMapping[value].value : '',
},
{
colId: 'actions',
@@ -69,7 +75,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
}: VegaICellRendererParams<AssetFieldsFragment, 'id'>) =>
value ? (
<ButtonLink
onClick={(e) => {
onClick={() => {
navigate(value);
}}
>
@@ -80,7 +86,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
),
},
],
[navigate]
[navigate, assetStatusMapping, assetTypeMapping]
);
return (
@@ -14,7 +14,7 @@ import { Routes } from '../../routes/route-names';
import { NetworkSwitcher } from '@vegaprotocol/environment';
import type { Navigable } from '../../routes/router-config';
import { isNavigable } from '../../routes/router-config';
import { routerConfig } from '../../routes/router-config';
import { useRouterConfig } from '../../routes/router-config';
import { useMemo } from 'react';
import compact from 'lodash/compact';
import { Search } from '../search';
@@ -26,6 +26,7 @@ const routeToNavigationItem = (r: Navigable) => (
);
export const Header = () => {
const routerConfig = useRouterConfig();
const isHome = Boolean(useMatch(Routes.HOME));
const pages = routerConfig[0].children || [];
const mainItems = compact(
@@ -1,34 +0,0 @@
import React from 'react';
import { DATA_SOURCES } from '../../../config';
import Hash from '../hash';
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 font-mono"
target="_blank"
rel="noopener noreferrer"
{...props}
href={link}
>
<Hash text={id} />
</a>
);
};
@@ -0,0 +1,34 @@
import type { ChainIdMapping } from './external-chain';
import { SUPPORTED_CHAIN_IDS, SUPPORTED_CHAIN_LABELS } from './external-chain';
export const SUPPORTED_CHAIN_ICON_URLS: ChainIdMapping = {
'1': '/assets/chain-eth-logo.svg',
'100': '/assets/chain-gno-logo.svg',
'42161': '/assets/chain-arb-logo.svg',
'11155111': '/assets/chain-eth-logo.svg',
};
export type ExternalChainIconProps = {
chainId?: string;
};
export const ExternalChainIcon = ({
// If chainID is not provided, default to a non-existent chain
chainId = '-1',
}: ExternalChainIconProps) => {
if (SUPPORTED_CHAIN_IDS.includes(chainId)) {
const url = SUPPORTED_CHAIN_ICON_URLS[chainId];
const alt = SUPPORTED_CHAIN_LABELS[chainId];
return (
<img
src={url}
className="inline-block w-4 h-4 mr-1 dark:invert"
alt={alt}
title={alt}
/>
);
} else {
return null;
}
};
@@ -0,0 +1,38 @@
export type ChainIdMapping = {
[K in typeof SUPPORTED_CHAIN_IDS[number]]: string;
};
export const SUPPORTED_CHAIN_IDS: string[] = ['1', '100', '42161', '11155111'];
export const SUPPORTED_CHAIN_LABELS: ChainIdMapping = {
'1': 'Ethereum',
'100': 'Gnosis',
'42161': 'Arbitrum',
'11155111': 'Sepolia',
};
export function getExternalExplorerLink(chainId: string, type: string) {
if (SUPPORTED_CHAIN_IDS.includes(chainId)) {
switch (chainId) {
case '1':
return 'https://etherscan.io';
case '100':
return 'https://gnosisscan.io';
case '42161':
return 'https://arbiscan.io';
case '11155111':
return 'https://sepolia.etherscan.io';
default:
return '#';
}
} else {
return '#';
}
}
export function getExternalChainLabel(chainId?: string) {
if (chainId && SUPPORTED_CHAIN_IDS.includes(chainId)) {
return SUPPORTED_CHAIN_LABELS[chainId];
} else {
return 'Custom Chain';
}
}
@@ -0,0 +1,41 @@
import Hash from '../hash';
import { getExternalExplorerLink } from './external-chain';
import { ExternalChainIcon } from './external-chain-icon';
export enum EthExplorerLinkTypes {
block = 'block',
address = 'address',
tx = 'tx',
}
export type ExternalExplorerLinkProps = Partial<typeof HTMLAnchorElement> & {
id: string;
type: EthExplorerLinkTypes;
// Defaults to Ethereum Mainnet, as chain support was added late
chain?: string;
code?: boolean;
};
export const ExternalExplorerLink = ({
id,
type,
chain = '1',
code = false,
...props
}: ExternalExplorerLinkProps) => {
const link = `${getExternalExplorerLink(chain, type)}/${type}/${id}${
code ? '#code' : ''
}`;
return (
<a
className="underline external font-mono"
target="_blank"
rel="noopener noreferrer"
{...props}
href={link}
>
<ExternalChainIcon chainId={chain} />
<Hash text={id} />
</a>
);
};
@@ -1,5 +1,6 @@
export type HashProps = {
export type HashProps = React.HTMLProps<HTMLSpanElement> & {
text: string;
truncate?: boolean;
};
/**
@@ -7,10 +8,16 @@ export type HashProps = {
* are broken when they need to wrap. This will remove the need
* for a lot of the overflow scrolling that currently exists.
*/
const Hash = ({ text }: HashProps) => {
const Hash = ({ text, truncate = false }: HashProps) => {
const h = truncate ? text.slice(0, 6) : text;
return (
<code className="break-all font-mono" style={{ wordWrap: 'break-word' }}>
{text}
<code
title={text}
className="break-all font-mono"
style={{ wordWrap: 'break-word' }}
>
{h}
</code>
);
};
@@ -2,4 +2,5 @@ export { default as BlockLink } from './block-link/block-link';
export { default as PartyLink } from './party-link/party-link';
export { default as NodeLink } from './node-link/node-link';
export { default as MarketLink } from './market-link/market-link';
export { default as NetworkParameterLink } from './network-parameter-link/network-parameter-link';
export * from './asset-link/asset-link';
@@ -3,6 +3,7 @@ query ExplorerMarket($id: ID!) {
id
decimalPlaces
positionDecimalPlaces
state
tradableInstrument {
instrument {
name
@@ -22,6 +23,5 @@ query ExplorerMarket($id: ID!) {
}
}
}
state
}
}
@@ -17,6 +17,7 @@ export const ExplorerMarketDocument = gql`
id
decimalPlaces
positionDecimalPlaces
state
tradableInstrument {
instrument {
name
@@ -36,7 +37,6 @@ export const ExplorerMarketDocument = gql`
}
}
}
state
}
}
`;
@@ -63,6 +63,9 @@ describe('Market link component', () => {
product: {
__typename: 'Future',
quoteName: 'dai',
settlementAsset: {
decimals: 8,
},
},
},
},
@@ -88,6 +91,6 @@ describe('Market link component', () => {
};
const res = render(renderComponent('123', [mock]));
expect(await res.findByText('123')).toBeInTheDocument();
expect(await res.findByTitle('123')).toBeInTheDocument();
});
});
@@ -23,6 +23,7 @@ const MarketLink = ({
}: MarketLinkProps) => {
const { data, error, loading } = useExplorerMarketQuery({
variables: { id },
fetchPolicy: 'cache-first',
});
let label = <span>{id}</span>;
@@ -0,0 +1,30 @@
import React from 'react';
import { Routes } from '../../../routes/route-names';
import { Link } from 'react-router-dom';
import type { ComponentProps } from 'react';
import Hash from '../hash';
export type NetworkParameterLinkProps = Partial<ComponentProps<typeof Link>> & {
parameter: string;
};
/**
* Links a given network parameter to the relevant page and anchor on the page
*/
const NetworkParameterLink = ({
parameter,
...props
}: NetworkParameterLinkProps) => {
return (
<Link
className="underline"
{...props}
to={`/${Routes.NETWORK_PARAMETERS}#${parameter}`}
>
<Hash text={parameter} />
</Link>
);
};
export default NetworkParameterLink;
@@ -0,0 +1,57 @@
import OracleLink, { getStatusString } from './oracle-link';
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing';
describe('getStatusString', () => {
it("returns 'Unknown' for undefined status", () => {
expect(getStatusString(undefined)).toBe('Unknown');
});
it('returns the correct string for a known status', () => {
expect(getStatusString('STATUS_ACTIVE')).toBe('Active');
expect(getStatusString('STATUS_DEACTIVATED')).toBe('Deactivated');
});
});
describe('OracleLink', () => {
it('renders the truncated Oracle ID', () => {
const id = '123456789';
render(
<MockedProvider>
<MemoryRouter>
<OracleLink id={id} />
</MemoryRouter>
</MockedProvider>
);
const idElement = screen.getByText(id.slice(0, 6));
expect(idElement).toBeInTheDocument();
expect(idElement).toHaveAttribute('title', id);
});
it('renders the Oracle status', () => {
const id = '123';
const status = 'STATUS_ACTIVE';
render(
<MockedProvider>
<MemoryRouter>
<OracleLink id={id} status={status} data-testid="link" />
</MemoryRouter>
</MockedProvider>
);
expect(screen.getByTestId('link')).toHaveAttribute('data-status', 'Active');
});
it('renders the Oracle data indicator', () => {
const id = '123';
const hasSeenOracleReports = true;
render(
<MockedProvider>
<MemoryRouter>
<OracleLink id={id} hasSeenOracleReports={hasSeenOracleReports} />
</MemoryRouter>
</MockedProvider>
);
expect(screen.getByTestId('oracle-data-indicator')).toBeInTheDocument();
});
});
@@ -3,20 +3,93 @@ import { Link } from 'react-router-dom';
import type { ComponentProps } from 'react';
import Hash from '../hash';
import { Tooltip, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
import {
DataSourceSpecStatus,
DataSourceSpecStatusMapping,
} from '@vegaprotocol/types';
import { t } from '@vegaprotocol/i18n';
/**
* Returns a human-readable string for the given status, or a meaningful
* default if the status is unrecognised
* @param status string status
*/
export function getStatusString(status: string | undefined): string {
if (status && status in DataSourceSpecStatus) {
return DataSourceSpecStatusMapping[status as DataSourceSpecStatus];
}
return t('Unknown');
}
export type OracleLinkProps = Partial<ComponentProps<typeof Link>> & {
// The Oracle ID
id: string;
// If available, the oracle status
status?: string;
// If the oracle has corresponding data in the OracleDataConnection
hasSeenOracleReports?: boolean;
};
const OracleLink = ({ id, ...props }: OracleLinkProps) => {
/**
* Given an Oracle ID, renders a data-dense link to the Oracle page. Data density is achieved by:
* - Colour coding the link based on the Oracle's status
* - Showing a small indicator if the Oracle has matched data
* - Showing a tooltip with the Oracle's status and whether it has matched data
*
* @returns
*/
export const OracleLink = ({
id,
status,
hasSeenOracleReports = false,
...props
}: OracleLinkProps) => {
const bgColour =
status === 'STATUS_ACTIVE'
? 'bg-yellow-100 hover:bg-yellow-200 border-yellow-200 dark:bg-yellow-200 dark:border-yellow-200 dark:text-gray-900 dark:border-yellow-300'
: 'bg-gray-100 hover:bg-gray-200 border-gray-200';
const indicatorColour =
status === 'STATUS_ACTIVE'
? 'bg-yellow-300 hover:bg-yellow-500 dark:bg-yellow-500'
: 'bg-gray-300 hover:bg-gray-500';
const description = (
<div>
<p>
<strong>{`Status: `}</strong>
{getStatusString(status)}
</p>
<p>
<strong>{`Matched data: `}</strong>
{hasSeenOracleReports ? (
<VegaIcon name={VegaIconNames.TICK} />
) : (
<VegaIcon name={VegaIconNames.CROSS} />
)}
</p>
</div>
);
return (
<Link
className="underline font-mono"
{...props}
to={`/${Routes.ORACLES}/${id}`}
>
<Hash text={id} />
</Link>
<Tooltip description={description}>
<Link
className={`pl-2 pr-2 font-mono dark:text-black ${bgColour} rounded-sm border-solid border-2 relative`}
{...props}
to={`/${Routes.ORACLES}/${id}`}
data-status={getStatusString(status)}
>
<Hash text={id} truncate={true} />
{hasSeenOracleReports ? (
<strong
data-testid="oracle-data-indicator"
className={`absolute top-0 right-0 w-1 h-full font-thin ${indicatorColour}`}
title="Oracle has matched data"
></strong>
) : null}
</Link>
</Tooltip>
);
};
@@ -60,7 +60,7 @@ const PartyLink = ({ id, truncate = false, ...props }: PartyLinkProps) => {
}
return (
<span className="whitespace-nowrap">
<span>
{useName && <Icon size={4} name="cube" className="mr-2" />}
<Link
className="underline font-mono"
@@ -1,9 +1,11 @@
query ExplorerProposal($id: ID!) {
proposal(id: $id) {
id
rationale {
title
description
... on Proposal {
id
rationale {
title
description
}
}
}
}
@@ -8,16 +8,18 @@ export type ExplorerProposalQueryVariables = Types.Exact<{
}>;
export type ExplorerProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null };
export type ExplorerProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'BatchProposal' } | { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null };
export const ExplorerProposalDocument = gql`
query ExplorerProposal($id: ID!) {
proposal(id: $id) {
id
rationale {
title
description
... on Proposal {
id
rationale {
title
description
}
}
}
}
@@ -3,7 +3,11 @@ import { MockedProvider } from '@apollo/client/testing';
import type { MockedResponse } from '@apollo/client/testing';
import { render } from '@testing-library/react';
import ProposalLink from './proposal-link';
import { ExplorerProposalDocument } from './__generated__/Proposal';
import {
ExplorerProposalDocument,
type ExplorerProposalQuery,
type ExplorerProposalQueryVariables,
} from './__generated__/Proposal';
import { GraphQLError } from 'graphql';
function renderComponent(id: string, mocks: MockedResponse[]) {
@@ -23,7 +27,10 @@ describe('Proposal link component', () => {
});
it('Renders the ID on error', async () => {
const mock = {
const mock: MockedResponse<
ExplorerProposalQuery,
ExplorerProposalQueryVariables
> = {
request: {
query: ExplorerProposalDocument,
variables: {
@@ -40,17 +47,22 @@ describe('Proposal link component', () => {
});
it('Renders the proposal title when the query returns a result', async () => {
const mock = {
const proposalId = '123';
const mock: MockedResponse<
ExplorerProposalQuery,
ExplorerProposalQueryVariables
> = {
request: {
query: ExplorerProposalDocument,
variables: {
id: '123',
id: proposalId,
},
},
result: {
data: {
proposal: {
id: '123',
__typename: 'Proposal',
id: proposalId,
rationale: {
title: 'test-title',
description: 'test description',
@@ -60,13 +72,16 @@ describe('Proposal link component', () => {
},
};
const res = render(renderComponent('123', [mock]));
expect(res.getByText('123')).toBeInTheDocument();
const res = render(renderComponent(proposalId, [mock]));
expect(res.getByText(proposalId)).toBeInTheDocument();
expect(await res.findByText('test-title')).toBeInTheDocument();
});
it('Leaves the proposal id when the market is not found', async () => {
const mock = {
const mock: MockedResponse<
ExplorerProposalQuery,
ExplorerProposalQueryVariables
> = {
request: {
query: ExplorerProposalDocument,
variables: {
@@ -1,7 +1,11 @@
import { useExplorerProposalQuery } from './__generated__/Proposal';
import {
useExplorerProposalQuery,
type ExplorerProposalQuery,
} from './__generated__/Proposal';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { ENV } from '../../../config/env';
import Hash from '../hash';
export type ProposalLinkProps = {
id: string;
text?: string;
@@ -16,8 +20,13 @@ const ProposalLink = ({ id, text }: ProposalLinkProps) => {
variables: { id },
});
const proposal = data?.proposal as Extract<
ExplorerProposalQuery['proposal'],
{ __typename?: 'Proposal' }
>;
const base = ENV.dataSources.governanceUrl;
const label = data?.proposal?.rationale.title || id;
const label = proposal?.rationale?.title || id;
return (
<ExternalLink href={`${base}/proposals/${id}`}>
@@ -1,6 +1,7 @@
import { t } from '@vegaprotocol/i18n';
import type { MarketInfoWithData } from '@vegaprotocol/markets';
import {
LiquidationStrategyInfoPanel,
LiquidityPriceRangeInfoPanel,
LiquiditySLAParametersInfoPanel,
MarginScalingFactorsPanel,
@@ -94,6 +95,8 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
</>
)
)}
<h2 className={headerClassName}>{t('Liquidation strategy')}</h2>
<LiquidationStrategyInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity monitoring')}</h2>
<LiquidityMonitoringParametersInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity price range')}</h2>
@@ -2,18 +2,18 @@ import { useMemo } from 'react';
import { getAsset, type MarketFieldsFragment } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import type { ColDef } from 'ag-grid-community';
import { type AgGridReact } from 'ag-grid-react';
import { type ColDef } from 'ag-grid-community';
import { AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
VegaValueGetterParams,
import {
type VegaICellRendererParams,
type VegaValueGetterParams,
} from '@vegaprotocol/datagrid';
import { useRef, useLayoutEffect } from 'react';
import { BREAKPOINT_MD } from '../../config/breakpoints';
import { MarketStateMapping } from '@vegaprotocol/types';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import type { RowClickedEvent } from 'ag-grid-community';
import { type RowClickedEvent } from 'ag-grid-community';
import { Link, useNavigate } from 'react-router-dom';
type MarketsTableProps = {
@@ -29,7 +29,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
const gridRef = useRef<AgGridReact>(null);
useLayoutEffect(() => {
const showColumnsOnDesktop = () => {
gridRef.current?.columnApi.setColumnsVisible(
gridRef.current?.api.setColumnsVisible(
['id', 'state', 'asset'],
window.innerWidth > BREAKPOINT_MD
);
@@ -1,9 +1,5 @@
import { render, waitFor } from '@testing-library/react';
import {
BORDER_COLOURS,
NestedDataList,
sortNestedDataByChildren,
} from './nested-data-list';
import { NestedDataList, sortNestedDataByChildren } from './nested-data-list';
import userEvent from '@testing-library/user-event';
const mockData = {
@@ -61,38 +57,6 @@ describe('NestedDataList', () => {
expect(parent[0].querySelector('li')).toHaveClass('pl-4 border-l-4 pt-2');
});
it('should repeat the border colours in the correct order', () => {
const colourMockData = {
t0: {
t1: {
t2: {
t3: {
t4: {
t5: {
t6: {
t7: {
t8: {
hello: 'world',
},
},
},
},
},
},
},
},
},
};
const tree = render(<NestedDataList data={colourMockData} />);
const { getByTestId } = tree;
for (let i = 0; i < 8; i++) {
const item = getByTestId(`T${i}`);
const expected = BORDER_COLOURS.light[i % 5];
expect(item.style.borderColor.toUpperCase()).toBe(expected);
}
});
it('should sort the data by values with children', () => {
const mockData = {
nonce: '5980890939790185837',
@@ -17,7 +17,7 @@ function renderAmendOrderDetails(
mocks: MockedResponse[]
) {
return render(
<MockedProvider mocks={mocks} addTypename={false}>
<MockedProvider mocks={mocks}>
<MemoryRouter>
<AmendOrderDetails version={version} id={id} amend={amend} />
</MemoryRouter>
@@ -44,18 +44,18 @@ function renderExistingAmend(
orderByID: {
__typename: 'Order',
id: '123',
type: 'GTT',
type: Schema.OrderType.TYPE_LIMIT,
status: Schema.OrderStatus.STATUS_ACTIVE,
version: version,
version: version ? version.toString() : '',
createdAt: '123',
updatedAt: '456',
expiresAt: '789',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
price: '200',
side: 'BUY',
side: Schema.Side.SIDE_BUY,
peggedOrder: null,
remaining: '99',
rejectionReason: 'rejection',
rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_NOT_FOUND,
reference: '123',
size: '100',
party: {
@@ -65,9 +65,9 @@ function renderExistingAmend(
market: {
__typename: 'Market',
id: '789',
state: 'STATUS_ACTIVE',
state: Schema.MarketState.STATE_ACTIVE,
positionDecimalPlaces: 2,
decimalPlaces: '5',
decimalPlaces: 0,
tradableInstrument: {
instrument: {
name: 'test',
@@ -94,18 +94,18 @@ function renderExistingAmend(
orderByID: {
__typename: 'Order',
id: '123',
type: 'GTT',
type: Schema.OrderType.TYPE_LIMIT,
status: Schema.OrderStatus.STATUS_ACTIVE,
version: 100,
version: '100',
createdAt: '123',
updatedAt: '456',
expiresAt: '789',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
peggedOrder: null,
price: '200',
side: 'BUY',
side: Schema.Side.SIDE_BUY,
remaining: '99',
rejectionReason: 'rejection',
rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_NOT_FOUND,
reference: '123',
size: '200',
party: {
@@ -114,10 +114,10 @@ function renderExistingAmend(
},
market: {
__typename: 'Market',
id: 'amend-to-order-latest-version',
state: 'STATUS_ACTIVE',
id: '8888',
state: Schema.MarketState.STATE_ACTIVE,
positionDecimalPlaces: 2,
decimalPlaces: '5',
decimalPlaces: 0,
tradableInstrument: {
instrument: {
name: 'amend-to-order-latest-version-test',
@@ -136,13 +136,13 @@ function renderExistingAmend(
request: {
query: ExplorerMarketDocument,
variables: {
id: '789',
id: '8888',
},
},
result: {
data: {
market: {
id: '789',
id: '8888',
decimalPlaces: 5,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data',
@@ -152,6 +152,9 @@ function renderExistingAmend(
product: {
__typename: 'Future',
quoteName: 'dai',
settlementAsset: {
decimals: 8,
},
},
},
},
@@ -216,12 +219,10 @@ describe('Amend order details', () => {
it('Fetches latest version when version is not specified', async () => {
const amend: Amend = {
price: '-7879',
price: '123',
};
const res = renderExistingAmend('123', undefined, amend);
expect(
await res.findByText('amend-to-order-latest-version')
).toBeInTheDocument();
expect(await res.findByText('test-label')).toBeInTheDocument();
});
});
@@ -46,10 +46,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
<div className={wrapperClasses}>
<div className="mb-12 lg:mb-0">
<div className="relative block rounded-lg px-3 py-6 md:px-6 lg:-mr-7">
<h2 className="text-3xl font-bold mb-4 display-5">
<h2 className="display-5 mb-4 text-3xl font-bold">
{t('Order not found')}
</h2>
<p className="text-gray-500 mb-12">
<p className="mb-12 text-gray-500">
{t('No order created from this transaction')}
</p>
</div>
@@ -68,24 +68,24 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
<div className={wrapperClasses}>
<div className="mb-12 lg:mb-0">
<div className="relative block px-3 py-6 md:px-6 lg:-mr-7">
<h2 className="text-3xl font-bold mb-4 display-5">
<h2 className="display-5 mb-4 text-3xl font-bold">
{t('Edits to ')}
{sideText[o.side]}
{t(' order')}
</h2>
<p className="text-gray-500 mb-4">
<div className="mb-4 text-gray-500">
In <MarketLink id={o.market.id} />, updated at{' '}
<Time date={o.updatedAt} />.
</p>
</div>
<div className="grid md:grid-cols-4 gap-x-6">
<div className="grid gap-x-6 md:grid-cols-4">
{amend.sizeDelta && amend.sizeDelta !== '0' ? (
<div className="mb-12 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-4">
<h2 className="text-dark mb-4 text-2xl font-bold">
{t('New size')}
</h2>
<h5
className={`text-lg font-medium text-gray-500 mb-0 capitalize ${getSideDeltaColour(
className={`mb-0 text-lg font-medium capitalize text-gray-500 ${getSideDeltaColour(
amend.sizeDelta
)}`}
>
@@ -96,10 +96,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
{amend.price && amend.price !== '0' ? (
<div className="">
<h2 className="text-2xl font-bold text-dark mb-4">
<h2 className="text-dark mb-4 text-2xl font-bold">
{t('New price')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
<h5 className="mb-0 text-lg font-medium text-gray-500">
<PriceInMarket price={amend.price} marketId={o.market.id} />
</h5>
</div>
@@ -108,10 +108,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
{amend.peggedReference &&
amend.peggedReference !== 'PEGGED_REFERENCE_UNSPECIFIED' ? (
<div className="">
<h2 className="text-2xl font-bold text-dark mb-4">
<h2 className="text-dark mb-4 text-2xl font-bold">
{t('New reference')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
<h5 className="mb-0 text-lg font-medium text-gray-500">
{peggedReference[amend.peggedReference]}
</h5>
</div>
@@ -119,10 +119,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
{amend.peggedOffset ? (
<div className="">
<h2 className="text-2xl font-bold text-dark mb-4">
<h2 className="text-dark mb-4 text-2xl font-bold">
{t('New offset')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
<h5 className="mb-0 text-lg font-medium text-gray-500">
{amend.peggedOffset}
</h5>
</div>
@@ -6,6 +6,7 @@ import { Time } from '../time';
import { sideText, statusText, tifFull, tifShort } from './lib/order-labels';
import SizeInMarket from '../size-in-market/size-in-market';
import { TxOrderPeggedReference } from '../txs/details/order/tx-order-peg';
import { OrderTypeMapping } from '@vegaprotocol/types';
export interface DeterministicOrderDetailsProps {
id: string;
@@ -59,7 +60,7 @@ const DeterministicOrderDetails = ({
const o = data.orderByID;
return (
<div className={wrapperClasses}>
<div className="mb-12 lg:mb-0">
<div className="mb-0">
<div className="relative block px-3 py-6 md:px-6 lg:-mr-7">
<h2 className="text-3xl font-bold mb-4 display-5">
<abbr title={tifFull[o.timeInForce]} className="bb-dotted mr-2">
@@ -69,7 +70,7 @@ const DeterministicOrderDetails = ({
<span className="mx-5 text-base">@</span>
<PriceInMarket price={o.price} marketId={o.market.id} />
</h2>
<p className="text-gray-200">
<p className="text-gray-400 dark:text-gray-600">
In <MarketLink id={o.market.id} /> at <Time date={o.createdAt} />.
</p>
{o.peggedOrder ? (
@@ -83,15 +84,14 @@ const DeterministicOrderDetails = ({
/>
</p>
) : null}
{o.reference ? (
<p className="text-gray-500 mt-4">
<span>{t('Reference')}</span>: {o.reference}
</p>
) : null}
<div className="grid md:grid-cols-4 gap-x-6 mt-4">
<div className="mb-12 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-4">
<div className="grid grid-cols-2 md:grid-cols-5 gap-x-6 mt-4">
<div className="mb-6 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
{t('Status')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0 capitalize">
@@ -99,21 +99,33 @@ const DeterministicOrderDetails = ({
</h5>
</div>
<div className="mb-12 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-4">{t('Size')}</h2>
<div className="mb-6 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
{t('Size')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
<SizeInMarket size={o.size} marketId={o.market.id} />
</h5>
</div>
<div className="">
<h2 className="text-2xl font-bold text-dark mb-4">
<div className="mb-6 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
{t('Version')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
{o.version}
</h5>
</div>
{o.type ? (
<div className="mb-6 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
{t('Type')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
{OrderTypeMapping[o.type]}
</h5>
</div>
) : null}
</div>
</div>
</div>
@@ -1,14 +1,15 @@
import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
import { type ProposalListFieldsFragment } from '@vegaprotocol/proposals';
import { VoteProgress } from '@vegaprotocol/proposals';
import type { AgGridReact } from 'ag-grid-react';
import { type AgGridReact } from 'ag-grid-react';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
VegaValueFormatterParams,
import {
type VegaICellRendererParams,
type VegaValueFormatterParams,
} from '@vegaprotocol/datagrid';
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
import { type ColDef } from 'ag-grid-community';
import type { RowClickedEvent } from 'ag-grid-community';
import { getDateTimeFormat } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import {
@@ -43,11 +44,11 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
const gridRef = useRef<AgGridReact>(null);
useLayoutEffect(() => {
const showColumnsOnDesktop = () => {
gridRef.current?.columnApi.setColumnsVisible(
gridRef.current?.api.setColumnsVisible(
['voting', 'cDate', 'eDate', 'type'],
window.innerWidth > BREAKPOINT_MD
);
gridRef.current?.columnApi.setColumnWidth(
gridRef.current?.api.setColumnWidth(
'actions',
window.innerWidth > BREAKPOINT_MD ? 221 : 80
);
@@ -105,7 +106,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
? new BigNumber(0)
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
return (
<div className="flex items-center justify-center h-full pt-2 uppercase">
<div className="flex h-full items-center justify-center pt-2 uppercase">
<VoteProgress
threshold={requiredMajorityPercentage}
progress={yesPercentage}
@@ -0,0 +1,59 @@
import { useState } from 'react';
import type { BlockExplorerTransactionResult } from '../../routes/types/block-explorer-response';
import {
CopyWithTooltip,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
interface SignatureProps {
signature: BlockExplorerTransactionResult['signature'];
}
const valueClass =
'font-mono px-2.5 py-0.5 text-xs max-w-[200px] cursor-pointer';
const valueClassClosed = 'text-ellipsis overflow-hidden';
const valueClassOpen = 'break-words text-left';
/**
* Viewer component for a vega signature. Featuers copy and pasting, truncation
*
* @param signature
*/
export const Signature = ({ signature }: SignatureProps) => {
const [isOpen, setIsOpen] = useState(false);
if (!signature || !signature.value || !signature.version || !signature.algo) {
return null;
}
return (
<div className="inline-flex border rounded signature-component relative pr-[20px]">
<div
className="bg-gray-100 px-2.5 py-0.5 text-xs text-gray-500 select-none cursor-default"
title={`${signature.algo}`}
>
<span>v{signature.version}</span>
</div>
<div
className={
isOpen
? `${valueClass} ${valueClassOpen}`
: `${valueClass} ${valueClassClosed}`
}
>
<CopyWithTooltip text={signature.value}>
<span title={signature.value}>{signature.value}</span>
</CopyWithTooltip>
</div>
<button
onClick={() => setIsOpen(!isOpen)}
className="absolute top-[-3px] right-0 pr-2"
title={t('Show full signature')}
>
<VegaIcon name={isOpen ? VegaIconNames.EYE_OFF : VegaIconNames.EYE} />
</button>
</div>
);
};
@@ -22,5 +22,9 @@ export const TimeAgo = ({ date, ...props }: TimeAgoProps) => {
return <>{t('Date unknown')}</>;
}
return <span {...props}>{t(`${distanceToNow} ago`)}</span>;
return (
<span {...props} title={date} className="underline decoration-dotted">
{t(`${distanceToNow} ago`)}
</span>
);
};
@@ -15,6 +15,7 @@ import isUndefined from 'lodash/isUndefined';
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
import { TxDetailsChainEventWithdrawal } from './tx-erc20-withdrawal';
import { TxDetailsChainEventErc20AssetDelist } from './tx-erc20-asset-delist';
import { TxDetailsContractCall } from './tx-contract-call';
interface ChainEventProps {
txData: BlockExplorerTransactionResult | undefined;
@@ -38,7 +39,7 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
return null;
}
const { builtin, erc20, erc20Multisig, stakingEvent } =
const { builtin, erc20, erc20Multisig, stakingEvent, contractCall } =
txData.command.chainEvent;
// Builtin Asset events
@@ -140,6 +141,10 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
}
}
if (contractCall) {
return <TxDetailsContractCall contractCall={contractCall} />;
}
// If we hit this return, tx-shared-details should give a basic overview
return null;
};
@@ -0,0 +1,26 @@
import { decodeEthCallResult } from './tx-contract-call';
import { base64 } from 'ethers/lib/utils';
import { defaultAbiCoder } from '@ethersproject/abi';
import { BigNumber } from '@ethersproject/bignumber';
describe('decodeEthCallResult', () => {
it('should decode contractData correctly (mocked)', () => {
const mockContractData = base64.encode(
defaultAbiCoder.encode(['int256'], [BigNumber.from(123)])
);
const result = decodeEthCallResult(mockContractData);
expect(result).toBe('123');
});
it('should decode contractData correctly (known data)', () => {
const mockContractData = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADH8cueyY=';
const result = decodeEthCallResult(mockContractData);
expect(result).toBe('3435020581670');
});
it('should return "-" when an error occurs', () => {
const mockContractData = 'invalid_data';
const result = decodeEthCallResult(mockContractData);
expect(result).toBe('-');
});
});
@@ -0,0 +1,102 @@
import { TableCell, TableRow } from '../../../table';
import { t } from '@vegaprotocol/i18n';
import {
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/external-explorer-link/external-explorer-link';
import { getExternalChainLabel } from '../../../links/external-explorer-link/external-chain';
import type { components } from '../../../../../types/explorer';
import { defaultAbiCoder, base64 } from 'ethers/lib/utils';
import { BigNumber } from 'ethers';
import OracleLink from '../../../links/oracle-link/oracle-link';
import { useExplorerOracleSpecByIdQuery } from '../../../../routes/oracles/__generated__/Oracles';
import { OracleEthSource } from '../../../../routes/oracles/components/oracle-eth-source';
/**
* Decodes the b64/ABIcoded result from an eth cal
* @param data
* @returns
*/
export function decodeEthCallResult(contractData: string): string {
try {
const rawResult = defaultAbiCoder.decode(
['int256'],
base64.decode(contractData)
);
// Finally, convert the resulting BigNumber in to a string
const res = BigNumber.from(rawResult[0]).toString();
return res;
} catch (e) {
return '-';
}
}
interface TxDetailsContractCallProps {
contractCall: components['schemas']['vegaEthContractCallEvent'];
}
export const TxDetailsContractCall = ({
contractCall,
}: TxDetailsContractCallProps) => {
const { data } = useExplorerOracleSpecByIdQuery({
variables: {
id: contractCall.specId || '1',
},
});
if (!contractCall) {
return null;
}
const chainLabel = getExternalChainLabel(contractCall.sourceChainId);
return (
<>
{contractCall.specId && (
<TableRow modifier="bordered">
<TableCell>{t('Oracle')}</TableCell>
<TableCell>
<OracleLink
id={contractCall.specId}
hasSeenOracleReports={true}
status={data?.oracleSpec?.dataSourceSpec.spec.status || '-'}
/>
</TableCell>
</TableRow>
)}
{contractCall.blockHeight && (
<TableRow modifier="bordered">
<TableCell>
{chainLabel} {t('block')}
</TableCell>
<TableCell>
<ExternalExplorerLink
chain={contractCall.sourceChainId}
id={contractCall.blockHeight}
type={EthExplorerLinkTypes.block}
/>
</TableCell>
</TableRow>
)}
{data?.oracleSpec?.dataSourceSpec && (
<OracleEthSource
chain={contractCall.sourceChainId}
sourceType={data.oracleSpec.dataSourceSpec.spec.data.sourceType}
/>
)}
{contractCall.error && (
<TableRow modifier="bordered">
<TableCell>{t('Call error')}</TableCell>
<TableCell>{contractCall.error}</TableCell>
</TableRow>
)}
{contractCall.result && (
<TableRow modifier="bordered">
<TableCell>{t('Result')}</TableCell>
<TableCell>{decodeEthCallResult(contractCall.result)}</TableCell>
</TableRow>
)}
</>
);
};
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links';
import {
EthExplorerLink,
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
} from '../../../links/external-explorer-link/external-explorer-link';
interface TxDetailsChainEventErc20AssetLimitsUpdatedProps {
assetLimitsUpdated: components['schemas']['vegaERC20AssetLimitsUpdated'];
@@ -42,7 +42,7 @@ export const TxDetailsChainEventErc20AssetLimitsUpdated = ({
<TableRow modifier="bordered">
<TableCell>{t('ERC20 asset')}</TableCell>
<TableCell>
<EthExplorerLink
<ExternalExplorerLink
id={assetLimitsUpdated.sourceEthereumAddress}
type={EthExplorerLinkTypes.address}
/>
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links';
import {
EthExplorerLink,
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
} from '../../../links/external-explorer-link/external-explorer-link';
interface TxDetailsChainEventErc20AssetListProps {
assetList: components['schemas']['vegaERC20AssetList'];
@@ -32,7 +32,7 @@ export const TxDetailsChainEventErc20AssetList = ({
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>
<EthExplorerLink
<ExternalExplorerLink
id={assetList.assetSource}
type={EthExplorerLinkTypes.address}
/>
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink, PartyLink } from '../../../links';
import {
EthExplorerLink,
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
} from '../../../links/external-explorer-link/external-explorer-link';
interface TxDetailsChainEventProps {
deposit: components['schemas']['vegaERC20Deposit'];
@@ -36,7 +36,7 @@ export const TxDetailsChainEventDeposit = ({
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>
<EthExplorerLink
<ExternalExplorerLink
id={deposit.sourceEthereumAddress}
type={EthExplorerLinkTypes.address}
/>
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { AssetLink } from '../../../links';
import {
EthExplorerLink,
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
} from '../../../links/external-explorer-link/external-explorer-link';
interface TxDetailsChainEventWithdrawalProps {
withdrawal: components['schemas']['vegaERC20Withdrawal'];
@@ -35,7 +35,7 @@ export const TxDetailsChainEventWithdrawal = ({
<TableRow modifier="bordered">
<TableCell>{t('Recipient')}</TableCell>
<TableCell>
<EthExplorerLink
<ExternalExplorerLink
id={withdrawal.targetEthereumAddress}
type={EthExplorerLinkTypes.address}
/>
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { PartyLink } from '../../../links';
import {
EthExplorerLink,
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
} from '../../../links/external-explorer-link/external-explorer-link';
interface TxDetailsChainEventStakeDepositProps {
deposit: components['schemas']['vegaStakeDeposited'];
@@ -39,7 +39,7 @@ export const TxDetailsChainEventStakeDeposit = ({
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>
<EthExplorerLink
<ExternalExplorerLink
id={deposit.ethereumAddress}
type={EthExplorerLinkTypes.address}
/>
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import { PartyLink } from '../../../links';
import {
EthExplorerLink,
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
} from '../../../links/external-explorer-link/external-explorer-link';
interface TxDetailsChainEventStakeRemoveProps {
remove: components['schemas']['vegaStakeRemoved'];
@@ -39,7 +39,7 @@ export const TxDetailsChainEventStakeRemove = ({
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>
<EthExplorerLink
<ExternalExplorerLink
id={remove.ethereumAddress}
type={EthExplorerLinkTypes.address}
/>
@@ -3,9 +3,9 @@ import { t } from '@vegaprotocol/i18n';
import { TableRow, TableCell } from '../../../table';
import type { components } from '../../../../../types/explorer';
import {
EthExplorerLink,
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
} from '../../../links/external-explorer-link/external-explorer-link';
interface TxDetailsChainEventStakeTotalSupplyProps {
update: components['schemas']['vegaStakeTotalSupply'];
@@ -38,7 +38,7 @@ export const TxDetailsChainEventStakeTotalSupply = ({
<TableRow modifier="bordered">
<TableCell>{t('Source')}</TableCell>
<TableCell>
<EthExplorerLink
<ExternalExplorerLink
id={update.tokenAddress}
type={EthExplorerLinkTypes.address}
/>
@@ -1,6 +0,0 @@
query ExplorerSettlementAssetForMarket($id: ID!) {
market(id: $id) {
id
decimalPlaces
}
}
@@ -1,49 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ExplorerSettlementAssetForMarketQueryVariables = Types.Exact<{
id: Types.Scalars['ID'];
}>;
export type ExplorerSettlementAssetForMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number } | null };
export const ExplorerSettlementAssetForMarketDocument = gql`
query ExplorerSettlementAssetForMarket($id: ID!) {
market(id: $id) {
id
decimalPlaces
}
}
`;
/**
* __useExplorerSettlementAssetForMarketQuery__
*
* To run a query within a React component, call `useExplorerSettlementAssetForMarketQuery` and pass it any options that fit your needs.
* When your component renders, `useExplorerSettlementAssetForMarketQuery` 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 } = useExplorerSettlementAssetForMarketQuery({
* variables: {
* id: // value for 'id'
* },
* });
*/
export function useExplorerSettlementAssetForMarketQuery(baseOptions: Apollo.QueryHookOptions<ExplorerSettlementAssetForMarketQuery, ExplorerSettlementAssetForMarketQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ExplorerSettlementAssetForMarketQuery, ExplorerSettlementAssetForMarketQueryVariables>(ExplorerSettlementAssetForMarketDocument, options);
}
export function useExplorerSettlementAssetForMarketLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerSettlementAssetForMarketQuery, ExplorerSettlementAssetForMarketQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ExplorerSettlementAssetForMarketQuery, ExplorerSettlementAssetForMarketQueryVariables>(ExplorerSettlementAssetForMarketDocument, options);
}
export type ExplorerSettlementAssetForMarketQueryHookResult = ReturnType<typeof useExplorerSettlementAssetForMarketQuery>;
export type ExplorerSettlementAssetForMarketLazyQueryHookResult = ReturnType<typeof useExplorerSettlementAssetForMarketLazyQuery>;
export type ExplorerSettlementAssetForMarketQueryResult = Apollo.QueryResult<ExplorerSettlementAssetForMarketQuery, ExplorerSettlementAssetForMarketQueryVariables>;
@@ -1,131 +0,0 @@
import { MockedProvider } from '@apollo/client/testing';
import { render } from '@testing-library/react';
import { Side } from '@vegaprotocol/types';
import type { LiquidityOrder } from '@vegaprotocol/types';
import { PeggedReference } from '@vegaprotocol/types';
import { LiquidityProvisionDetailsRow } from './liquidity-provision-details-row';
import type { VegaSide } from './liquidity-provision-details-row';
describe('LiquidityProvisionDetails component', () => {
function renderComponent(
order: LiquidityOrder,
side: VegaSide,
normaliseProportionsTo: number,
marketId: string
) {
return render(
<MockedProvider>
<table>
<tbody data-testid="container">
<LiquidityProvisionDetailsRow
order={order}
marketId={marketId}
normaliseProportionsTo={normaliseProportionsTo}
side={side}
/>
</tbody>
</table>
</MockedProvider>
);
}
it('renders null for an order with no proportion', () => {
const mockOrder = {
offset: '1',
reference: PeggedReference.PEGGED_REFERENCE_MID,
};
const res = renderComponent(
mockOrder as LiquidityOrder,
Side.SIDE_BUY,
100,
'123'
);
expect(res.getByTestId('container')).toBeEmptyDOMElement();
});
it('renders null for a null order', () => {
const res = renderComponent(
null as unknown as LiquidityOrder,
Side.SIDE_BUY,
100,
'123'
);
expect(res.getByTestId('container')).toBeEmptyDOMElement();
});
it('renders a row when the order is as expected', () => {
const mockOrder = {
offset: '1',
proportion: 20,
reference: PeggedReference.PEGGED_REFERENCE_MID,
};
const res = renderComponent(
mockOrder as LiquidityOrder,
Side.SIDE_BUY,
100,
'123'
);
// Row test ids and keys are based on the side, reference and proportion
expect(res.getByTestId('SIDE_BUY-20-1')).toBeInTheDocument();
expect(res.getByText('+1')).toBeInTheDocument();
expect(res.getByText('Mid')).toBeInTheDocument();
expect(res.getByText('20%')).toBeInTheDocument();
});
it('normalises offsets when normaliseToProportion is not 100', () => {
const mockOrder = {
offset: '1',
proportion: 20,
reference: PeggedReference.PEGGED_REFERENCE_BEST_BID,
};
const res = renderComponent(
mockOrder as LiquidityOrder,
Side.SIDE_SELL,
50,
'123'
);
// Row test ids and keys are based on the side, reference and proportion - and that proportion is scaled
expect(res.getByTestId('SIDE_SELL-40-1')).toBeInTheDocument();
expect(res.getByText('-1')).toBeInTheDocument();
expect(res.getByText('Best Bid')).toBeInTheDocument();
expect(res.getByText('40%')).toBeInTheDocument();
});
it('handles a missing offset gracefully (should not happen)', () => {
const mockOrder = {
proportion: 20,
reference: PeggedReference.PEGGED_REFERENCE_BEST_BID,
};
const res = renderComponent(
mockOrder as LiquidityOrder,
Side.SIDE_SELL,
50,
'123'
);
// Row test ids and keys are based on the side, reference and proportion - and that proportion is scaled
expect(res.getByTestId('SIDE_SELL-40-')).toBeInTheDocument();
expect(res.getByText('-')).toBeInTheDocument();
});
it('handles a missing reference gracefully (should not happen)', () => {
const mockOrder = {
offset: '1',
proportion: 20,
};
const res = renderComponent(
mockOrder as LiquidityOrder,
Side.SIDE_SELL,
50,
'123'
);
// Row test ids and keys are based on the side, reference and proportion - and that proportion is scaled
expect(res.getByTestId('SIDE_SELL-40-1')).toBeInTheDocument();
expect(res.getByText('40%')).toBeInTheDocument();
expect(res.getByText('-')).toBeInTheDocument();
});
});
@@ -1,73 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import type { components } from '../../../../../../types/explorer';
import { TableRow } from '../../../../table';
import { LiquidityProvisionOffset } from './liquidity-provision-offset';
export type VegaPeggedReference = components['schemas']['vegaPeggedReference'];
export type VegaSide = components['schemas']['vegaSide'];
export type LiquidityProvisionOrder =
components['schemas']['vegaLiquidityOrder'];
export const LiquidityReferenceLabel: Record<VegaPeggedReference, string> = {
PEGGED_REFERENCE_BEST_ASK: t('Best Ask'),
PEGGED_REFERENCE_BEST_BID: t('Best Bid'),
PEGGED_REFERENCE_MID: t('Mid'),
PEGGED_REFERENCE_UNSPECIFIED: '-',
};
export type LiquidityProvisionDetailsRowProps = {
order?: LiquidityProvisionOrder;
marketId?: string;
side: VegaSide;
// If this is
normaliseProportionsTo: number;
};
/**
*
* Note: offset is formatted by settlement asset on the market, assuming that is available
* Note: Due to the mix of references (MID vs BEST_X), it's not possible to correctly order
* the orders by their actual distance from a midpoint. This would require us knowing
* the best bid (now or at placement) and the mid. Getting the data for *now* would be
* misleading for LP submissions in the past. There is no API for getting <mid />
* at the time of a transaction.
*/
export function LiquidityProvisionDetailsRow({
normaliseProportionsTo,
order,
side,
marketId,
}: LiquidityProvisionDetailsRowProps) {
if (!order || !order.proportion) {
return null;
}
const proportion =
normaliseProportionsTo === 100
? order.proportion
: Math.round((order.proportion / normaliseProportionsTo) * 100);
const key = `${side}-${proportion}-${order.offset ? order.offset : ''}`;
return (
<TableRow modifier="bordered" key={key} data-testid={key}>
<td className="text-right px-2">
{order.offset && marketId ? (
<LiquidityProvisionOffset
offset={order.offset}
side={side}
marketId={marketId}
/>
) : (
'-'
)}
</td>
<td className="text-center">
{order.reference ? LiquidityReferenceLabel[order.reference] : '-'}
</td>
<td className="text-center">{proportion}%</td>
</TableRow>
);
}
@@ -1,22 +0,0 @@
import { render } from '@testing-library/react';
import { LiquidityProvisionMid } from './liquidity-provision-mid';
describe('LiquidityProvisionMid component', () => {
function renderComponent() {
return render(
<table>
<tbody data-testid="container">
<LiquidityProvisionMid />
</tbody>
</table>
);
}
it('renders a basic row that spans the whole table', () => {
const res = renderComponent();
const display = res.getByTestId('mid-display');
expect(res.getByTestId('mid')).toBeInTheDocument();
expect(display).toBeInTheDocument();
expect(display).toHaveAttribute('colspan', '3');
});
});
@@ -1,17 +0,0 @@
import { TableRow } from '../../../../table';
/**
* In a LiquidityProvision table, this row is the midpoint. Above our LP orders on the
* buy side, below are LP orders on the sell side. This component simply divides them.
*
* There is no API that can give us the mid price when the order was created, and even
* if there was it isn't clear that would be appropriate for this centre row. So instead
* it's a simple divider.
*/
export function LiquidityProvisionMid() {
return (
<TableRow modifier="bordered" data-testid="mid">
<td data-testid="mid-display" colSpan={3} className="bg-white"></td>
</TableRow>
);
}
@@ -1,67 +0,0 @@
import { MockedProvider } from '@apollo/client/testing';
import type { MockedResponse } from '@apollo/client/testing';
import { render } from '@testing-library/react';
import { ExplorerSettlementAssetForMarketDocument } from '../__generated__/Explorer-settlement-asset';
import type { ExplorerSettlementAssetForMarketQuery } from '../__generated__/Explorer-settlement-asset';
import type { VegaSide } from './liquidity-provision-details-row';
import {
getFormattedOffset,
LiquidityProvisionOffset,
} from './liquidity-provision-offset';
const decimalsMock: ExplorerSettlementAssetForMarketQuery = {
market: {
id: '123',
__typename: 'Market',
decimalPlaces: 5,
},
};
describe('LiquidityProvisionOffset component', () => {
function renderComponent(
offset: string,
side: VegaSide,
marketId: string,
mocks: MockedResponse[]
) {
return render(
<MockedProvider mocks={mocks}>
<LiquidityProvisionOffset
offset={offset}
side={side}
marketId={marketId}
/>
</MockedProvider>
);
}
it('renders a simple row before market data comes in', () => {
const res = renderComponent('1', 'SIDE_BUY', '123', []);
expect(res.getByText('+1')).toBeInTheDocument();
});
it('replaces unformatted with formatted if the market data comes in', () => {
const mock = {
request: {
query: ExplorerSettlementAssetForMarketDocument,
variables: {
id: '123',
},
result: {
data: decimalsMock,
},
},
};
const res = renderComponent('1', 'SIDE_BUY', '123', [mock]);
expect(res.getByText('+1')).toBeInTheDocument();
});
it('getFormattedOffset returns the unformatted offset if there is not enough data', () => {
const res = getFormattedOffset('1', {});
expect(res).toEqual('1');
});
it('getFormattedOffset decimal formats a number if it comes in with market data', () => {
const res = getFormattedOffset('1', decimalsMock);
expect(res).toEqual('0.00001');
});
});
@@ -1,59 +0,0 @@
import { useExplorerSettlementAssetForMarketQuery } from '../__generated__/Explorer-settlement-asset';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import type { ExplorerSettlementAssetForMarketQuery } from '../__generated__/Explorer-settlement-asset';
import type { VegaSide } from './liquidity-provision-details-row';
export type LiquidityProvisionOffsetProps = {
side: VegaSide;
offset: string;
marketId: string;
};
/**
* Correctly formats an LP's offset according to the market settlement decimal places.
* Initially this will appear unformatted, then when the query loads in the proper formatted
* value will be displayed
*
* @see getFormattedOffset
*/
export function LiquidityProvisionOffset({
side,
offset,
marketId,
}: LiquidityProvisionOffsetProps) {
const { data } = useExplorerSettlementAssetForMarketQuery({
variables: {
id: marketId,
},
});
// getFormattedOffset handles missing results/loading states
const formattedOffset = getFormattedOffset(offset, data);
const label = side === 'SIDE_BUY' ? '+' : '-';
const className = side === 'SIDE_BUY' ? 'text-vega-green' : 'text-vega-pink';
return <span className={className}>{`${label}${formattedOffset}`}</span>;
}
/**
* Does the work of formatting the number now we have the market decimal places.
* If no market data is assigned (i.e. during loading, or if the market doesn't exist)
* this function will return the unformatted number
*
* @see LiquidityProvisionOffset
* @param data the result of a ExplorerSettlementAssetForMarketQuery
* @param offset the unformatted offset
* @returns string the offset of this lp order formatted with the settlement decimal places
*/
export function getFormattedOffset(
offset: string,
data?: ExplorerSettlementAssetForMarketQuery
) {
const decimals = data?.market?.decimalPlaces;
if (!decimals) {
return offset;
}
return addDecimalsFormatNumber(offset, decimals);
}
@@ -1,209 +0,0 @@
import { MockedProvider } from '@apollo/client/testing';
import { render } from '@testing-library/react';
import type { LiquidityOrder } from '@vegaprotocol/types';
import { PeggedReference } from '@vegaprotocol/types';
import type { LiquiditySubmission } from '../tx-liquidity-submission';
import {
LiquidityProvisionDetails,
sumProportions,
} from './liquidity-provision-details';
function mockProportion(proportion: number): LiquidityOrder {
return {
proportion,
reference: PeggedReference.PEGGED_REFERENCE_MID,
offset: '1',
};
}
describe('sumProportions function', () => {
it('returns 0 if the side is undefined', () => {
const side: LiquidityOrder[] = undefined as unknown as LiquidityOrder[];
const res = sumProportions(side);
expect(res).toEqual(0);
});
it('returns 0 if the side is empty', () => {
const side: LiquidityOrder[] = [];
const res = sumProportions(side);
expect(res).toEqual(0);
});
it('sums 1 item correctly (under 100%)', () => {
const side: LiquidityOrder[] = [mockProportion(10)];
const res = sumProportions(side);
expect(res).toEqual(10);
});
it('sums 2 item correctly (exactly 100%)', () => {
const side: LiquidityOrder[] = [mockProportion(50), mockProportion(50)];
const res = sumProportions(side);
expect(res).toEqual(100);
});
it('sums 3 item correctly to over 100%', () => {
const side: LiquidityOrder[] = [
mockProportion(20),
mockProportion(40),
mockProportion(50),
];
const res = sumProportions(side);
expect(res).toEqual(110);
});
});
describe('LiquidityProvisionDetails component', () => {
function renderComponent(provision: LiquiditySubmission) {
return render(
<MockedProvider>
<LiquidityProvisionDetails provision={provision} />
</MockedProvider>
);
}
it('handles an LP with no buys or sells by returning empty (should never happen)', () => {
const mock: LiquiditySubmission = {};
const res = renderComponent(mock);
expect(res.container).toBeEmptyDOMElement();
});
it('handles an LP with no sells by just rendering buys', () => {
const mock: LiquiditySubmission = {
marketId: '123',
buys: [
{
offset: '1',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
{
offset: '2',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
],
};
const res = renderComponent(mock);
expect(res.getByText('Price offset')).toBeInTheDocument();
expect(res.getByText('Price reference')).toBeInTheDocument();
expect(res.getByText('Proportion')).toBeInTheDocument();
expect(res.getByTestId('SIDE_BUY-50-1')).toBeInTheDocument();
expect(res.getByTestId('SIDE_BUY-50-2')).toBeInTheDocument();
});
it('handles an LP with no buys by just rendering sells', () => {
const mock: LiquiditySubmission = {
marketId: '123',
sells: [
{
offset: '1',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
{
offset: '2',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
],
};
const res = renderComponent(mock);
expect(res.getByText('Price offset')).toBeInTheDocument();
expect(res.getByText('Price reference')).toBeInTheDocument();
expect(res.getByText('Proportion')).toBeInTheDocument();
expect(res.getByTestId('SIDE_SELL-50-1')).toBeInTheDocument();
expect(res.getByTestId('SIDE_SELL-50-2')).toBeInTheDocument();
});
it('handles an LP with sells by just rendering buys', () => {
const mock: LiquiditySubmission = {
marketId: '123',
buys: [
{
offset: '1',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
{
offset: '2',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
],
};
const res = renderComponent(mock);
expect(res.getByText('Price offset')).toBeInTheDocument();
expect(res.getByText('Price reference')).toBeInTheDocument();
expect(res.getByText('Proportion')).toBeInTheDocument();
expect(res.getByTestId('SIDE_BUY-50-1')).toBeInTheDocument();
expect(res.getByTestId('SIDE_BUY-50-2')).toBeInTheDocument();
});
it('handles an LP with both sides', () => {
const mock: LiquiditySubmission = {
marketId: '123',
buys: [
{
offset: '1',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
{
offset: '2',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
],
sells: [
{
offset: '4',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
{
offset: '2',
proportion: 50,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
],
};
const res = renderComponent(mock);
expect(res.getByText('Price offset')).toBeInTheDocument();
expect(res.getByText('Price reference')).toBeInTheDocument();
expect(res.getByText('Proportion')).toBeInTheDocument();
expect(res.getByTestId('SIDE_BUY-50-1')).toBeInTheDocument();
expect(res.getByTestId('SIDE_BUY-50-2')).toBeInTheDocument();
expect(res.getByTestId('SIDE_SELL-50-4')).toBeInTheDocument();
expect(res.getByTestId('SIDE_SELL-50-2')).toBeInTheDocument();
});
it('normalises proportions when they do not total 100%', () => {
const mock: LiquiditySubmission = {
marketId: '123',
buys: [
{
offset: '1',
proportion: 25,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
{
offset: '2',
proportion: 30,
reference: PeggedReference.PEGGED_REFERENCE_MID,
},
],
};
const res = renderComponent(mock);
expect(res.getByText('45%')).toBeInTheDocument();
expect(res.getByText('55%')).toBeInTheDocument();
});
});
@@ -1,94 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import type { components } from '../../../../../types/explorer';
import type { LiquiditySubmission } from '../tx-liquidity-submission';
import { TableRow } from '../../../table';
import { LiquidityProvisionMid } from './components/liquidity-provision-mid';
import { LiquidityProvisionDetailsRow } from './components/liquidity-provision-details-row';
import { Side } from '@vegaprotocol/types';
export type VegaPeggedReference = components['schemas']['vegaPeggedReference'];
export type LiquidityProvisionOrder =
components['schemas']['vegaLiquidityOrder'];
export const LiquidityReferenceLabel: Record<VegaPeggedReference, string> = {
PEGGED_REFERENCE_BEST_ASK: t('Best Ask'),
PEGGED_REFERENCE_BEST_BID: t('Best Bid'),
PEGGED_REFERENCE_MID: t('Mid'),
PEGGED_REFERENCE_UNSPECIFIED: '-',
};
/**
* Given a side of a liquidity provision order, returns the total
* It should be 100%, but it isn't always and if it isn't the proportion
* reported for each order should be scaled
*
* @returns number
*/
export function sumProportions(
side: LiquiditySubmission['buys'] | LiquiditySubmission['sells']
): number {
if (!side || side.length === 0) {
return 0;
}
return side.reduce((total, o) => total + (o.proportion || 0), 0);
}
export type LiquidityProvisionDetailsProps = {
provision: LiquiditySubmission;
};
/**
* Renders a table displaying all buys and sells in this LP. It is valid for there
* to be no buys or sells.
*
* It might seem logical to turn proportions in to values based on the total commitment
* but based on the current API structure it is awkward, and given that non-LP orders
* will change the amount that is actually deployed vs assigned to a level, we decided
* not to bother going down that route.
*/
export function LiquidityProvisionDetails({
provision,
}: LiquidityProvisionDetailsProps) {
if (!provision.buys?.length && !provision.sells?.length) {
return null;
}
// We need to do some additional calcs if these aren't both 100
const buyTotal = sumProportions(provision.buys);
const sellTotal = sumProportions(provision.sells);
return (
<table>
<thead>
<TableRow modifier="bordered">
<th className="px-2 pb-1">{t('Price offset')}</th>
<th className="px-2 pb-1">{t('Price reference')}</th>
<th className="px-2 pb-1">{t('Proportion')}</th>
</TableRow>
</thead>
<tbody>
{provision.buys?.map((b, i) => (
<LiquidityProvisionDetailsRow
order={b}
marketId={provision.marketId}
side={Side.SIDE_BUY}
key={`SIDE_BUY-${i}`}
normaliseProportionsTo={buyTotal}
/>
))}
<LiquidityProvisionMid />
{provision.sells?.map((s, i) => (
<LiquidityProvisionDetailsRow
order={s}
marketId={provision.marketId}
side={Side.SIDE_SELL}
key={`SIDE_SELL-${i}`}
normaliseProportionsTo={sellTotal}
/>
))}
</tbody>
</table>
);
}
@@ -1,11 +1,20 @@
import { t } from '@vegaprotocol/i18n';
import type { components } from '../../../../../types/explorer';
import { TableCell, TableRow } from '../../../table';
import type { VegaPeggedReference } from '../liquidity-provision/liquidity-provision-details';
import { Side, PeggedReferenceMapping } from '@vegaprotocol/types';
import { useExplorerMarketQuery } from '../../../links/market-link/__generated__/Market';
import type { ExplorerMarketQuery } from '../../../links/market-link/__generated__/Market';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
export type VegaPeggedReference = components['schemas']['vegaPeggedReference'];
export const LiquidityReferenceLabel: Record<VegaPeggedReference, string> = {
PEGGED_REFERENCE_BEST_ASK: t('Best Ask'),
PEGGED_REFERENCE_BEST_BID: t('Best Bid'),
PEGGED_REFERENCE_MID: t('Mid'),
PEGGED_REFERENCE_UNSPECIFIED: '-',
};
export interface TxDetailsOrderProps {
offset: string;
reference: VegaPeggedReference;
@@ -1,7 +1,14 @@
query ExplorerProposalStatus($id: ID!) {
proposal(id: $id) {
id
state
rejectionReason
... on Proposal {
id
state
rejectionReason
}
... on BatchProposal {
id
state
rejectionReason
}
}
}
@@ -8,15 +8,22 @@ export type ExplorerProposalStatusQueryVariables = Types.Exact<{
}>;
export type ExplorerProposalStatusQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, state: Types.ProposalState, rejectionReason?: Types.ProposalRejectionReason | null } | null };
export type ExplorerProposalStatusQuery = { __typename?: 'Query', proposal?: { __typename?: 'BatchProposal', id?: string | null, state: Types.ProposalState, rejectionReason?: Types.ProposalRejectionReason | null } | { __typename?: 'Proposal', id?: string | null, state: Types.ProposalState, rejectionReason?: Types.ProposalRejectionReason | null } | null };
export const ExplorerProposalStatusDocument = gql`
query ExplorerProposalStatus($id: ID!) {
proposal(id: $id) {
id
state
rejectionReason
... on Proposal {
id
state
rejectionReason
}
... on BatchProposal {
id
state
rejectionReason
}
}
}
`;
@@ -0,0 +1,257 @@
import { render, screen } from '@testing-library/react';
import { BatchItem } from './batch-item';
import { MemoryRouter } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing';
import type { components } from '../../../../../types/explorer';
type Item = components['schemas']['vegaBatchProposalTermsChange'];
describe('BatchItem', () => {
it('Renders "Unknown proposal type" by default', () => {
const item = {};
render(<BatchItem item={item} />);
expect(screen.getByText('Unknown proposal type')).toBeInTheDocument();
});
it('Renders "Unknown proposal type" for unknown items', () => {
const item = {
newLochNessMonster: {
location: 'Loch Ness',
},
} as unknown as Item;
render(<BatchItem item={item} />);
expect(screen.getByText('Unknown proposal type')).toBeInTheDocument();
});
it('Renders "New spot market"', () => {
const item = {
newSpotMarket: {},
};
render(<BatchItem item={item} />);
expect(screen.getByText('New spot market')).toBeInTheDocument();
});
it('Renders "Cancel transfer"', () => {
const item = {
cancelTransfer: {
changes: {
transferId: 'transfer123',
},
},
};
render(<BatchItem item={item} />);
expect(screen.getByText('Cancel transfer')).toBeInTheDocument();
expect(screen.getByText('transf')).toBeInTheDocument();
});
it('Renders "Cancel transfer" without an id', () => {
const item = {
cancelTransfer: {
changes: {},
},
};
render(<BatchItem item={item} />);
expect(screen.getByText('Cancel transfer')).toBeInTheDocument();
});
it('Renders "New freeform"', () => {
const item = {
newFreeform: {},
};
render(<BatchItem item={item} />);
expect(screen.getByText('New freeform proposal')).toBeInTheDocument();
});
it('Renders "New market"', () => {
const item = {
newMarket: {},
};
render(<BatchItem item={item} />);
expect(screen.getByText('New market')).toBeInTheDocument();
});
it('Renders "New transfer"', () => {
const item = {
newTransfer: {},
};
render(<BatchItem item={item} />);
expect(screen.getByText('New transfer')).toBeInTheDocument();
});
it('Renders "Update asset" with assetId', () => {
const item = {
updateAsset: {
assetId: 'asset123',
},
};
render(
<MemoryRouter>
<MockedProvider>
<BatchItem item={item} />
</MockedProvider>
</MemoryRouter>
);
expect(screen.getByText('Update asset')).toBeInTheDocument();
expect(screen.getByText('asset123')).toBeInTheDocument();
});
it('Renders "Update asset" even if assetId is not set', () => {
const item = {
updateAsset: {
assetId: undefined,
},
};
render(<BatchItem item={item} />);
expect(screen.getByText('Update asset')).toBeInTheDocument();
});
it('Renders "Update market state" with marketId', () => {
const item = {
updateMarketState: {
changes: {
marketId: 'market123',
},
},
};
render(
<MemoryRouter>
<MockedProvider>
<BatchItem item={item} />
</MockedProvider>
</MemoryRouter>
);
expect(screen.getByText('Update market state')).toBeInTheDocument();
expect(screen.getByText('market123')).toBeInTheDocument();
});
it('Renders "Update market state" even if marketId is not set', () => {
const item = {
updateMarketState: {
changes: {
marketId: undefined,
},
},
};
render(
<MemoryRouter>
<MockedProvider>
<BatchItem item={item} />
</MockedProvider>
</MemoryRouter>
);
expect(screen.getByText('Update market state')).toBeInTheDocument();
});
it('Renders "Update network parameter" with parameter', () => {
const item = {
updateNetworkParameter: {
changes: {
key: 'parameter123',
},
},
};
render(
<MockedProvider>
<MemoryRouter>
<BatchItem item={item} />
</MemoryRouter>
</MockedProvider>
);
expect(screen.getByText('Update network parameter')).toBeInTheDocument();
expect(screen.getByText('parameter123')).toBeInTheDocument();
});
it('Renders "Update network parameter" even if parameter is not set', () => {
const item = {
updateNetworkParameter: {
changes: {
key: undefined,
},
},
};
render(<BatchItem item={item} />);
expect(screen.getByText('Update network parameter')).toBeInTheDocument();
});
it('Renders "Update referral program"', () => {
const item = {
updateReferralProgram: {},
};
render(<BatchItem item={item} />);
expect(screen.getByText('Update referral program')).toBeInTheDocument();
});
it('Renders "Update spot market" with marketId', () => {
const item = {
updateSpotMarket: {
marketId: 'market123',
},
};
render(
<MemoryRouter>
<MockedProvider>
<BatchItem item={item} />
</MockedProvider>
</MemoryRouter>
);
expect(screen.getByText('Update spot market')).toBeInTheDocument();
expect(screen.getByText('market123')).toBeInTheDocument();
});
it('Renders "Update spot market" even if marketId is not set', () => {
const item = {
updateSpotMarket: {
marketId: undefined,
},
};
render(
<MemoryRouter>
<MockedProvider>
<BatchItem item={item} />
</MockedProvider>
</MemoryRouter>
);
expect(screen.getByText('Update spot market')).toBeInTheDocument();
});
it('Renders "Update market" with marketId', () => {
const item = {
updateMarket: {
marketId: 'market123',
},
};
render(
<MemoryRouter>
<MockedProvider>
<BatchItem item={item} />
</MockedProvider>
</MemoryRouter>
);
expect(screen.getByText('Update market')).toBeInTheDocument();
expect(screen.getByText('market123')).toBeInTheDocument();
});
it('Renders "Update market" even if marketId is not set', () => {
const item = {
updateMarket: {
marketId: undefined,
},
};
render(
<MemoryRouter>
<MockedProvider>
<BatchItem item={item} />
</MockedProvider>
</MemoryRouter>
);
expect(screen.getByText('Update market')).toBeInTheDocument();
});
it('Renders "Update volume discount program"', () => {
const item = {
updateVolumeDiscountProgram: {},
};
render(<BatchItem item={item} />);
expect(
screen.getByText('Update volume discount program')
).toBeInTheDocument();
});
});
@@ -0,0 +1,87 @@
import { t } from '@vegaprotocol/i18n';
import { AssetLink, MarketLink, NetworkParameterLink } from '../../../links';
import type { components } from '../../../../../types/explorer';
import Hash from '../../../links/hash';
type Item = components['schemas']['vegaBatchProposalTermsChange'];
export interface BatchItemProps {
item: Item;
}
/**
* Produces a one line summary for an item in a batch proposal. Could
* easily be adapted to summarise individual proposals, but there is no
* place for that yet.
*
* Details (like IDs) should be shown and linked if available, but handled
* if not available. This is adequate as the ProposalSummary component contains
* a JSON viewer for the full proposal.
*/
export const BatchItem = ({ item }: BatchItemProps) => {
if (item.cancelTransfer) {
const transferId = item?.cancelTransfer?.changes?.transferId || false;
return (
<span>
{t('Cancel transfer')}&nbsp;
{transferId && (
<Hash className="ml-1" truncate={true} text={transferId} />
)}
</span>
);
} else if (item.newFreeform) {
return <span>{t('New freeform proposal')}</span>;
} else if (item.newMarket) {
return <span>{t('New market')}</span>;
} else if (item.newSpotMarket) {
return <span>{t('New spot market')}</span>;
} else if (item.newTransfer) {
return <span>{t('New transfer')}</span>;
} else if (item.updateAsset) {
const assetId = item?.updateAsset?.assetId || false;
return (
<span>
{t('Update asset')}
{assetId && <AssetLink className="ml-1" assetId={assetId} />}
</span>
);
} else if (item.updateMarket) {
const marketId = item?.updateMarket?.marketId || false;
return (
<span>
{t('Update market')}{' '}
{marketId && <MarketLink className="ml-1" id={marketId} />}
</span>
);
} else if (item.updateMarketState) {
const marketId = item?.updateMarketState?.changes?.marketId || false;
return (
<span>
{t('Update market state')}
{marketId && <MarketLink className="ml-1" id={marketId} />}
</span>
);
} else if (item.updateNetworkParameter) {
const param = item?.updateNetworkParameter?.changes?.key || false;
return (
<span>
{t('Update network parameter')}
{param && <NetworkParameterLink className="ml-1" parameter={param} />}
</span>
);
} else if (item.updateReferralProgram) {
return <span>{t('Update referral program')}</span>;
} else if (item.updateSpotMarket) {
const marketId = item?.updateSpotMarket?.marketId || '';
return (
<span>
{t('Update spot market')}
<MarketLink className="ml-1" id={marketId} />
</span>
);
} else if (item.updateVolumeDiscountProgram) {
return <span>{t('Update volume discount program')}</span>;
}
return <span>{t('Unknown proposal type')}</span>;
};
@@ -14,16 +14,18 @@ export function format(date: string | undefined, def: string) {
return new Date().toLocaleDateString() || def;
}
export function getDate(
data: ExplorerProposalStatusQuery | undefined,
terms: Terms
): string {
type Proposal = Extract<
ExplorerProposalStatusQuery['proposal'],
{ __typename?: 'Proposal' }
>;
export function getDate(proposal: Proposal | undefined, terms: Terms): string {
const DEFAULT = t('Unknown');
if (!data?.proposal?.state) {
if (!proposal?.state) {
return DEFAULT;
}
switch (data.proposal.state) {
switch (proposal.state) {
case 'STATE_DECLINED':
return `${t('Rejected on')}: ${format(terms.closingTimestamp, DEFAULT)}`;
case 'STATE_ENACTED':
@@ -62,9 +64,11 @@ export const ProposalDate = ({ terms, id }: ProposalDateProps) => {
},
});
const proposal = data?.proposal as Proposal;
return (
<Lozenge className="font-sans text-xs float-right">
{getDate(data, terms)}
{getDate(proposal, terms)}
</Lozenge>
);
};
@@ -2,17 +2,8 @@ import { Icon, Tooltip } from '@vegaprotocol/ui-toolkit';
import type { IconProps } from '@vegaprotocol/ui-toolkit';
import { useExplorerProposalStatusQuery } from './__generated__/Proposal';
import type { ExplorerProposalStatusQuery } from './__generated__/Proposal';
import type * as Apollo from '@apollo/client';
import type * as Types from '@vegaprotocol/types';
import { t } from '@vegaprotocol/i18n';
type ProposalQueryResult = Apollo.QueryResult<
ExplorerProposalStatusQuery,
Types.Exact<{
id: string;
}>
>;
interface ProposalStatusIconProps {
id: string;
}
@@ -29,29 +20,38 @@ type IconAndLabel = {
* @param data a data result from useExplorerProposalStatusQuery
* @returns Icon name
*/
export function getIconAndLabelForStatus(
res: ProposalQueryResult
): IconAndLabel {
export function useIconAndLabelForStatus(id: string): IconAndLabel {
const { data, loading, error } = useExplorerProposalStatusQuery({
variables: {
id,
},
});
const proposal = data?.proposal as Extract<
ExplorerProposalStatusQuery['proposal'],
{ __typename?: 'Proposal' }
>;
const DEFAULT: IconAndLabel = {
icon: 'error',
label: t('Proposal state unknown'),
};
if (res.loading) {
if (loading) {
return {
icon: 'more',
label: t('Loading data'),
};
}
if (!res?.data?.proposal || res.error) {
if (!data?.proposal || error) {
return {
icon: 'error',
label: res.error?.message || DEFAULT.label,
label: error?.message || DEFAULT.label,
};
}
switch (res.data.proposal.state) {
switch (proposal.state) {
case 'STATE_DECLINED':
return {
icon: 'stop',
@@ -99,13 +99,7 @@ export function getIconAndLabelForStatus(
/**
*/
export const ProposalStatusIcon = ({ id }: ProposalStatusIconProps) => {
const { icon, label } = getIconAndLabelForStatus(
useExplorerProposalStatusQuery({
variables: {
id,
},
})
);
const { icon, label } = useIconAndLabelForStatus(id);
return (
<div className="float-left mr-3">
@@ -1,6 +1,4 @@
import type { ProposalTerms } from '../tx-proposal';
import { useState } from 'react';
import type { components } from '../../../../../types/explorer';
import { JsonViewerDialog } from '../../../dialogs/json-viewer-dialog';
import ProposalLink from '../../../links/proposal-link/proposal-link';
import truncate from 'lodash/truncate';
@@ -9,7 +7,12 @@ import ReactMarkdown from 'react-markdown';
import { ProposalDate } from './proposal-date';
import { t } from '@vegaprotocol/i18n';
import type { ProposalTerms } from '../tx-proposal';
import type { components } from '../../../../../types/explorer';
import { BatchItem } from './batch-item';
type Rationale = components['schemas']['vegaProposalRationale'];
type Batch = components['schemas']['v1BatchProposalSubmissionTerms']['changes'];
type ProposalTermsDialog = {
open: boolean;
@@ -21,6 +24,7 @@ interface ProposalSummaryProps {
id: string;
rationale?: Rationale;
terms?: ProposalTerms;
batch?: Batch;
}
/**
@@ -31,6 +35,7 @@ export const ProposalSummary = ({
id,
rationale,
terms,
batch,
}: ProposalSummaryProps) => {
const [dialog, setDialog] = useState<ProposalTermsDialog>({
open: false,
@@ -72,6 +77,18 @@ export const ProposalSummary = ({
</ReactMarkdown>
</div>
)}
{batch && (
<section className="pt-2 text-sm leading-tight my-3">
<h2 className="text-lg pb-1">{t('Changes')}</h2>
<ol>
{batch.map((change, index) => (
<li className="ml-4 list-decimal" key={`batch-${index}`}>
<BatchItem item={change} />
</li>
))}
</ol>
</section>
)}
<div className="pt-5">
<button className="underline max-md:hidden mr-5" onClick={openDialog}>
{t('View terms')}
@@ -0,0 +1,54 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ExplorerReferralCodeOwnerQueryVariables = Types.Exact<{
id: Types.Scalars['ID'];
}>;
export type ExplorerReferralCodeOwnerQuery = { __typename?: 'Query', referralSets: { __typename?: 'ReferralSetConnection', edges: Array<{ __typename?: 'ReferralSetEdge', node: { __typename?: 'ReferralSet', createdAt: any, updatedAt: any, referrer: string } } | null> } };
export const ExplorerReferralCodeOwnerDocument = gql`
query ExplorerReferralCodeOwner($id: ID!) {
referralSets(id: $id) {
edges {
node {
createdAt
updatedAt
referrer
}
}
}
}
`;
/**
* __useExplorerReferralCodeOwnerQuery__
*
* To run a query within a React component, call `useExplorerReferralCodeOwnerQuery` and pass it any options that fit your needs.
* When your component renders, `useExplorerReferralCodeOwnerQuery` 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 } = useExplorerReferralCodeOwnerQuery({
* variables: {
* id: // value for 'id'
* },
* });
*/
export function useExplorerReferralCodeOwnerQuery(baseOptions: Apollo.QueryHookOptions<ExplorerReferralCodeOwnerQuery, ExplorerReferralCodeOwnerQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ExplorerReferralCodeOwnerQuery, ExplorerReferralCodeOwnerQueryVariables>(ExplorerReferralCodeOwnerDocument, options);
}
export function useExplorerReferralCodeOwnerLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerReferralCodeOwnerQuery, ExplorerReferralCodeOwnerQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ExplorerReferralCodeOwnerQuery, ExplorerReferralCodeOwnerQueryVariables>(ExplorerReferralCodeOwnerDocument, options);
}
export type ExplorerReferralCodeOwnerQueryHookResult = ReturnType<typeof useExplorerReferralCodeOwnerQuery>;
export type ExplorerReferralCodeOwnerLazyQueryHookResult = ReturnType<typeof useExplorerReferralCodeOwnerLazyQuery>;
export type ExplorerReferralCodeOwnerQueryResult = Apollo.QueryResult<ExplorerReferralCodeOwnerQuery, ExplorerReferralCodeOwnerQueryVariables>;
@@ -0,0 +1,11 @@
query ExplorerReferralCodeOwner($id: ID!) {
referralSets(id: $id) {
edges {
node {
createdAt
updatedAt
referrer
}
}
}
}
@@ -0,0 +1,95 @@
import { render, waitFor } from '@testing-library/react';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import { MemoryRouter } from 'react-router-dom';
import { ReferralCodeOwner } from './referral-code-owner';
import type { ReferralCodeOwnerProps } from './referral-code-owner';
import { ExplorerReferralCodeOwnerDocument } from './__generated__/code-owner';
const renderComponent = (
props: ReferralCodeOwnerProps,
mocks: MockedResponse[]
) => {
return render(
<MockedProvider mocks={mocks}>
<MemoryRouter>
<ReferralCodeOwner {...props} />
</MemoryRouter>
</MockedProvider>
);
};
describe('ReferralCodeOwner', () => {
it('should render loading state', () => {
const mocks = [
{
request: {
query: ExplorerReferralCodeOwnerDocument,
variables: {
id: 'ABC123',
},
},
},
];
const { getByText } = renderComponent({ code: 'ABC123' }, mocks);
expect(getByText('Loading...')).toBeInTheDocument();
});
it('should render error state', async () => {
const errorMessage = 'Error fetching referrer: ABC123';
const mocks = [
{
request: {
query: ExplorerReferralCodeOwnerDocument,
variables: {
id: 'ABC123',
},
},
error: new Error('nope'),
},
];
const { getByText } = renderComponent({ code: 'ABC123' }, mocks);
await waitFor(() => {
expect(getByText(errorMessage)).toBeInTheDocument();
});
});
it('should render link to referring party', async () => {
const referrerId = 'DEF789';
const mocks = [
{
request: {
query: ExplorerReferralCodeOwnerDocument,
variables: {
id: 'ABC123',
},
},
result: {
data: {
referralSets: {
edges: [
{
node: {
__typename: 'ReferralSet',
referrer: referrerId,
createdAt: '123',
updatedAt: '456',
},
},
],
},
},
},
},
];
const { getByText } = renderComponent({ code: 'ABC123' }, mocks);
await waitFor(() => {
expect(getByText(referrerId)).toBeInTheDocument();
});
});
});
@@ -0,0 +1,26 @@
import { TableCell } from '../../../table';
import { useExplorerReferralCodeOwnerQuery } from './__generated__/code-owner';
import { PartyLink } from '../../../links';
export interface ReferralCodeOwnerProps {
code: string;
}
/**
* Render the owner of a referral code
*/
export const ReferralCodeOwner = ({ code }: ReferralCodeOwnerProps) => {
const { data, error, loading } = useExplorerReferralCodeOwnerQuery({
variables: {
id: code,
},
});
const referrer = data?.referralSets.edges[0]?.node.referrer || '';
return (
<TableCell>
{loading && 'Loading...'}
{error && `Error fetching referrer: ${code}`}
{referrer.length > 0 && <PartyLink id={referrer} />}
</TableCell>
);
};
@@ -0,0 +1,93 @@
import { render } from '@testing-library/react';
import { ReferralTeam } from './team';
import type { CreateReferralSet } from './team';
import { MockedProvider } from '@apollo/client/testing';
describe('ReferralTeam', () => {
const team = {
name: 'Test Team',
teamUrl: 'https://example.com/team',
avatarUrl: 'https://example.com/avatar',
closed: false,
};
const mockTx: CreateReferralSet = {
team,
};
const mockId = '123456';
const mockCreator = 'JohnDoe';
it('should render the team name', () => {
const { getByText } = render(
<MockedProvider>
<ReferralTeam tx={mockTx} id={mockId} creator={mockCreator} />
</MockedProvider>
);
expect(getByText('Test Team')).toBeInTheDocument();
});
it('should render the team ID', () => {
const { getByText } = render(
<MockedProvider>
<ReferralTeam tx={mockTx} id={mockId} creator={mockCreator} />
</MockedProvider>
);
expect(getByText('Id')).toBeInTheDocument();
expect(getByText(mockId)).toBeInTheDocument();
});
it('should render the creator', () => {
const { getByText } = render(
<MockedProvider>
<ReferralTeam tx={mockTx} id={mockId} creator={mockCreator} />
</MockedProvider>
);
expect(getByText('Creator')).toBeInTheDocument();
expect(getByText(mockCreator)).toBeInTheDocument();
});
it('should render the team URL', () => {
const { getByText } = render(
<MockedProvider>
<ReferralTeam tx={mockTx} id={mockId} creator={mockCreator} />
</MockedProvider>
);
expect(getByText('Team URL')).toBeInTheDocument();
expect(getByText(team.teamUrl)).toBeInTheDocument();
});
it('should render the avatar URL', () => {
const { getByText } = render(
<MockedProvider>
<ReferralTeam tx={mockTx} id={mockId} creator={mockCreator} />
</MockedProvider>
);
expect(getByText('Avatar')).toBeInTheDocument();
expect(getByText(team.avatarUrl)).toBeInTheDocument();
});
it('should render the open status as a tick if closed is falsy', () => {
const { getByTestId } = render(
<MockedProvider>
<ReferralTeam tx={mockTx} id={mockId} creator={mockCreator} />
</MockedProvider>
);
expect(getByTestId('open-yes')).toBeInTheDocument();
});
it('should render the open status as a cross if it is truthy', () => {
const m = {
team: {
closed: true,
},
};
const { getByTestId } = render(
<MockedProvider>
<ReferralTeam tx={m} id={mockId} creator={mockCreator} />
</MockedProvider>
);
expect(getByTestId('open-no')).toBeInTheDocument();
});
});
@@ -0,0 +1,73 @@
import {
VegaIcon,
Icon,
KeyValueTable,
KeyValueTableRow,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import type { components } from '../../../../../types/explorer';
import Hash from '../../../links/hash';
import { t } from 'i18next';
import { PartyLink } from '../../../links';
export type CreateReferralSet = components['schemas']['v1CreateReferralSet'];
export type ReferralTeam = CreateReferralSet['team'];
export interface ReferralTeamProps {
tx: CreateReferralSet;
id: string;
creator: string;
}
/**
* Renders the details for a team in a CreateReferralSet or UpdateReferralSet transaction.
*
* Intentionally does not render the avatar image or link to the team url.
*/
export const ReferralTeam = ({ tx, id, creator }: ReferralTeamProps) => {
if (!tx.team) {
return null;
}
return (
<section>
<div className="inline-block mr-2 leading-none">
<VegaIcon name={VegaIconNames.TEAM} />
</div>
{tx.team.name && (
<h3 className="inline-block leading-loose">{tx.team.name}</h3>
)}
<div className="min-w-fit max-w-2xl block">
<KeyValueTable>
<KeyValueTableRow>
{t('Id')}
<Hash text={id} truncate={false} />
</KeyValueTableRow>
<KeyValueTableRow>
{t('Creator')}
<PartyLink id={creator} truncate={false} />
</KeyValueTableRow>
{tx.team.teamUrl && (
<KeyValueTableRow>
{t('Team URL')}
<Hash text={tx.team.teamUrl} truncate={false} />
</KeyValueTableRow>
)}
{tx.team.avatarUrl && (
<KeyValueTableRow>
{t('Avatar')}
<Hash text={tx.team.avatarUrl} truncate={false} />
</KeyValueTableRow>
)}
<KeyValueTableRow>
{t('Open')}
<span data-testid={!tx.team.closed ? 'open-yes' : 'open-no'}>
{!tx.team.closed ? <Icon name="tick" /> : <Icon name="cross" />}
</span>
</KeyValueTableRow>
</KeyValueTable>
</div>
</section>
);
};
@@ -9,6 +9,7 @@ import { Time } from '../../../time';
import { ChainResponseCode } from '../chain-response-code/chain-reponse.code';
import { TxDataView } from '../../tx-data-view';
import Hash from '../../../links/hash';
import { Signature } from '../../../signature/signature';
interface TxDetailsSharedProps {
txData: BlockExplorerTransactionResult | undefined;
@@ -26,7 +27,8 @@ export const sharedHeaderProps = {
className: 'align-top',
};
const Labels: Record<BlockExplorerTransactionResult['type'], string> = {
// The incoming type field is usually the right thing to show. Exceptions are listed here
const LabelOverrides: Record<BlockExplorerTransactionResult['type'], string> = {
'Stop Orders Submission': 'Stop Order',
'Stop Orders Cancellation': 'Cancel Stop Order',
};
@@ -49,7 +51,7 @@ export const TxDetailsShared = ({
const time: string = blockData?.result.block.header.time || '';
const height: string = blockData?.result.block.header.height || txData.block;
const type = Labels[txData.type] || txData.type;
const type = LabelOverrides[txData.type] || txData.type;
return (
<>
@@ -75,6 +77,12 @@ export const TxDetailsShared = ({
<BlockLink height={height} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell {...sharedHeaderProps}>{t('Signature')}</TableCell>
<TableCell>
<Signature signature={txData.signature} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell {...sharedHeaderProps}>{t('Time')}</TableCell>
<TableCell>
@@ -33,6 +33,15 @@ const AccountType: Record<AccountTypes, string> = {
ACCOUNT_TYPE_HOLDING: 'Holding',
ACCOUNT_TYPE_LIQUIDITY_FEES_BONUS_DISTRIBUTION: 'Bonus Distribution',
ACCOUNT_TYPE_LP_LIQUIDITY_FEES: 'LP Liquidity Fees',
ACCOUNT_TYPE_NETWORK_TREASURY: 'Network Treasury',
ACCOUNT_TYPE_VESTING_REWARDS: 'Vesting Rewards',
ACCOUNT_TYPE_VESTED_REWARDS: 'Vested Rewards',
ACCOUNT_TYPE_REWARD_AVERAGE_POSITION: 'Reward Average Position',
ACCOUNT_TYPE_REWARD_RELATIVE_RETURN: 'Reward Relative Return',
ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY: 'Reward Return Volatility',
ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING: 'Reward Validator Ranking',
ACCOUNT_TYPE_PENDING_FEE_REFERRAL_REWARD: 'Pending Fee Referral Reward',
ACCOUNT_TYPE_ORDER_MARGIN: 'Order Margin',
};
interface TransferParticipantsProps {

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