Compare commits

...
Author SHA1 Message Date
m.ray 5f57234e4e chore(trading): enable close position (#5489) 2023-12-11 15:50:50 +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
m.ray 22703d937e fix(trading): fix percentage formatter rounding in liquidity table (#5250) 2023-11-13 16:14:18 +00:00
567 changed files with 14477 additions and 8245 deletions
+1
View File
@@ -77,6 +77,7 @@
"fixStyle": "inline-type-imports"
}
],
"@typescript-eslint/no-useless-constructor": 0,
"curly": ["error", "multi-line"]
}
},
+2 -2
View File
@@ -10,7 +10,7 @@ on:
inputs:
console-test-branch:
type: choice
description: 'main: v0.72.14, develop: v0.73.4'
description: 'main: v0.73.5, develop: v0.73.5'
options:
- main
- develop
@@ -215,7 +215,7 @@ jobs:
if: always()
with:
name: playwright-trace
path: ./traces/
path: apps/trading/e2e/traces/
retention-days: 15
#----------------------------------------------
# ----- upload logs -----
+3 -4
View File
@@ -48,16 +48,15 @@ cypress.env.json
# Next.js
.next
#cypress
# cypress
/apps/**/cypress/reports/
/apps/**/cypress/downloads/
/apps/**/fixtures/wallet/node**
#console-test
# apps/trading/e2e
__pycache__/
apps/trading/e2e/logs/
apps/trading/e2e/.pytest_cache/
apps/trading/e2e/traces/
.nx/cache
.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
+12 -1
View File
@@ -1,6 +1,7 @@
# Add files here to ignore them from prettier formatting
/dist
/dist-result
/coverage
__generated__
__generated___
@@ -9,4 +10,14 @@ apps/static/src/assets/devnet-tranches.json
apps/static/src/assets/mainnet-tranches.json
apps/static/src/assets/testnet-tranches.json
/.nx/cache
/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/
-4
View File
@@ -1,4 +0,0 @@
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
-9
View File
@@ -74,15 +74,6 @@
]
}
},
"build-netlify": {
"executor": "nx:run-commands",
"options": {
"commands": [
"cp apps/explorer/netlify.toml netlify.toml",
"nx build explorer"
]
}
},
"build-spec": {
"executor": "nx:run-commands",
"outputs": [],
+19 -14
View File
@@ -1,3 +1,4 @@
import '../i18n';
import {
NetworkLoader,
NodeFailure,
@@ -28,20 +29,24 @@ function App() {
);
return (
<TendermintWebsocketProvider>
<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={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={router} 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,6 +1,9 @@
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';
@@ -9,12 +12,15 @@ 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 = () => {
@@ -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 (
@@ -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;
@@ -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,13 +84,12 @@ 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="grid md:grid-cols-5 gap-x-6 mt-4">
<div className="mb-12 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-4">
{t('Status')}
@@ -114,6 +114,16 @@ const DeterministicOrderDetails = ({
{o.version}
</h5>
</div>
{o.type ? (
<div className="">
<h2 className="text-2xl font-bold text-dark 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>
@@ -8,7 +8,8 @@ import {
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 {
@@ -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]">
<span
className="bg-gray-100 px-2.5 py-0.5 text-xs text-gray-500 select-none cursor-default"
title={`Version ${signature.version}`}
>
{signature.algo}
</span>
<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>
);
};
@@ -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,88 @@
import { TableCell, TableRow } from '../../../table';
import { t } from '@vegaprotocol/i18n';
import {
EthExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/eth-explorer-link/eth-explorer-link';
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 || !contractCall.result) {
return null;
}
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>{t('ETH block')}</TableCell>
<TableCell>
<EthExplorerLink
id={contractCall.blockHeight}
type={EthExplorerLinkTypes.block}
/>
</TableCell>
</TableRow>
)}
{data?.oracleSpec?.dataSourceSpec && (
<OracleEthSource
sourceType={data.oracleSpec.dataSourceSpec.spec.data.sourceType}
/>
)}
<TableRow modifier="bordered">
<TableCell>{t('Result')}</TableCell>
<TableCell>{decodeEthCallResult(contractCall.result)}</TableCell>
</TableRow>
</>
);
};
@@ -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;
@@ -75,6 +76,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>
@@ -1,51 +1,11 @@
import { t } from '@vegaprotocol/i18n';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableWithTbody } from '../../table';
import { defaultAbiCoder, base64 } from 'ethers/lib/utils';
import { ChainEvent } from './chain-events';
import { BigNumber } from 'ethers';
import type { AbiType } from '../../../lib/encoders/abis/abi-types';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
interface AbiOutput {
type: AbiType;
internalType: AbiType;
name: string;
}
/**
* Decodes the b64/ABIcoded result from an eth cal
* @param data
* @returns
*/
export function decodeEthCallResult(
data: BlockExplorerTransactionResult
): string {
const ethResult = data.command.chainEvent?.contractCall.result;
try {
// Decode the result string: base64 => uint8array
const data = base64.decode(ethResult);
// Parse the escaped ABI in to an object
const abi = JSON.parse(
'[{"inputs":[],"name":"latestAnswer","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"}]'
);
// Pull the expected types out of the Oracles ABI
const types: AbiType[] = abi[0].outputs.map((o: AbiOutput) => o.type);
const rawResult = defaultAbiCoder.decode(types, data);
// Finally, convert the resulting BigNumber in to a string
const res = BigNumber.from(rawResult[0]).toString();
return res;
} catch (e) {
return '-';
}
}
interface TxDetailsChainEventProps {
txData: BlockExplorerTransactionResult | undefined;
pubKey: string | undefined;
@@ -80,6 +80,12 @@ export function getLabelForOrderType(
if (command.orderSubmission.icebergOpts) {
return 'Iceberg';
}
if (command.orderSubmission.type === 'TYPE_MARKET') {
return 'Market order';
}
if (command.orderSubmission.type === 'TYPE_LIMIT') {
return 'Limit order';
}
}
return 'Order';
}
@@ -98,6 +98,8 @@ describe('TxDetailsTransfer', () => {
},
},
signature: {
version: '1',
algo: 'vega/ed25519',
value:
'610c2e196a7d4fed4413b9e82af267b1ff3e30e943df3a3d28096fd60604d430d752fbaf6dd4f84d496be78885bb6118f40560bff7832c06bd7a3d67b718b700',
},
@@ -20,6 +20,8 @@ const generateTxs = (number: number): BlockExplorerTransactionResult[] => {
'4b782482f587d291e8614219eb9a5ee9280fa2c58982dee71d976782a9be1964',
type: 'Submit Order',
signature: {
version: '1',
algo: 'vega/ed25519',
value: '123',
},
code: 0,
@@ -1,6 +1,7 @@
import { AccountManager } from '@vegaprotocol/accounts';
import { useCallback } from 'react';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { useExplorerPartyAssetsQuery } from '../__generated__/Party-assets';
import { AssetLink, MarketLink } from '../../../../components/links';
import AssetBalance from '../../../../components/asset-balance/asset-balance';
import { AccountTypeMapping } from '@vegaprotocol/types';
interface PartyAccountsProps {
partyId: string;
@@ -12,21 +13,71 @@ interface PartyAccountsProps {
* appearing first and... tbd
*/
export const PartyAccounts = ({ partyId }: PartyAccountsProps) => {
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
const onClickAsset = useCallback(
(assetId?: string) => {
assetId && openAssetDetailsDialog(assetId);
},
[openAssetDetailsDialog]
);
const { data } = useExplorerPartyAssetsQuery({
variables: { partyId },
});
const party = data?.partiesConnection?.edges[0]?.node;
const accounts =
party?.accountsConnection?.edges?.filter((edge) => edge?.node) || [];
return (
<div className="block min-h-44 h-60 4 w-full border-red-800 relative">
<AccountManager
partyId={partyId}
onClickAsset={onClickAsset}
isReadOnly={true}
/>
<table>
<thead>
<tr>
<th className="text-right px-4">Balance</th>
<th className="text-left px-4">Type</th>
<th className="text-left px-4">Market</th>
<th className="text-left px-4">Asset</th>
</tr>
</thead>
<tbody>
{accounts
.sort((a, b) => {
// Sort by asset id, then market id, with general accounts first
if (!a) {
return 1;
}
if (!b) {
return -1;
}
if (a.node.asset.id !== b.node.asset.id) {
return a.node.asset.id.localeCompare(b.node.asset.id);
}
if (a.node.type === 'ACCOUNT_TYPE_GENERAL') return -1;
if (b.node.type === 'ACCOUNT_TYPE_GENERAL') return 1;
if (a.node.market && b.node.market) {
return a.node.market.id.localeCompare(b.node.market.id);
} else {
return a.node.type.localeCompare(b.node.type);
}
})
.map((e) => {
if (!e) return null;
const { type, asset, balance, market } = e.node;
return (
<tr className="border-t border-neutral-300 dark:border-neutral-600">
<td className="px-4 text-right">
<AssetBalance
assetId={asset.id}
price={balance}
showAssetSymbol={true}
/>
</td>
<td className="px-4">{AccountTypeMapping[type]}</td>
<td className="px-4">
{market?.id ? <MarketLink id={market.id} /> : '-'}
</td>
<td className="px-4">
<AssetLink assetId={asset.id} />
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
};
@@ -23,6 +23,8 @@ const txData: BlockExplorerTransactionResult = {
type: 'type',
command: {} as ValidatorHeartbeat,
signature: {
version: '1',
algo: 'vega/ed25519',
value: '123',
},
};
@@ -11,6 +11,8 @@ export interface BlockExplorerTransactionResult {
cursor: string;
command: components['schemas']['blockexplorerv1transaction'];
signature: {
version: string;
algo: string;
value: string;
};
error?: string;
+14
View File
@@ -3,6 +3,9 @@
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
import { locales } from '@vegaprotocol/i18n';
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
Object.defineProperty(window, 'ResizeObserver', {
writable: false,
@@ -13,3 +16,14 @@ Object.defineProperty(window, 'ResizeObserver', {
disconnect: jest.fn(),
})),
});
// Set up i18n instance so that components have the correct default
// en translations
i18n.use(initReactI18next).init({
// we init with resources
resources: locales,
fallbackLng: 'en',
nsSeparator: false,
ns: ['explorer'],
defaultNS: 'explorer',
});
+1
View File
@@ -0,0 +1 @@
../../../../libs/i18n/src/locales
+45
View File
@@ -0,0 +1,45 @@
import type { Module } from 'i18next';
import i18n from 'i18next';
import HttpBackend from 'i18next-http-backend';
import LocizeBackend from 'i18next-locize-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
const isInDev = process.env.NODE_ENV === 'development';
const useLocize = isInDev && !!process.env.NX_USE_LOCIZE;
const backend = useLocize
? {
projectId: '96ac1231-4bdd-455a-b9d7-f5322a2e7430',
apiKey: process.env.NX_LOCIZE_API_KEY,
referenceLng: 'en',
}
: {
loadPath: '/assets/locales/{{lng}}/{{ns}}.json',
};
const Backend: Module = useLocize ? LocizeBackend : HttpBackend;
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
lng: 'en',
fallbackLng: 'en',
supportedLngs: ['en'],
load: 'languageOnly',
debug: isInDev,
// have a common namespace used around the full app
ns: ['explorer'],
defaultNS: 'explorer',
keySeparator: false, // we use content as keys
nsSeparator: false,
backend,
saveMissing: useLocize && !!process.env.NX_LOCIZE_API_KEY,
interpolation: {
escapeValue: false,
},
});
export default i18n;
@@ -133,7 +133,7 @@ export const proposalsData = {
instrument: {
name: 'UNIDAI Monthly (Dec 2022)',
code: 'UNIDAI.MF21',
futureProduct: {
product: {
settlementAsset: { symbol: 'tDAI', __typename: 'Asset' },
__typename: 'FutureProduct',
},
@@ -240,7 +240,7 @@ export const proposalsData = {
instrument: {
name: 'ETHBTC Quarterly (Feb 2023)',
code: 'ETHBTC.QM21',
futureProduct: {
product: {
settlementAsset: { symbol: 'tBTC', __typename: 'Asset' },
__typename: 'FutureProduct',
},
@@ -302,14 +302,17 @@ context(
cy.getByTestId(vegaWalletCurrencyTitle)
.contains(name)
.parent()
.siblings(txTimeout)
.should((elementAmount) => {
const displayedAmount = parseFloat(elementAmount.text());
// @ts-ignore clash between jest and cypress
expect(displayedAmount).be.gte(expectedAmount);
.parent() // back to currency-title
.parent() // back to container
.within(() => {
cy.get(
'[data-account-type="account_type_general"] [data-value]'
).should((elementAmount) => {
const displayedAmount = parseFloat(elementAmount.text());
// @ts-ignore clash between jest and cypress
expect(displayedAmount).be.gte(expectedAmount);
});
});
cy.getByTestId(vegaWalletCurrencyTitle)
.contains(name)
.parent()
@@ -256,10 +256,7 @@ export function validateWalletCurrency(
.parent()
.parent()
.within(() => {
cy.getByTestId('currency-value', txTimeout).should(
'have.text',
expectedAmount
);
cy.get('[data-value]', txTimeout).should('have.text', expectedAmount);
});
}
+1 -2
View File
@@ -35,6 +35,5 @@ NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
NX_REFERRALS=true
NX_GOVERNANCE_TRANSFERS=false
NX_VOLUME_DISCOUNTS=false
+1 -2
View File
@@ -31,9 +31,8 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
CYPRESS_FAIRGROUND=false
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false
NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
NX_VOLUME_DISCOUNTS=true
-1
View File
@@ -28,4 +28,3 @@ NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
NX_VOLUME_DISCOUNTS=true
+4 -5
View File
@@ -22,9 +22,8 @@ NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false
NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
NX_VOLUME_DISCOUNTS=false
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
+4 -5
View File
@@ -21,9 +21,8 @@ NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false
NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
NX_VOLUME_DISCOUNTS=false
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
-1
View File
@@ -25,4 +25,3 @@ NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
NX_GOVERNANCE_TRANSFERS=true
NX_VOLUME_DISCOUNTS=true
-1
View File
@@ -29,4 +29,3 @@ NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
NX_VOLUME_DISCOUNTS=true
+4 -5
View File
@@ -20,9 +20,8 @@ NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false
NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_REFERRALS=false
NX_VOLUME_DISCOUNTS=false
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_REFERRALS=true
-4
View File
@@ -49,10 +49,6 @@ There are a few different configuration options offered for this app:
| `NX_ETH_WALLET_MNEMONIC` (optional) | The mnemonic to be used to sign transactions with in browser |
| `NX_LOCAL_PROVIDER_URL` (optional) | The local node to use to send transaction to when signing in browser |
## Example configs:
For example configurations, check out our [netlify.toml](./netlify.toml).
## Testing
To run the minimal set of unit tests, run the following:
-4
View File
@@ -1,4 +0,0 @@
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
-9
View File
@@ -69,15 +69,6 @@
"jestConfig": "apps/governance/jest.config.ts"
}
},
"build-netlify": {
"executor": "nx:run-commands",
"options": {
"commands": [
"cp apps/governance/netlify.toml netlify.toml",
"nx build token"
]
}
},
"build-spec": {
"executor": "nx:run-commands",
"outputs": [],
+10 -9
View File
@@ -4,7 +4,7 @@ import { Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet, useEagerConnect } from '@vegaprotocol/wallet';
import { FLAGS, useEnvironment } from '@vegaprotocol/environment';
import { useWeb3React } from '@web3-react/core';
import React from 'react';
import React, { Suspense } from 'react';
import { useTranslation } from 'react-i18next';
import { SplashError } from './components/splash-error';
@@ -164,13 +164,14 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
);
}
if (!loaded) {
return (
<Splash>
<SplashLoader />
</Splash>
);
}
const loading = (
<Splash>
<SplashLoader />
</Splash>
);
return children;
if (!loaded) {
return loading;
}
return <Suspense fallback={loading}>{children}</Suspense>;
};
+6 -3
View File
@@ -42,6 +42,7 @@ import {
useNodeSwitcherStore,
DocsLinks,
NodeFailure,
AppLoader as Loader,
} from '@vegaprotocol/environment';
import { ENV } from './config';
import type { InMemoryCacheConfig } from '@apollo/client';
@@ -352,9 +353,11 @@ function App() {
useInitializeEnv();
return (
<NetworkLoader cache={cache}>
<AppContainer />
</NetworkLoader>
<React.Suspense fallback={<Loader />}>
<NetworkLoader cache={cache}>
<AppContainer />
</NetworkLoader>
</React.Suspense>
);
}
+1
View File
@@ -0,0 +1 @@
../../../../libs/i18n/src/locales
@@ -23,10 +23,13 @@ export const Heading = ({
})}
>
<h1
className={classNames('font-alpha calt text-5xl break-words', {
'mt-0': !marginTop,
'mb-0': !marginBottom,
})}
className={classNames(
'font-alpha calt text-5xl [word-break:break-word]',
{
'mt-0': !marginTop,
'mb-0': !marginBottom,
}
)}
>
{title}
</h1>
@@ -114,6 +114,16 @@ export const usePollForDelegations = () => {
isAssetTypeERC20(a.asset) &&
a.asset.source.contractAddress === vegaToken.address;
const isVesting =
a.type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS ||
a.type === Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS;
let icon = noIcon;
if (isVega) {
if (isVesting) icon = vegaVesting;
else icon = vegaBlack;
}
return {
isVega,
name: a.asset.name,
@@ -124,14 +134,7 @@ export const usePollForDelegations = () => {
balance: new BigNumber(
addDecimal(a.balance, a.asset.decimals)
),
image: isVega
? vegaBlack
: a.type ===
Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS ||
a.type ===
Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS
? vegaVesting
: noIcon,
image: icon,
border: isVega,
address: isAssetTypeERC20(a.asset)
? a.asset.source.contractAddress
@@ -11,7 +11,10 @@ import { BigNumber } from '../../lib/bignumber';
import { truncateMiddle } from '../../lib/truncate-middle';
import Routes from '../../routes/routes';
import { BulletHeader } from '../bullet-header';
import type { WalletCardAssetProps } from '../wallet-card';
import type {
WalletCardAssetProps,
WalletCardAssetWithMultipleBalancesProps,
} from '../wallet-card';
import {
WalletCard,
WalletCardActions,
@@ -27,6 +30,7 @@ import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit';
import { toBigNum } from '@vegaprotocol/utils';
import { usePendingBalancesStore } from '../../hooks/use-pending-balances-manager';
import { StakingEventType } from '../../hooks/use-get-association-breakdown';
import omit from 'lodash/omit';
export const VegaWallet = () => {
const { t } = useTranslation();
@@ -99,12 +103,29 @@ const VegaWalletAssetList = ({ accounts }: VegaWalletAssetsListProps) => {
if (!accounts.length) {
return null;
}
const groupedByAsset = accounts.reduce((all, a) => {
const foundIndex = all.findIndex((acc) => acc.assetId === a.assetId);
if (foundIndex > -1) {
const found = all[foundIndex];
all[foundIndex] = {
...found,
balances: [...found.balances, { balance: a.balance, type: a.type }],
};
return all;
}
const acc = {
...omit(a, 'balance', 'type'),
balances: [{ balance: a.balance, type: a.type }],
};
return [...all, acc];
}, [] as WalletCardAssetWithMultipleBalancesProps[]);
return (
<>
<WalletCardHeader>
<BulletHeader tag="h2">{t('assets')}</BulletHeader>
</WalletCardHeader>
{accounts.map((a, i) => (
{groupedByAsset.map((a, i) => (
<WalletCardAsset key={i} {...a} />
))}
</>
@@ -182,6 +203,7 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
subheading={t('Associated')}
symbol="VEGA"
balance={currentStakeAvailable}
allowZeroBalance={true}
/>
{totalPending.eq(0) ? null : (
<>
@@ -192,6 +214,7 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
subheading={t('Pending association')}
symbol="VEGA"
balance={totalPending}
allowZeroBalance={true}
/>
<WalletCardAsset
image={vegaWhite}
@@ -200,6 +223,7 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
subheading={t('Total associated after pending')}
symbol="VEGA"
balance={pendingStakeAmount}
allowZeroBalance={true}
/>
</>
)}
@@ -103,7 +103,7 @@ export const WalletCardActions = ({
return <div className="flex justify-end gap-2 mb-4">{children}</div>;
};
export interface WalletCardAssetProps {
export type WalletCardAssetProps = {
image: string;
name: string;
symbol: string;
@@ -113,42 +113,61 @@ export interface WalletCardAssetProps {
border?: boolean;
subheading?: string;
type?: Schema.AccountType;
}
allowZeroBalance?: boolean;
};
export type WalletCardAssetWithMultipleBalancesProps = Omit<
WalletCardAssetProps,
'balance' | 'type'
> & {
balances: { balance: BigNumber; type?: Schema.AccountType }[];
};
export const WalletCardAsset = ({
image,
name,
symbol,
balance,
decimals,
assetId,
border,
subheading,
type,
}: WalletCardAssetProps) => {
const [integers, decimalsPlaces, separator] = useNumberParts(
balance,
decimals
);
const { t } = useTranslation();
const consoleLink = useLinks(DApp.Console);
const transferAssetLink = (assetId: string) =>
consoleLink(CONSOLE_TRANSFER_ASSET.replace(':assetId', assetId));
const { param: baseRate } = useNetworkParam('rewards_vesting_baseRate');
allowZeroBalance = false,
...props
}: WalletCardAssetProps | WalletCardAssetWithMultipleBalancesProps) => {
const balance = 'balance' in props ? props.balance : undefined;
const type = 'type' in props ? props.type : undefined;
const balances =
'balances' in props
? props.balances
: balance
? [{ balance, type }]
: undefined;
const isRedeemable =
type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS && assetId;
const values =
balances &&
balances.length > 0 &&
balances
.filter((b) => allowZeroBalance || !b.balance.isZero())
.sort((a, b) => {
const order = [
Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS,
Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS,
Schema.AccountType.ACCOUNT_TYPE_GENERAL,
undefined,
];
return order.indexOf(a.type) - order.indexOf(b.type);
})
.map(({ balance, type }, i) => (
<CurrencyValue
key={i}
balance={balance}
decimals={decimals}
type={type}
assetId={assetId}
/>
));
const accountTypeTooltip = useMemo(() => {
if (type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS) {
return t('VestedRewardsTooltip');
}
if (type === Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS && baseRate) {
return t('VestingRewardsTooltip', { baseRate });
}
return null;
}, [baseRate, t, type]);
if (!values || values.length === 0) return;
return (
<div className="flex flex-nowrap gap-2 mt-2 mb-4">
@@ -169,35 +188,92 @@ export const WalletCardAsset = ({
{subheading || symbol}
</div>
</div>
{type ? (
<div className="mb-[2px] flex gap-2 items-baseline">
<Tooltip description={accountTypeTooltip}>
<span className="px-2 py-1 leading-none text-xs bg-vega-cdark-700 rounded">
{Schema.AccountTypeMapping[type]}
</span>
</Tooltip>
{isRedeemable ? (
<Tooltip description={t('RedeemRewardsTooltip')}>
<AnchorButton
variant="primary"
size="xs"
href={transferAssetLink(assetId)}
target="_blank"
className="px-2 py-1 leading-none text-xs bg-vega-yellow text-black rounded"
>
{t('Redeem')}
</AnchorButton>
</Tooltip>
) : null}
</div>
) : null}
<div className="basis-full font-mono" data-testid="currency-value">
<span>
{integers}
{separator}
</span>
<span className="text-neutral-400">{decimalsPlaces}</span>
{values}
</div>
</div>
);
};
const useAccountTypeTooltip = (type?: Schema.AccountType) => {
const { t } = useTranslation();
const { param: baseRate } = useNetworkParam('rewards_vesting_baseRate');
const accountTypeTooltip = useMemo(() => {
if (type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS) {
return t('VestedRewardsTooltip');
}
if (type === Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS && baseRate) {
return t('VestingRewardsTooltip', { baseRate });
}
return null;
}, [baseRate, t, type]);
return accountTypeTooltip;
};
const CurrencyValue = ({
balance,
decimals,
type,
assetId,
}: {
balance: BigNumber;
decimals: number;
type?: Schema.AccountType;
assetId?: string;
}) => {
const { t } = useTranslation();
const consoleLink = useLinks(DApp.Console);
const transferAssetLink = (assetId: string) =>
consoleLink(CONSOLE_TRANSFER_ASSET.replace(':assetId', assetId));
const [integers, decimalsPlaces, separator] = useNumberParts(
balance,
decimals
);
const accountTypeTooltip = useAccountTypeTooltip(type);
const accountType = type && (
<Tooltip description={accountTypeTooltip}>
<span className="px-2 py-1 leading-none text-xs bg-vega-cdark-700 rounded">
{Schema.AccountTypeMapping[type]}
</span>
</Tooltip>
);
const isRedeemable =
type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS && assetId;
const redeemBtn = isRedeemable ? (
<Tooltip description={t('RedeemRewardsTooltip')}>
<AnchorButton
variant="primary"
size="xs"
href={transferAssetLink(assetId)}
target="_blank"
className="px-2 py-1 leading-none text-xs bg-vega-yellow text-black rounded"
>
{t('Redeem')}
</AnchorButton>
</Tooltip>
) : null;
return (
<div
className="basis-full font-mono mb-1"
data-account-type={type?.toLowerCase() || 'unspecified'}
data-testid="currency-value"
>
{type && (
<div data-type className="flex gap-1">
{accountType}
{redeemBtn}
</div>
)}
<div data-value>
<span>
{integers}
{separator}
</span>
<span className="text-neutral-400">{decimalsPlaces}</span>
</div>
</div>
);
@@ -49,12 +49,8 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
? activeProvider
: defaultProvider;
if (
account &&
activeProvider &&
typeof activeProvider.getSigner === 'function'
) {
signer = provider.getSigner();
if (account && provider && typeof provider.getSigner === 'function') {
signer = provider.getSigner(account);
}
const tokenVestingAddress =
+27 -14
View File
@@ -1,29 +1,42 @@
import type { Module } from 'i18next';
import i18n from 'i18next';
import HttpBackend from 'i18next-http-backend';
import LocizeBackend from 'i18next-locize-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
import dev from './translations/dev.json';
const isInDev = process.env.NODE_ENV === 'development';
const useLocize = isInDev && !!process.env.NX_USE_LOCIZE;
const backend = useLocize
? {
projectId: '96ac1231-4bdd-455a-b9d7-f5322a2e7430',
apiKey: process.env.NX_LOCIZE_API_KEY,
referenceLng: 'en',
}
: {
loadPath: '/assets/locales/{{lng}}/{{ns}}.json',
};
const Backend: Module = useLocize ? LocizeBackend : HttpBackend;
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
// we init with resources
resources: {
en: {
translations: {
...dev,
},
},
},
lng: undefined,
lng: 'en',
fallbackLng: 'en',
debug: true,
supportedLngs: ['en'],
load: 'languageOnly',
debug: isInDev,
// have a common namespace used around the full app
ns: ['translations'],
defaultNS: 'translations',
ns: ['governance'],
defaultNS: 'governance',
keySeparator: false, // we use content as keys
nsSeparator: false,
backend,
saveMissing: useLocize && !!process.env.NX_LOCIZE_API_KEY,
interpolation: {
escapeValue: false,
},
@@ -189,7 +189,6 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
},
});
@@ -7,8 +7,10 @@ import type { AssetFieldsFragment } from '@vegaprotocol/assets';
export const ProposalAssetDetails = ({
asset,
originalAsset,
}: {
asset: AssetFieldsFragment;
originalAsset?: AssetFieldsFragment;
}) => {
const { t } = useTranslation();
const [showAssetDetails, setShowAssetDetails] = useState(false);
@@ -27,6 +29,7 @@ export const ProposalAssetDetails = ({
<div className="mb-10 pb-4">
<AssetDetailsTable
asset={asset}
originalAsset={originalAsset}
omitRows={[
AssetDetail.STATUS,
AssetDetail.INFRASTRUCTURE_FEE_ACCOUNT_BALANCE,
@@ -77,7 +77,7 @@ describe('Proposal header', () => {
__typename: 'InstrumentConfiguration',
name: 'Some market',
code: 'FX:BTCUSD/DEC99',
futureProduct: {
product: {
__typename: 'FutureProduct',
settlementAsset: {
__typename: 'Asset',
@@ -39,6 +39,18 @@ export const ProposalHeader = ({
const titleContent = shorten(title ?? '', 100);
const getAsset = (proposal: ProposalQuery['proposal']) => {
const terms = proposal?.terms;
if (
terms?.change.__typename === 'NewMarket' &&
(terms.change.instrument.product?.__typename === 'FutureProduct' ||
terms.change.instrument.product?.__typename === 'PerpetualProduct')
) {
return terms.change.instrument.product.settlementAsset;
}
return undefined;
};
switch (change?.__typename) {
case 'NewMarket': {
proposalType =
@@ -54,10 +66,10 @@ export const ProposalHeader = ({
<span>
{t('Code')}: {change.instrument.code}.
</span>{' '}
{change.instrument.futureProduct?.settlementAsset.symbol ? (
{proposal?.terms && getAsset(proposal)?.symbol ? (
<>
<span className="font-semibold">
{change.instrument.futureProduct.settlementAsset.symbol}
{getAsset(proposal)?.symbol}
</span>{' '}
{t('settled future')}.
</>
@@ -54,8 +54,8 @@ export const ProposalReferralProgramDetails = ({
return null;
}
const benefitTiers = proposal?.terms?.change?.benefitTiers;
const stakingTiers = proposal?.terms?.change?.stakingTiers;
const benefitTiers = proposal?.terms?.change?.benefitTiers.slice();
const stakingTiers = proposal?.terms?.change?.stakingTiers.slice();
const windowLength = proposal?.terms?.change?.windowLength;
const endOfProgramTimestamp = proposal?.terms?.change?.endOfProgram;
@@ -78,7 +78,7 @@ export const ProposalVolumeDiscountProgramDetails = ({
{t('BenefitTiers')}
</h3>
<KeyValueTable>
{benefitTiers
{[...benefitTiers]
.sort(
(a, b) =>
Number(a.minimumRunningNotionalTakerVolume) -
@@ -65,10 +65,13 @@ export const Proposal = ({
? removePaginationWrapper(assetData.assetsConnection?.edges)[0]
: undefined;
const originalAsset = asset;
if (proposal.terms.change.__typename === 'UpdateAsset' && asset) {
asset = {
...asset,
quantum: proposal.terms.change.quantum,
source: { ...asset.source },
};
if (asset.source.__typename === 'ERC20') {
@@ -228,7 +231,7 @@ export const Proposal = ({
proposal.terms.change.__typename === 'UpdateAsset') &&
asset && (
<div className="mb-4">
<ProposalAssetDetails asset={asset} />
<ProposalAssetDetails asset={asset} originalAsset={originalAsset} />
</div>
)}
@@ -1,7 +1,7 @@
import {
getProposalDialogIcon,
getProposalDialogIntent,
getProposalDialogTitle,
useGetProposalDialogTitle,
} from '@vegaprotocol/proposals';
import type { ProposalEventFieldsFragment } from '@vegaprotocol/proposals';
import type { DialogProps } from '@vegaprotocol/proposals';
@@ -15,6 +15,7 @@ export const ProposalFormTransactionDialog = ({
finalizedProposal,
TransactionDialog,
}: ProposalFormTransactionDialogProps) => {
const title = useGetProposalDialogTitle(finalizedProposal?.state);
// Render a custom complete UI if the proposal was rejected otherwise
// pass undefined so that the default vega transaction dialog UI gets used
const completeContent = finalizedProposal?.rejectionReason ? (
@@ -24,7 +25,7 @@ export const ProposalFormTransactionDialog = ({
return (
<div data-testid="proposal-transaction-dialog">
<TransactionDialog
title={getProposalDialogTitle(finalizedProposal?.state)}
title={title}
intent={getProposalDialogIntent(finalizedProposal?.state)}
icon={getProposalDialogIcon(finalizedProposal?.state)}
content={{
@@ -8,7 +8,7 @@ import {
networkParamsQueryMock,
nextWeek,
} from '../../test-helpers/mocks';
import { VoteBreakdown } from './vote-breakdown';
import { CompactVotes, VoteBreakdown } from './vote-breakdown';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import type { MockedResponse } from '@apollo/client/testing';
import {
@@ -346,3 +346,22 @@ describe('VoteBreakdown', () => {
expect(style.width).toBe(`${expectedProgress}%`);
});
});
describe('CompactVotes', () => {
it.each([
[0, '0'],
[1, '1'],
[12, '12'],
[123, '123'],
[1234, '1.2K'],
[12345, '12.3K'],
[123456, '123.5K'],
[1234567, '1.2M'],
[12345678, '12.3M'],
[123456789, '123.5M'],
[1234567890, '1.2B'],
])('compacts %s to %s', (input, output) => {
const { getByTestId } = render(<CompactVotes number={BigNumber(input)} />);
expect(getByTestId('compact-number').textContent).toBe(output);
});
});
@@ -3,11 +3,21 @@ import BigNumber from 'bignumber.js';
import { useTranslation } from 'react-i18next';
import { useVoteInformation } from '../../hooks';
import { Icon, Tooltip } from '@vegaprotocol/ui-toolkit';
import { formatNumber, toBigNum } from '@vegaprotocol/utils';
import { formatNumber } from '@vegaprotocol/utils';
import { ProposalState } from '@vegaprotocol/types';
import type { ReactNode } from 'react';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import { CompactNumber } from '@vegaprotocol/react-helpers';
export const CompactVotes = ({ number }: { number: BigNumber }) => (
<CompactNumber
number={number}
decimals={number.isGreaterThan(1000) ? 1 : 0}
compactAbove={1000}
compactDisplay="short"
/>
);
interface VoteBreakdownProps {
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
@@ -198,10 +208,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
)}
>
<button>
{yesEquityLikeShareWeight
.dividedBy(toBigNum(10 ** 6, 0))
.toFixed(1)}
M
<CompactVotes number={yesEquityLikeShareWeight} />
</button>
</Tooltip>
<span>
@@ -226,10 +233,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
)}
>
<button>
{noEquityLikeShareWeight
.dividedBy(toBigNum(10 ** 6, 0))
.toFixed(1)}
M
<CompactVotes number={noEquityLikeShareWeight} />
</button>
</Tooltip>
<span>
@@ -279,10 +283,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
)}
>
<button>
{totalEquityLikeShareWeight
.dividedBy(toBigNum(10 ** 6, 0))
.toFixed(1)}
M
<CompactVotes number={totalEquityLikeShareWeight} />
</button>
</Tooltip>
<span>
@@ -321,7 +322,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
<span>{t('tokenVotesFor')}:</span>
<Tooltip description={formatNumber(yesTokens, defaultDP)}>
<button data-testid="num-votes-for">
{yesTokens.dividedBy(toBigNum(10 ** 6, 0)).toFixed(1)}M
<CompactVotes number={yesTokens} />
</button>
</Tooltip>
<span>
@@ -341,7 +342,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
<span>{t('tokenVotesAgainst')}:</span>
<Tooltip description={formatNumber(noTokens, defaultDP)}>
<button data-testid="num-votes-against">
{noTokens.dividedBy(toBigNum(10 ** 6, 0)).toFixed(1)}M
<CompactVotes number={noTokens} />
</button>
</Tooltip>
<span>
@@ -384,7 +385,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
<span>{t('totalTokensVoted')}:</span>
<Tooltip description={formatNumber(totalTokensVoted, defaultDP)}>
<button data-testid="total-voted">
{totalTokensVoted.dividedBy(toBigNum(10 ** 6, 0)).toFixed(1)}M
<CompactVotes number={totalTokensVoted} />
</button>
</Tooltip>
<span data-testid="total-voted-percentage">
@@ -84,7 +84,6 @@ query Proposal(
$includeNewMarketProductField: Boolean!
$includeUpdateMarketState: Boolean!
$includeUpdateReferralProgram: Boolean!
$includeUpdateVolumeDiscountProgram: Boolean!
) {
proposal(id: $proposalId) {
id
@@ -104,7 +103,6 @@ query Proposal(
...UpdateMarketState @include(if: $includeUpdateMarketState)
...UpdateReferralProgram @include(if: $includeUpdateReferralProgram)
...UpdateVolumeDiscountProgram
@include(if: $includeUpdateVolumeDiscountProgram)
terms {
closingDatetime
enactmentDatetime
@@ -132,46 +130,25 @@ query Proposal(
instrument {
name
code
futureProduct {
settlementAsset {
id
name
symbol
decimals
quantum
}
quoteName
dataSourceSpecForSettlementData {
sourceType {
... on DataSourceDefinitionInternal {
sourceType {
... on DataSourceSpecConfigurationTime {
conditions {
operator
value
}
}
}
}
... on DataSourceDefinitionExternal {
sourceType {
... on DataSourceSpecConfiguration {
signers {
signer {
... on PubKey {
key
}
... on ETHAddress {
address
}
}
}
filters {
key {
name
type
}
product {
... on FutureProduct {
settlementAsset {
id
name
symbol
decimals
quantum
}
quoteName
dataSourceSpecBinding {
settlementDataProperty
tradingTerminationProperty
}
dataSourceSpecForSettlementData {
sourceType {
... on DataSourceDefinitionInternal {
sourceType {
... on DataSourceSpecConfigurationTime {
conditions {
operator
value
@@ -179,52 +156,44 @@ query Proposal(
}
}
}
... on DataSourceDefinitionExternal {
sourceType {
... on DataSourceSpecConfiguration {
signers {
signer {
... on PubKey {
key
}
... on ETHAddress {
address
}
}
}
filters {
key {
name
type
}
conditions {
operator
value
}
}
}
}
}
}
}
}
# dataSourceSpecForTradingTermination {
# sourceType {
# ... on DataSourceDefinitionInternal {
# sourceType {
# ... on DataSourceSpecConfigurationTime {
# conditions {
# operator
# value
# }
# }
# }
# }
# ... on DataSourceDefinitionExternal {
# sourceType {
# ... on DataSourceSpecConfiguration {
# signers {
# signer {
# ... on PubKey {
# key
# }
# ... on ETHAddress {
# address
# }
# }
# }
# filters {
# key {
# name
# type
# }
# conditions {
# operator
# value
# }
# }
# }
# }
# }
# }
# }
dataSourceSpecBinding {
settlementDataProperty
tradingTerminationProperty
... on PerpetualProduct {
settlementAsset {
id
name
symbol
decimals
quantum
}
quoteName
}
}
}
File diff suppressed because one or more lines are too long
@@ -62,7 +62,6 @@ export const ProposalContainer = () => {
includeNewMarketProductField: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketState: !!FLAGS.UPDATE_MARKET_STATE,
includeUpdateReferralProgram: !!FLAGS.REFERRALS,
includeUpdateVolumeDiscountProgram: !!FLAGS.VOLUME_DISCOUNTS,
},
skip: !params.proposalId,
});
@@ -101,9 +101,16 @@ fragment ProposalFields on Proposal {
instrument {
name
code
futureProduct {
settlementAsset {
symbol
product {
... on FutureProduct {
settlementAsset {
symbol
}
}
... on PerpetualProduct {
settlementAsset {
symbol
}
}
}
}
@@ -164,7 +171,6 @@ query Proposals(
$includeNewMarketProductFields: Boolean!
$includeUpdateMarketStates: Boolean!
$includeUpdateReferralPrograms: Boolean!
$includeUpdateVolumeDiscountPrograms: Boolean!
) {
proposalsConnection {
edges {
@@ -174,7 +180,6 @@ query Proposals(
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
...UpdateReferralPrograms @include(if: $includeUpdateReferralPrograms)
...UpdateVolumeDiscountPrograms
@include(if: $includeUpdateVolumeDiscountPrograms)
}
}
}
@@ -11,17 +11,16 @@ export type UpdateReferralProgramsFragment = { __typename?: 'Proposal', terms: {
export type UpdateVolumeDiscountProgramsFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } } };
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } };
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, product?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | { __typename?: 'PerpetualProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | { __typename?: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } };
export type ProposalsQueryVariables = Types.Exact<{
includeNewMarketProductFields: Types.Scalars['Boolean'];
includeUpdateMarketStates: Types.Scalars['Boolean'];
includeUpdateReferralPrograms: Types.Scalars['Boolean'];
includeUpdateVolumeDiscountPrograms: Types.Scalars['Boolean'];
}>;
export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram', windowLength: number, endOfProgram: any, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, product?: { __typename: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | { __typename: 'PerpetualProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram', windowLength: number, endOfProgram: any, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
export const NewMarketProductFieldsFragmentDoc = gql`
fragment NewMarketProductFields on Proposal {
@@ -131,9 +130,16 @@ export const ProposalFieldsFragmentDoc = gql`
instrument {
name
code
futureProduct {
settlementAsset {
symbol
product {
... on FutureProduct {
settlementAsset {
symbol
}
}
... on PerpetualProduct {
settlementAsset {
symbol
}
}
}
}
@@ -191,7 +197,7 @@ export const ProposalFieldsFragmentDoc = gql`
}
`;
export const ProposalsDocument = gql`
query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!, $includeUpdateReferralPrograms: Boolean!, $includeUpdateVolumeDiscountPrograms: Boolean!) {
query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!, $includeUpdateReferralPrograms: Boolean!) {
proposalsConnection {
edges {
node {
@@ -199,7 +205,7 @@ export const ProposalsDocument = gql`
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
...UpdateReferralPrograms @include(if: $includeUpdateReferralPrograms)
...UpdateVolumeDiscountPrograms @include(if: $includeUpdateVolumeDiscountPrograms)
...UpdateVolumeDiscountPrograms
}
}
}
@@ -225,7 +231,6 @@ ${UpdateVolumeDiscountProgramsFragmentDoc}`;
* includeNewMarketProductFields: // value for 'includeNewMarketProductFields'
* includeUpdateMarketStates: // value for 'includeUpdateMarketStates'
* includeUpdateReferralPrograms: // value for 'includeUpdateReferralPrograms'
* includeUpdateVolumeDiscountPrograms: // value for 'includeUpdateVolumeDiscountPrograms'
* },
* });
*/
@@ -52,7 +52,6 @@ export const ProposalsContainer = () => {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
},
});
@@ -8,7 +8,7 @@ import {
doesValueEquateToParam,
} from '@vegaprotocol/proposals';
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
import { validateJson } from '@vegaprotocol/utils';
import { useValidateJson } from '@vegaprotocol/utils';
import {
NetworkParams,
useNetworkParams,
@@ -41,6 +41,7 @@ export interface NewAssetProposalFormFields {
const DOCS_LINK = '/new-asset-proposal';
export const ProposeNewAsset = () => {
const validateJson = useValidateJson();
const {
params,
loading: networkParamsLoading,
@@ -7,7 +7,7 @@ import {
doesValueEquateToParam,
} from '@vegaprotocol/proposals';
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
import { validateJson } from '@vegaprotocol/utils';
import { useValidateJson } from '@vegaprotocol/utils';
import {
NetworkParams,
useNetworkParams,
@@ -39,6 +39,7 @@ export interface NewMarketProposalFormFields {
const DOCS_LINK = '/new-market-proposal';
export const ProposeNewMarket = () => {
const validateJson = useValidateJson();
const {
params,
loading: networkParamsLoading,
@@ -14,7 +14,7 @@ import {
RoundedWrapper,
TextArea,
} from '@vegaprotocol/ui-toolkit';
import { validateJson } from '@vegaprotocol/utils';
import { useValidateJson } from '@vegaprotocol/utils';
import {
NetworkParams,
useNetworkParams,
@@ -31,6 +31,7 @@ export interface RawProposalFormFields {
}
export const ProposeRaw = () => {
const validateJson = useValidateJson();
const {
params,
loading: networkParamsLoading,
@@ -7,7 +7,7 @@ import {
doesValueEquateToParam,
} from '@vegaprotocol/proposals';
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
import { validateJson } from '@vegaprotocol/utils';
import { useValidateJson } from '@vegaprotocol/utils';
import {
NetworkParams,
useNetworkParams,
@@ -39,6 +39,7 @@ export interface UpdateAssetProposalFormFields {
const DOCS_LINK = '/update-asset-proposal';
export const ProposeUpdateAsset = () => {
const validateJson = useValidateJson();
const {
params,
loading: networkParamsLoading,
@@ -8,7 +8,7 @@ import {
useProposalSubmit,
} from '@vegaprotocol/proposals';
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
import { validateJson } from '@vegaprotocol/utils';
import { useValidateJson } from '@vegaprotocol/utils';
import {
NetworkParams,
useNetworkParams,
@@ -53,6 +53,7 @@ export interface UpdateMarketProposalFormFields {
const DOCS_LINK = '/update-market-proposal';
export const ProposeUpdateMarket = () => {
const validateJson = useValidateJson();
const {
params,
loading: networkParamsLoading,
@@ -260,7 +261,7 @@ export const ProposeUpdateMarket = () => {
</FormGroup>
{selectedMarket && (
<div className="mt-[-20px] mb-6">
<div className="mb-6 mt-[-20px]">
<KeyValueTable data-testid="update-market-details">
<KeyValueTableRow>
{t('MarketName')}
@@ -42,7 +42,6 @@ export const RejectedProposalsContainer = () => {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
},
});
+4 -10
View File
@@ -3,7 +3,7 @@
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
import dev from './i18n/translations/dev.json';
import { locales } from '@vegaprotocol/i18n';
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import ResizeObserver from 'resize-observer-polyfill';
@@ -12,16 +12,10 @@ import ResizeObserver from 'resize-observer-polyfill';
// en translations
i18n.use(initReactI18next).init({
// we init with resources
resources: {
en: {
translations: {
...dev,
},
},
},
resources: locales,
fallbackLng: 'en',
ns: ['translations'],
defaultNS: 'translations',
ns: ['governance'],
defaultNS: 'governance',
});
global.ResizeObserver = ResizeObserver;
+4
View File
@@ -104,6 +104,10 @@
list-style: circle;
}
.react-markdown-container a {
text-decoration: underline;
}
.jsondiffpatch-delta,
.jsondiffpatch-delta pre {
font-family: 'Roboto Mono', monospace !important;
@@ -1,4 +0,0 @@
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
@@ -82,15 +82,6 @@
"jestConfig": "apps/liquidity-provision-dashboard/jest.config.ts"
}
},
"build-netlify": {
"executor": "nx:run-commands",
"options": {
"commands": [
"cp apps/liquidity-provision-dashboard/netlify.toml netlify.toml",
"nx build liquidity-provision-dashboard"
]
}
},
"build-spec": {
"executor": "nx:run-commands",
"outputs": [],
-4
View File
@@ -1,4 +0,0 @@
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
-9
View File
@@ -66,15 +66,6 @@
"jestConfig": "apps/multisig-signer/jest.config.ts"
}
},
"build-netlify": {
"executor": "nx:run-commands",
"options": {
"commands": [
"cp apps/multisig-signer/netlify.toml netlify.toml",
"nx build multisig-signer"
]
}
},
"build-spec": {
"executor": "nx:run-commands",
"outputs": [],
-4
View File
@@ -1,4 +0,0 @@
[[headers]]
for = "/*"
[headers.values]
Access-Control-Allow-Origin = "*"
-9
View File
@@ -46,15 +46,6 @@
"buildTarget": "static:build:production"
}
}
},
"build-netlify": {
"executor": "nx:run-commands",
"options": {
"commands": [
"cp apps/static/netlify.toml netlify.toml",
"nx build static"
]
}
}
}
}
@@ -1,23 +1,6 @@
import { removeDecimal } from '@vegaprotocol/cypress';
import * as Schema from '@vegaprotocol/types';
import {
OrderStatusMapping,
OrderTypeMapping,
Side,
} from '@vegaprotocol/types';
import { isBefore, isAfter, addSeconds, subSeconds } from 'date-fns';
import { createOrder } from '../support/create-order';
import { connectEthereumWallet } from '../support/ethereum-wallet';
import { selectAsset } from '../support/helpers';
const orderSize = 'size';
const orderType = 'type';
const orderStatus = 'status';
const orderRemaining = 'remaining';
const orderPrice = 'price';
const orderTimeInForce = 'timeInForce';
const orderUpdatedAt = 'updatedAt';
const assetSelectField = 'select[name="asset"]';
const amountField = 'input[name="amount"]';
const txTimeout = Cypress.env('txTimeout');
const sepoliaUrl = Cypress.env('ETHERSCAN_URL');
@@ -25,18 +8,10 @@ const btcName = 0;
const vegaName = 4;
const btcSymbol = 'tBTC';
const vegaSymbol = 'VEGA';
const usdcSymbol = 'fUSDC';
const toastContent = 'toast-content';
const openOrdersTab = 'Open';
const depositsTab = 'Deposits';
const collateralTab = 'Collateral';
const toastCloseBtn = 'toast-close';
const price = '390';
const size = '0.0005';
const newPrice = '200';
const completeWithdrawalBtn = 'complete-withdrawal';
const submitTransferBtn = '[type="submit"]';
const transferForm = 'transfer-form';
const depositSubmit = 'deposit-submit';
const approveSubmit = 'approve-submit';
const dialogContent = 'dialog-content';
@@ -116,33 +91,6 @@ describe('capsule - without MultiSign', { tags: '@slow' }, () => {
});
});
it('can key to key transfers', function () {
// 1003-TRAN-023
// 1003-TRAN-006
cy.get('[data-testid="pathname-/portfolio"]').should('exist');
cy.getByTestId(collateralTab).click();
cy.getByTestId('open-transfer').eq(1).click();
cy.getByTestId('transfer-form').should('be.visible');
cy.getByTestId('transfer-form').find('[name="toAddress"]').select(1);
cy.get('select option')
.contains('BTC')
.invoke('index')
.then((index) => {
cy.get(assetSelectField).select(index, { force: true });
});
cy.getByTestId(transferForm)
.find(amountField)
.focus()
.type('1', { delay: 100 });
cy.getByTestId(transferForm).find(submitTransferBtn).click();
cy.getByTestId(toastContent).should(
'contain.text',
'Transfer completeYour transaction has been confirmed View in block explorerTransferTo 7f9cf0…c255351.00 tBTC'
);
cy.getByTestId(toastCloseBtn).click();
});
it('can not withdrawal because of no MultiSign', function () {
// 1002-WITH-022
// 1002-WITH-023
@@ -187,143 +135,6 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
cy.setVegaWallet();
});
it('shows node health', function () {
// 0006-NETW-010
const regex = /^Operational\d+$/;
const market = this.market;
cy.visit(`/#/markets/${market.id}`);
cy.getByTestId('node-health-trigger').realHover();
cy.getByTestId('node-health')
.children()
.first()
.invoke('text')
.should('match', regex);
cy.getByTestId('node-health')
.children()
.eq(1)
.should('contain.text', new URL(Cypress.env('VEGA_URL')).hostname);
});
it('can place and receive an order', function () {
const market = this.market;
cy.visit(`/#/markets/${market.id}`);
const order = {
marketId: market.id,
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_BUY,
size: size,
price: price,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
};
const rawPrice = removeDecimal(order.price, market.decimalPlaces);
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId('Collateral').click();
cy.get('[col-id="asset.symbol"]', txTimeout).should(
'contain.text',
usdcSymbol
);
createOrder(order);
cy.getByTestId(toastContent).should(
'contain.text',
`Order submittedYour transaction has been confirmed View in block explorerSubmit order - activeTEST.24h+${order.size} @ ${order.price}.00 ${usdcSymbol}`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click();
// orderbook cells are keyed by price level
cy.getByTestId('tab-orderbook')
.get(`[data-testid="price-${rawPrice}"]`)
.should('contain.text', order.price)
.get(`[data-testid="bid-vol-${rawPrice}"]`)
.should('contain.text', order.size);
cy.getByTestId(openOrdersTab).click();
cy.getByTestId('tab-open-orders').within(() => {
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get(`[col-id='${orderSize}']`).should(
'contain.text',
order.side === Side.SIDE_BUY ? '+' : '-' + order.size
);
cy.get(`[col-id='${orderType}']`).should(
'contain.text',
OrderTypeMapping[order.type]
);
cy.get(`[col-id='${orderStatus}']`).should(
'contain.text',
OrderStatusMapping.STATUS_ACTIVE
);
cy.get(`[col-id='${orderRemaining}']`).should('contain.text', '0.00');
cy.get(`[col-id='${orderPrice}']`).then(($price) => {
expect(parseFloat($price.text())).to.equal(parseFloat(order.price));
});
cy.get(`[col-id='${orderTimeInForce}']`).should(
'contain.text',
'GTC'
);
checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderUpdatedAt);
});
});
});
it('can edit order', function () {
const market = this.market;
cy.visit(`/#/markets/${market.id}`);
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId(openOrdersTab).click();
cy.getByTestId('edit').first().click();
cy.getByTestId('dialog-title').should('contain.text', 'Edit order');
cy.get('#limitPrice').focus().clear().type(newPrice);
cy.getByTestId('edit-order').find('[type="submit"]').click();
cy.getByTestId(toastContent).should(
'contain.text',
`Order submittedYour transaction has been confirmed View in block explorerEdit order - activeTEST.24h+${size} @ ${price}.00 ${usdcSymbol}+${size} @ ${newPrice}.00 ${usdcSymbol}`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click({ multiple: true });
cy.getByTestId(openOrdersTab).click();
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get(`[col-id='${orderPrice}']`).then(($price) => {
expect(parseFloat($price.text())).to.equal(parseFloat(newPrice));
});
checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderUpdatedAt);
});
});
it('can cancel order', function () {
const market = this.market;
cy.visit(`/#/markets/${market.id}`);
cy.getByTestId(toastCloseBtn, txTimeout).click();
cy.getByTestId(openOrdersTab).click();
cy.getByTestId('cancel').first().click();
cy.getByTestId(toastContent).should(
'contain.text',
`Order cancelledYour transaction has been confirmed View in block explorerCancel order - cancelledTEST.24h+${size} @ ${newPrice}.00 ${usdcSymbol}`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click({ multiple: true });
cy.getByTestId('Closed').click();
cy.getByTestId('tab-closed-orders')
.get('.ag-center-cols-container')
.children()
.first()
.get(`[col-id='${orderStatus}']`, txTimeout)
.should('contain.text', OrderStatusMapping.STATUS_CANCELLED);
});
it('can withdrawal', function () {
// 1002-WITH-0014
// 1002-WITH-006
@@ -524,22 +335,3 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
});
});
});
function checkIfDataAndTimeOfCreationAndUpdateIsEqual(date: string) {
cy.get(`[col-id='${date}'] .ag-cell-wrapper`)
.children('span')
.children('span')
.invoke('data', 'value')
.then(($dateTime) => {
// allow a date 5 seconds either side to allow for
// unexpected latency
const minBefore = subSeconds(new Date(), 5);
const maxAfter = addSeconds(new Date(), 5);
// eslint-disable-next-line no-console
console.log(maxAfter);
const date = new Date($dateTime.toString());
expect(isAfter(date, minBefore) && isBefore(date, maxAfter)).to.equal(
true
);
});
}
@@ -1,72 +0,0 @@
const dialogContent = 'dialog-content';
const nodeHealth = 'node-health';
const nodeHealthTrigger = 'node-health-trigger';
describe('home', { tags: '@regression' }, () => {
before(() => {
cy.setOnBoardingViewed();
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/');
});
describe('node health', () => {
it('shows current block height', () => {
// 0006-NETW-004
// 0006-NETW-008
// 0006-NETW-009
cy.getByTestId(nodeHealthTrigger).realHover();
cy.getByTestId(nodeHealth)
.children()
.first()
.should('contain.text', 'Operational', {
timeout: 10000,
})
.should('contain.text', '100'); // all mocked queries have x-block-height header set to 100
cy.getByTestId(nodeHealth)
.children()
.eq(1)
.should('contain.text', new URL(Cypress.env('VEGA_URL')).hostname);
});
it('shows node switcher details', () => {
// 0006-NETW-012
// 0006-NETW-013
// 0006-NETW-014
// 0006-NETW-015
// 0006-NETW-016
cy.getByTestId(nodeHealthTrigger).click();
cy.getByTestId(dialogContent).should('contain.text', 'Connected node');
cy.getByTestId(dialogContent).should(
'contain.text',
'This app will only work on CUSTOM. Select a node to connect to.'
);
cy.getByTestId('node')
.first()
.should('contain.text', new URL(Cypress.env('VEGA_URL')).origin)
.next()
.should('contain.text', 'Response time')
.next()
.should('contain.text', 'Block')
.next()
.should('contain.text', 'Subscription');
cy.getByTestId('custom-row').should('contain.text', 'Other');
cy.getByTestId('dialog-close').click();
});
it('switch to other node', () => {
// 0006-NETW-017
// 0006-NETW-018
// 0006-NETW-019
// 0006-NETW-020
cy.getByTestId(nodeHealthTrigger).click();
cy.getByTestId('connect').should('be.disabled');
cy.getByTestId('node-url-custom').click({ force: true });
cy.getByTestId('connect').should('be.disabled');
cy.get("input[placeholder='https://']")
.focus()
.type(new URL(Cypress.env('VEGA_URL')).origin + '/graphql');
cy.getByTestId('connect').click();
});
});
});
@@ -1,204 +0,0 @@
const marketInfoBtn = 'Info';
const marketInfoSubtitle = 'accordion-title';
const marketSummaryBlock = 'header-summary';
const marketExpiry = 'market-expiry';
const marketPrice = 'market-price';
const marketChange = 'market-change';
const marketVolume = 'market-volume';
const marketMode = 'market-trading-mode';
const marketSettlement = 'market-settlement-asset';
const percentageValue = 'price-change-percentage';
const priceChangeValue = 'price-change';
const itemHeader = 'item-header';
const itemValue = 'item-value';
const marketListContent = 'popover-content';
describe(
'Console - market info - live env',
{ tags: '@live', testIsolation: true },
() => {
before(() => {
cy.visit('/');
cy.contains('Loading market data...').should('not.exist');
cy.getByTestId('link').should('be.visible');
cy.getByTestId('dialog-close').click();
cy.getByTestId(marketInfoBtn).click();
});
const titles = ['Market data', 'Market specification', 'Market governance'];
const subtitles = [
'Current fees',
'Market price',
'Market volume',
'Insurance pool',
'Key details',
'Instrument',
'Settlement asset',
'Metadata',
'Risk model',
'Risk parameters',
'Risk factors',
'Price monitoring bounds 1',
'Liquidity monitoring parameters',
'Liquidity',
'Liquidity price range',
'Oracle',
'Proposal',
];
it('market info titles are displayed', () => {
cy.getByTestId('split-view-view')
.find('.text-lg')
.each((element, index) => {
cy.wrap(element).should('have.text', titles[index]);
});
});
it('market info subtitles are displayed', () => {
cy.getByTestId('popover-trigger').click();
cy.contains('Loading market data...').should('not.exist');
cy.contains('[data-testid="link"]', 'AAVEDAI.MF21').click();
cy.getByTestId(marketInfoBtn).click();
cy.getByTestId(marketInfoSubtitle).each((element, index) => {
cy.wrap(element).should('have.text', subtitles[index]);
});
});
it('renders correctly liquidity in trading tab', () => {
cy.getByTestId('Liquidity').click();
cy.contains('Loading').should('not.exist');
cy.contains('Something went wrong').should('not.exist');
cy.contains('Application error').should('not.exist');
cy.getByTestId('tab-liquidity').within(() => {
cy.get('[col-id="partyId"]').eq(1).should('not.be.empty');
});
});
}
);
describe(
'Console - market summary - live env',
{ tags: '@live', testIsolation: true },
() => {
before(() => {
cy.visit('/');
cy.getByTestId('dialog-close').click();
cy.getByTestId(marketSummaryBlock).should('be.visible');
});
it('must display market name', () => {
cy.getByTestId('popover-trigger').should('not.be.empty');
});
it('must see market expiry', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketExpiry).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Expiry');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market price', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketPrice).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Price');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market change', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketChange).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Change (24h)');
cy.getByTestId(percentageValue).should('not.be.empty');
cy.getByTestId(priceChangeValue).should('not.be.empty');
});
});
});
it('must see market volume', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketVolume).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Volume (24h)');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market mode', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketMode).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Trading mode');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market settlement', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketSettlement).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Settlement asset');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
}
);
describe(
'Console - markets table - live env',
{ tags: '@live', testIsolation: true },
() => {
beforeEach(() => {
cy.visit('/');
});
it('renders markets correctly', () => {
cy.get('[data-testid^="market-link-"]').should('not.be.empty');
cy.getByTestId('price').invoke('text').should('not.be.empty');
cy.getByTestId('settlement-asset').should('not.be.empty');
cy.getByTestId('price-change-percentage').should('not.be.empty');
cy.getByTestId('price-change').should('not.be.empty');
cy.getByTestId('sparkline-svg').should('be.visible');
});
it('renders market list drop down', () => {
openMarketDropDown();
cy.getByTestId(marketListContent)
.find('[data-testid="price"]')
.invoke('text')
.should('not.be.empty');
cy.getByTestId(marketListContent)
.find('[data-testid="trading-mode-col"]')
.should('not.be.empty');
cy.getByTestId(marketListContent)
.find('[data-testid="taker-fee"]')
.should('contain.text', '%');
cy.getByTestId(marketListContent)
.find('[data-testid="market-volume"]')
.should('not.be.empty');
cy.getByTestId(marketListContent)
.find('[data-testid="market-name"]')
.should('not.be.empty');
});
it('Able to select market from dropdown', () => {
cy.getByTestId('popover-trigger')
.invoke('text')
.then((marketName) => {
openMarketDropDown();
cy.get('[data-testid^=market-link]').eq(1).click();
cy.getByTestId('popover-trigger').should('not.be.equal', marketName);
});
});
}
);
function openMarketDropDown() {
cy.contains('Loading...').should('not.exist');
cy.getByTestId('link').should('be.visible');
cy.getByTestId('dialog-close').click();
cy.getByTestId('popover-trigger').click();
cy.contains('Loading market data...').should('not.exist');
}
@@ -1,311 +0,0 @@
import { checkSorting } from '@vegaprotocol/cypress';
import * as Schema from '@vegaprotocol/types';
const liquidityTab = 'Liquidity';
const rowSelector =
'[data-testid="tab-liquidity"] .ag-center-cols-container .ag-row';
const rowSelectorLiquidityActive =
'[data-testid="tab-active"] .ag-center-cols-container .ag-row';
const rowSelectorLiquidityInactive =
'[data-testid="tab-inactive"] .ag-center-cols-container .ag-row';
const marketSummaryBlock = 'header-summary';
const itemValue = 'item-value';
const itemHeader = 'item-header';
const colCommitmentAmount = '[col-id="commitmentAmount"]';
const colEquityLikeShare = '[col-id="feeShare.equityLikeShare"]';
const colFee = '[col-id="fee"]';
const colCommitmentAmount_1 = '[col-id="commitmentAmount_1"]';
const colBalance = '[col-id="balance"]';
const colStatus = '[col-id="status"]';
const colCreatedAt = '[col-id="createdAt"] button';
const colUpdatedAt = '[col-id="updatedAt"] button';
const headers = [
'Party',
'Status',
'Commitment (tDAI)',
'Obligation',
'Fee',
'Adjusted stake share',
'Share',
'Live supplied liquidity',
'Fees accrued this epoch',
'Live time on book',
'Live liquidity quality score (%)',
'Last time on the book',
'Last fee penalty',
'Last bond penalty',
'Created',
'Updated',
];
describe('liquidity table - trading', { tags: '@smoke' }, () => {
before(() => {
cy.setOnBoardingViewed();
cy.mockSubscription();
cy.mockTradingPage(
Schema.MarketState.STATE_ACTIVE,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
);
cy.visit('/#/markets/market-0');
cy.wait('@MarketData');
cy.getByTestId(liquidityTab).click();
cy.wait('@LiquidityProvisions');
});
it('can see table headers', () => {
// 5002-LIQP-001
cy.getByTestId('tab-liquidity').within(($headers) => {
cy.wrap($headers)
.get('.ag-header-cell-text')
.each(($header, i) => {
cy.wrap($header).should('have.text', headers[i]);
});
});
});
it('renders liquidity table correctly', () => {
// 5002-LIQP-002
cy.get(rowSelector)
.first()
.find('[col-id="partyId"]')
.should('have.text', '69464e…dc6f');
cy.get(rowSelector)
.first()
.find(colCommitmentAmount)
.should('have.text', '4,000.00');
cy.get(rowSelector)
.first()
.find(colEquityLikeShare)
.should('have.text', '100.00%');
cy.get(rowSelector).first().find(colFee).should('have.text', '0.09%');
cy.get(rowSelector)
.first()
.find(colCommitmentAmount_1)
.should('have.text', '4,000.00');
cy.get(rowSelector)
.first()
.find(colBalance)
.scrollIntoView()
.should('have.text', '4,000.00');
cy.get(rowSelector).first().find(colStatus).should('have.text', 'Active');
cy.get(rowSelector).first().find(colCreatedAt).should('not.be.empty');
cy.get(rowSelector).first().find(colUpdatedAt).should('not.be.empty');
});
it('liquidity status column should be sorted properly', () => {
// 5002-LIQP-003
const liquidityColDefault = ['Active', 'Pending'];
const liquidityColAsc = ['Active', 'Pending'];
const liquidityColDesc = ['Pending', 'Active'];
checkSorting(
'status',
liquidityColDefault,
liquidityColAsc,
liquidityColDesc
);
});
});
describe('liquidity table view', { tags: '@smoke' }, () => {
before(() => {
cy.setOnBoardingViewed();
cy.mockSubscription();
cy.mockTradingPage(
Schema.MarketState.STATE_ACTIVE,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
);
cy.visit('/#/liquidity/market-0');
cy.wait('@LiquidityProvisions');
});
it('can see header title', () => {
// 5002-LIQP-004
// 5002-LIQP-005
cy.getByTestId('header-title').should(
'contain.text',
'BTCUSD.MF21 liquidity provision'
);
});
it('can see target stake', () => {
// 5002-LIQP-006
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId('target-stake').within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Target stake');
cy.getByTestId(itemValue).should('have.text', '10.00 tDAI').realHover();
});
});
cy.getByTestId('tooltip-content').should(
'contain.text',
`The market's liquidity requirement which is derived from the maximum open interest observed over a rolling time window.The market's liquidity requirement which is derived from the maximum open interest observed over a rolling time window.`
);
});
it('can see supplied stake', () => {
// 5002-LIQP-007
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId('supplied-stake').within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Supplied stake');
cy.getByTestId(itemValue).should('have.text', '0.01 tDAI').realHover();
});
});
cy.getByTestId('tooltip-content').should(
'contain.text',
'The current amount of liquidity supplied for this market.'
);
});
it('can see liquidity supplied', () => {
// 5002-LIQP-008
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId('liquidity-supplied').within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Liquidity supplied');
cy.getByTestId('indicator').should('be.visible');
cy.getByTestId(itemValue).should('have.text', ' 0.10%').realHover();
});
});
});
it('can see market id', () => {
// 5002-LIQP-009
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId('liquidity-market-id').within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Market ID');
cy.getByTestId(itemValue).should('have.text', 'market-0');
});
});
});
it('can see market id', () => {
// 5002-LIQP-010
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId('liquidity-learn-more').within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Learn more');
cy.getByTestId(itemValue).should('have.text', 'Providing liquidity');
cy.getByTestId('external-link')
.should('have.attr', 'href')
.and(
'include',
'https://docs.vega.xyz/testnet/concepts/liquidity/provision'
);
});
});
});
describe('liquidity table view', { tags: '@smoke' }, () => {
it('can see table headers', () => {
cy.getByTestId('tab-active').within(($headers) => {
cy.wrap($headers)
.get('.ag-header-cell-text')
.each(($header, i) => {
cy.wrap($header).should('have.text', headers[i]);
});
});
});
it('renders liquidity active table correctly', () => {
// 5002-LIQP-011
cy.get(rowSelectorLiquidityActive)
.first()
.find('[col-id="partyId"]')
.should('have.text', '69464e…dc6f');
cy.get(rowSelectorLiquidityActive)
.first()
.find(colCommitmentAmount)
.should('have.text', '4,000.00');
cy.get(rowSelectorLiquidityActive)
.first()
.find(colEquityLikeShare)
.should('have.text', '100.00%');
cy.get(rowSelectorLiquidityActive)
.first()
.find(colFee)
.should('have.text', '0.09%');
cy.get(rowSelectorLiquidityActive)
.first()
.find(colCommitmentAmount_1)
.should('have.text', '4,000.00');
cy.get(rowSelectorLiquidityActive)
.first()
.find(colBalance)
.should('have.text', '4,000.00');
cy.get(rowSelectorLiquidityActive)
.first()
.find(colStatus)
.should('have.text', 'Active');
cy.get(rowSelectorLiquidityActive)
.first()
.find(colCreatedAt)
.should('not.be.empty');
cy.get(rowSelectorLiquidityActive)
.first()
.find(colUpdatedAt)
.should('not.be.empty');
});
it('renders liquidity inactive table correctly', () => {
// 5002-LIQP-012
cy.getByTestId('Inactive').click();
cy.get(rowSelectorLiquidityInactive)
.first()
.find('[col-id="partyId"]')
.should('have.text', 'cc464e…dc6f');
cy.get(rowSelectorLiquidityInactive)
.first()
.find(colCommitmentAmount)
.should('have.text', '4,000.00');
cy.get(rowSelectorLiquidityInactive)
.first()
.find(colEquityLikeShare)
.should('have.text', '100.00%');
cy.get(rowSelectorLiquidityInactive)
.first()
.find(colFee)
.should('have.text', '0.40%');
cy.get(rowSelectorLiquidityInactive)
.first()
.find(colCommitmentAmount_1)
.should('have.text', '4,000.00');
cy.get(rowSelectorLiquidityInactive)
.first()
.find(colBalance)
.should('have.text', '2,000.00');
cy.get(rowSelectorLiquidityInactive)
.first()
.find(colStatus)
.should('have.text', 'Pending');
cy.get(rowSelectorLiquidityInactive)
.first()
.find(colCreatedAt)
.should('not.be.empty');
cy.get(rowSelectorLiquidityInactive)
.first()
.find(colUpdatedAt)
.should('not.be.empty');
});
});
});
@@ -1,47 +0,0 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { proposalListQuery, marketUpdateProposal } from '@vegaprotocol/mock';
import * as Schema from '@vegaprotocol/types';
const marketSummaryBlock = 'header-summary';
describe('Market proposal notification', { tags: '@smoke' }, () => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage(
Schema.MarketState.STATE_ACTIVE,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
);
cy.mockGQL((req) => {
aliasGQLQuery(
req,
'ProposalsList',
proposalListQuery({
proposalsConnection: {
edges: [{ node: marketUpdateProposal }],
},
})
);
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@MarketData');
cy.getByTestId(marketSummaryBlock).should('be.visible');
});
it('should display market proposal notification if proposal found', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId('market-proposal-notification').should(
'contain.text',
'Changes have been proposed for this market'
);
cy.getByTestId('market-proposal-notification').within(() => {
cy.getByTestId('external-link').should(
'have.attr',
'href',
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/123`
);
});
});
});
});
@@ -1,216 +0,0 @@
import * as Schema from '@vegaprotocol/types';
const expirtyTooltip = 'expiry-tooltip';
const externalLink = 'external-link';
const itemHeader = 'item-header';
const itemValue = 'item-value';
const link = 'link';
const liquidityLink = 'view-liquidity-link';
const liquiditySupplied = 'liquidity-supplied';
const liquiditySuppliedTooltip = 'liquidity-supplied-tooltip';
const marketChange = 'market-change';
const marketExpiry = 'market-expiry';
const marketMode = 'market-trading-mode';
const marketName = 'header-title';
const marketPrice = 'market-price';
const marketSettlement = 'market-settlement-asset';
const marketState = 'market-state';
const marketSummaryBlock = 'header-summary';
const marketVolume = 'market-volume';
const percentageValue = 'price-change-percentage';
const priceChangeValue = 'price-change';
const tradingModeTooltip = 'trading-mode-tooltip';
describe('Market trading page', () => {
before(() => {
cy.clearAllLocalStorage();
cy.mockTradingPage(
Schema.MarketState.STATE_ACTIVE,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
);
cy.mockSubscription();
cy.setOnBoardingViewed();
cy.visit('/#/markets/market-0');
cy.wait('@MarketData');
cy.getByTestId(marketSummaryBlock).should('be.visible');
});
describe('Market summary', { tags: '@smoke' }, () => {
// 7002-SORD-001
// 7002-SORD-002
it('must display market name', () => {
// 6002-MDET-001
cy.getByTestId(marketName).should('not.be.empty');
});
it('must see market expiry', () => {
// 6002-MDET-002
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketExpiry).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Expiry');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market price', () => {
// 6002-MDET-003
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketPrice).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Mark Price');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market change', () => {
// 6002-MDET-004
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketChange).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Change (24h)');
cy.getByTestId(percentageValue).should('not.be.empty');
cy.getByTestId(priceChangeValue).should('not.be.empty');
});
});
});
it('must see market volume', () => {
// 6002-MDET-005
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketVolume).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Volume (24h)');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market mode', () => {
// 6002-MDET-006
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketMode).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Trading mode');
cy.getByTestId(itemValue).should(
'have.text',
'Monitoring auction - liquidity (target not met)'
);
});
});
});
it('must see market status', () => {
// 6002-MDET-007
// 7002-SORD-061
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketState).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Status');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market settlement', () => {
// 6002-MDET-008
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketSettlement).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Settlement asset');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
it('must see market liquidity supplied', () => {
// 6002-MDET-009
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(liquiditySupplied).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Liquidity supplied');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
});
});
describe('Market tooltips', { tags: '@smoke' }, () => {
it('should see expiry tooltip', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketExpiry).within(() => {
cy.getByTestId(itemValue)
.should('have.text', 'Not time-based')
.realHover();
});
});
cy.getByTestId(expirtyTooltip)
.eq(0)
.should(
'contain.text',
'This market expires when triggered by its oracle, not on a set date.'
)
.within(() => {
cy.getByTestId(link)
.should('have.attr', 'href')
.and('include', Cypress.env('EXPLORER_URL'));
});
});
it('should see trading conditions tooltip', () => {
const toolTipLabel = 'tooltip-label';
const toolTipValue = 'tooltip-value';
const auctionToolTipLabels = [
'Auction start',
'Est. auction end',
'Target liquidity',
'Current liquidity',
'Est. uncrossing price',
'Est. uncrossing vol',
];
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketMode).within(() => {
cy.getByTestId(itemValue)
.should('contain.text', 'Monitoring auction')
.and('contain.text', 'liquidity')
.realHover();
});
});
cy.getByTestId(tradingModeTooltip)
.should(
'contain.text',
'This market is in auction until it reaches sufficient liquidity.'
)
.eq(0)
.within(() => {
cy.getByTestId(externalLink)
.should('have.attr', 'href')
.and('include', Cypress.env('TRADING_MODE_LINK'));
for (let i = 0; i < 6; i++) {
cy.getByTestId(toolTipLabel)
.eq(i)
.should('have.text', auctionToolTipLabels[i]);
cy.getByTestId(toolTipValue).eq(i).should('not.be.empty');
}
});
});
it('should see liquidity supplied tooltip', () => {
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(liquiditySupplied).within(() => {
cy.getByTestId(itemValue).realHover();
});
});
cy.getByTestId(liquiditySuppliedTooltip)
.should('contain.text', 'Supplied stake')
.and('contain.text', 'Target stake')
.first()
.within(() => {
cy.getByTestId(liquidityLink).should(
'have.text',
'View liquidity provision table'
);
cy.getByTestId(externalLink).should(
'have.text',
'Learn about providing liquidity'
);
});
});
});
});
@@ -1,87 +0,0 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import {
accountsQuery,
amendGeneralAccountBalance,
amendMarginAccountBalance,
} from '@vegaprotocol/mock';
describe.skip(
'account validation',
{ tags: '@regression', testIsolation: true },
() => {
describe('zero balance error', () => {
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
let accounts = accountsQuery();
accounts = amendMarginAccountBalance(accounts, 'market-0', '1000');
accounts = amendGeneralAccountBalance(accounts, 'market-0', '0');
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('should show an error if your balance is zero', () => {
const accounts = accountsQuery();
amendMarginAccountBalance(accounts, 'market-0', '0');
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
});
// 7002-SORD-060
cy.getByTestId('place-order').should('be.enabled');
// 7002-SORD-003
cy.getByTestId('deal-ticket-error-message-zero-balance').should(
'have.text',
'You need ' +
'tDAI' +
' in your wallet to trade in this market. See all your collateral.Make a deposit'
);
cy.getByTestId('deal-ticket-deposit-dialog-button').should('exist');
});
});
describe('not enough balance warning', () => {
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
let accounts = accountsQuery();
accounts = amendMarginAccountBalance(accounts, 'market-0', '1000');
accounts = amendGeneralAccountBalance(accounts, 'market-0', '1');
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
cy.get('[data-testid="deal-ticket-form"]').then(($form) => {
if (!$form.length) {
cy.getByTestId('Order').click();
}
});
});
it('should display info and button for deposit', () => {
// 7002-SORD-003
// warning should show immediately
cy.getByTestId('deal-ticket-warning-margin').should(
'contain.text',
'You may not have enough margin available to open this position'
);
cy.getByTestId('deal-ticket-warning-margin').should(
'contain.text',
'You may not have enough margin available to open this position. 5.00 tDAI is currently required. You have only 0.01001 tDAI available.'
);
cy.getByTestId('deal-ticket-deposit-dialog-button').click();
cy.getByTestId('sidebar-content')
.find('h2')
.eq(0)
.should('have.text', 'Deposit');
});
});
}
);
@@ -1,87 +0,0 @@
import * as Schema from '@vegaprotocol/types';
import { testOrderSubmission } from '../support/order-validation';
import type { OrderSubmission } from '@vegaprotocol/wallet';
import { createOrder } from '../support/create-order';
const displayTomorrow = () => {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
return tomorrow.toISOString().substring(0, 16);
};
describe(
'must submit order for market in batch auction',
{ tags: '@regression' },
() => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage(
Schema.MarketState.STATE_SUSPENDED,
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
);
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
beforeEach(() => {
cy.setVegaWallet();
});
it('successfully places limit buy order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '200',
};
createOrder(order);
testOrderSubmission(order, { price: '20000000' });
});
it('successfully places limit sell order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '50000',
};
createOrder(order);
testOrderSubmission(order, { price: '5000000000' });
});
it('successfully places GTT limit buy order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
size: '100',
postOnly: false,
reduceOnly: false,
price: '1.00',
expiresAt: displayTomorrow(),
};
createOrder(order);
testOrderSubmission(order, {
price: '100000',
postOnly: false,
reduceOnly: false,
expiresAt:
new Date(order.expiresAt as string).getTime().toString() + '000000',
});
});
}
);
@@ -1,85 +0,0 @@
import * as Schema from '@vegaprotocol/types';
import { testOrderSubmission } from '../support/order-validation';
import type { OrderSubmission } from '@vegaprotocol/wallet';
import { createOrder } from '../support/create-order';
const displayTomorrow = () => {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
return tomorrow.toISOString().substring(0, 16);
};
describe(
'must submit order for market in monitoring auction',
{ tags: '@regression' },
() => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage(
Schema.MarketState.STATE_SUSPENDED,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
);
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
beforeEach(() => {
cy.setVegaWallet();
});
it('successfully places limit buy order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '200',
};
createOrder(order);
testOrderSubmission(order, { price: '20000000' });
});
it('successfully places limit sell order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
price: '50000',
postOnly: false,
reduceOnly: false,
};
createOrder(order);
testOrderSubmission(order, { price: '5000000000' });
});
it('successfully places GTT limit buy order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
size: '100',
price: '1.00',
expiresAt: displayTomorrow(),
postOnly: false,
reduceOnly: false,
};
createOrder(order);
testOrderSubmission(order, {
price: '100000',
expiresAt:
new Date(order.expiresAt as string).getTime().toString() + '000000',
});
});
}
);
@@ -1,85 +0,0 @@
import * as Schema from '@vegaprotocol/types';
import { testOrderSubmission } from '../support/order-validation';
import type { OrderSubmission } from '@vegaprotocol/wallet';
import { createOrder } from '../support/create-order';
const displayTomorrow = () => {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
return tomorrow.toISOString().substring(0, 16);
};
describe(
'must submit order for market in opening auction',
{ tags: '@regression' },
() => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage(
Schema.MarketState.STATE_SUSPENDED,
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
);
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
beforeEach(() => {
cy.setVegaWallet();
});
it('successfully places limit buy order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '200',
};
createOrder(order);
testOrderSubmission(order, { price: '20000000' });
});
it('successfully places limit sell order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '50000',
};
createOrder(order);
testOrderSubmission(order, { price: '5000000000' });
});
it('successfully places GTT limit buy order', () => {
cy.mockVegaWalletTransaction();
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
size: '100',
price: '1.00',
expiresAt: displayTomorrow(),
postOnly: false,
reduceOnly: false,
};
createOrder(order);
testOrderSubmission(order, {
price: '100000',
expiresAt:
new Date(order.expiresAt as string).getTime().toString() + '000000',
});
});
}
);
@@ -1,103 +0,0 @@
import * as Schema from '@vegaprotocol/types';
import type { OrderSubmission } from '@vegaprotocol/wallet';
import { createOrder } from '../support/create-order';
describe(
'vega wallet - prompt',
{ tags: '@regression', testIsolation: true },
() => {
describe('must submit order', { tags: '@smoke' }, () => {
// 7002-SORD-039
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('must see a prompt to check connected vega wallet to approve transaction', () => {
// 0003-WTXN-002
cy.mockVegaWalletTransaction(1000);
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_MARKET,
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
size: '100',
};
createOrder(order);
cy.getByTestId('toast-content').should(
'contain.text',
'Please go to your Vega wallet application and approve or reject the transaction.'
);
});
it('must show error returned by wallet ', () => {
// 0003-WTXN-009
// 0003-WTXN-011
// 0002-WCON-016
// 0003-WTXN-008
//trigger error from the wallet
cy.intercept('POST', 'http://localhost:1789/api/v2/requests', (req) => {
req.on('response', (res) => {
res.send({
jsonrpc: '2.0',
id: '1',
});
});
});
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_MARKET,
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
size: '100',
};
createOrder(order);
cy.getByTestId('toast-content').should(
'contain.text',
'The connection to your Vega Wallet has been lost.'
);
cy.getByTestId('connect-vega-wallet').click();
cy.getByTestId('dialog-content').should('be.visible');
});
it('must see that the order was rejected by the connected wallet', () => {
// 0003-WTXN-007
//trigger rejection error from the wallet
cy.intercept('POST', 'http://localhost:1789/api/v2/requests', (req) => {
req.alias = 'client.send_transaction';
req.reply({
statusCode: 400,
body: {
jsonrpc: '2.0',
error: {
code: 3001,
data: 'the user rejected the wallet connection',
message: 'User error',
},
id: '0',
},
});
});
const order: OrderSubmission = {
marketId: 'market-0',
type: Schema.OrderType.TYPE_MARKET,
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
size: '100',
};
createOrder(order);
cy.getByTestId('toast-content').should(
'contain.text',
'Error occurredthe user rejected the wallet connection'
);
});
});
}
);
@@ -26,18 +26,6 @@ describe('ethereum wallet', { tags: '@smoke', testIsolation: true }, () => {
cy.getByTestId('tab-deposits').should('not.be.empty');
});
it.skip('should see QR code modal for WalletConnect', () => {
// 0004-EWAL-003
cy.getByTestId('Deposits').click();
cy.getByTestId('deposit-button').click();
cy.getByTestId('connect-eth-wallet-btn').click();
cy.getByTestId('web3-connector-list').should('exist');
cy.getByTestId('web3-connector-WalletConnect').click();
// testing if exists rather than visible because of the long loading time
cy.get('#w3m-modal').should('exist');
});
it('able to disconnect eth wallet', () => {
// 0004-EWAL-004
// 0004-EWAL-005
@@ -1,91 +0,0 @@
import {
mockConnectWallet,
mockConnectWalletWithUserError,
} from '@vegaprotocol/cypress';
const connectVegaBtn = 'connect-vega-wallet';
const manageVegaBtn = 'manage-vega-wallet';
const dialogContent = 'dialog-content';
describe('connect vega wallet', { tags: '@smoke', testIsolation: true }, () => {
beforeEach(() => {
// Using portfolio page as it requires vega wallet connection
cy.mockTradingPage();
cy.mockSubscription();
cy.setOnBoardingViewed();
cy.visit('/#/portfolio');
cy.get('[data-testid="pathname-/portfolio"]').should('exist');
});
it('can connect', () => {
// 0002-WCON-002
// 0002-WCON-005
// 0002-WCON-007
// 0002-WCON-009
mockConnectWallet();
cy.getByTestId(connectVegaBtn).click();
cy.getByTestId('connectors-list')
.find('[data-testid="connector-jsonRpc"]')
.click();
cy.wait('@walletReq');
cy.getByTestId(dialogContent).should(
'contain.text',
'Approve the connection from your Vega wallet app.'
);
cy.getByTestId(dialogContent).should('not.exist');
cy.getByTestId(manageVegaBtn).should('exist');
});
it('can not connect', () => {
// 0002-WCON-002
// 0002-WCON-005
// 0002-WCON-007
// 0002-WCON-015
mockConnectWalletWithUserError();
cy.getByTestId(connectVegaBtn).click();
cy.getByTestId('connectors-list')
.find('[data-testid="connector-jsonRpc"]')
.click();
cy.getByTestId('dialog-content')
.should('contain.text', 'User error')
.and('contain.text', 'the user rejected the wallet connection');
});
it('can change selected public key and disconnect', () => {
// 0002-WCON-022
// 0002-WCON-023
// 0002-WCON-025
// 0002-WCON-026
// 0002-WCON-021
// 0002-WCON-027
// 0002-WCON-030
// 0002-WCON-029
// 0002-WCON-008
// 0002-WCON-035
// 0002-WCON-014
// 0002-WCON-010
// 0003-WTXN-004
mockConnectWallet();
const key2 = Cypress.env('VEGA_PUBLIC_KEY2');
const truncatedKey2 = Cypress.env('TRUNCATED_VEGA_PUBLIC_KEY2');
cy.connectVegaWallet();
cy.getByTestId('manage-vega-wallet').click();
cy.getByTestId('keypair-list').should('exist');
cy.getByTestId(`key-${key2}`).should('contain.text', truncatedKey2);
cy.getByTestId(`key-${key2}`)
.find('[data-testid="copy-vega-public-key"]')
.should('be.visible');
cy.get(`[data-testid="key-${key2}"] > .mr-2`).click();
cy.getByTestId('keypair-list')
.find('[data-state="checked"]')
.should('be.visible');
cy.getByTestId('disconnect').click();
cy.getByTestId('connect-vega-wallet').should('exist');
cy.getByTestId('manage-vega-wallet').should('not.exist');
cy.getByTestId('connect-vega-wallet').click();
cy.contains('Enter a custom wallet location');
});
});
+2 -2
View File
@@ -22,9 +22,9 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_ICEBERG_ORDERS=true
# NX_PRODUCT_PERPETUALS
NX_METAMASK_SNAPS=true
NX_REFERRALS=false
NX_REFERRALS=true
# NX_DISABLE_CLOSE_POSITION=false
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
-1
View File
@@ -23,7 +23,6 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_ICEBERG_ORDERS=true
# NX_PRODUCT_PERPETUALS
NX_METAMASK_SNAPS=true
NX_REFERRALS=true
+2 -1
View File
@@ -1,9 +1,10 @@
import { t } from '@vegaprotocol/i18n';
import { useT } from '../../lib/use-t';
import { Links } from '../../lib/links';
import classNames from 'classnames';
import { NavLink, Outlet } from 'react-router-dom';
export const Assets = () => {
const t = useT();
const linkClasses = ({ isActive }: { isActive: boolean }) => {
return classNames('border-b-2 border-transparent', {
'border-vega-yellow': isActive,
@@ -1,4 +1,3 @@
import { t } from '@vegaprotocol/i18n';
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
import { GetStartedCheckList } from '../../components/welcome-dialog';
import {
@@ -8,8 +7,10 @@ import {
} from '../../components/welcome-dialog/use-get-onboarding-step';
import { Links } from '../../lib/links';
import classNames from 'classnames';
import { useT } from '../../lib/use-t';
export const DepositGetStarted = () => {
const t = useT();
const onboardingDismissed = useOnboardingStore((store) => store.dismissed);
const dismiss = useOnboardingStore((store) => store.dismiss);
const step = useGetOnboardingStep();
@@ -1,6 +1,7 @@
import { t } from '@vegaprotocol/i18n';
import { useT } from '../../lib/use-t';
export const Disclaimer = () => {
const t = useT();
return (
<>
<h1 className="text-4xl uppercase xl:text-5xl font-alpha calt">
@@ -8,37 +9,44 @@ export const Disclaimer = () => {
</h1>
<p className="mt-10 mb-6">
{t(
'Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets. The Vega Protocol is an implementation layer (layer one) protocol made of free, public, open-source or source-available software. Use of the Vega Protocol involves various risks, including but not limited to, losses while digital assets are supplied to the Vega Protocol and losses due to the fluctuation of prices of assets.'
'DISCLAIMER_P1',
'Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets. The Vega Protocol is an implementation layer (layer one) protocol made of free, public, open-source or source-available software. Use of the Vega Protocol involves various risks, including but not limited to, losses while digital assets are supplied to the Vega Protocol and losses due to the fluctuation of prices of assets.'
)}
</p>
<p className="mb-6">
{t(
'Before using the Vega Protocol, review the relevant documentation at docs.vega.xyz to make sure that you understand how it works. Conduct your own due diligence and consult your financial advisor before making any investment decisions.'
'DISCLAIMER_P2',
'Before using the Vega Protocol, review the relevant documentation at docs.vega.xyz to make sure that you understand how it works. Conduct your own due diligence and consult your financial advisor before making any investment decisions.'
)}
</p>
<p className="mb-6">
{t(
'As described in the Vega Protocol core license, the Vega Protocol is provided “as is”, at your own risk, and without warranties of any kind. Although Gobalsky Labs Limited developed much of the initial code for the Vega Protocol, it does not provide or control the Vega Protocol, which is run by third parties deploying it on a bespoke blockchain. Upgrades and modifications to the Vega Protocol are managed in a community-driven way by holders of the VEGA governance token.'
'DISCLAIMER_P3',
'As described in the Vega Protocol core license, the Vega Protocol is provided “as is”, at your own risk, and without warranties of any kind. Although Gobalsky Labs Limited developed much of the initial code for the Vega Protocol, it does not provide or control the Vega Protocol, which is run by third parties deploying it on a bespoke blockchain. Upgrades and modifications to the Vega Protocol are managed in a community-driven way by holders of the VEGA governance token.'
)}
</p>
<p className="mb-8">
{t(
'DISCLAIMER_P4',
'No developer or entity involved in creating the Vega Protocol will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the Vega Protocol, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or legal costs, or loss of profits, cryptoassets, tokens or anything else of value.'
)}
</p>
<p className="mb-8">
{t(
'This website is hosted on a decentralised network, the Interplanetary File System (“IPFS”). The IPFS decentralised web is made up of all the computers (nodes) connected to it. Data is therefore stored on many different computers.'
'DISCLAIMER_P5',
'This website is hosted on a decentralised network, the Interplanetary File System (“IPFS”). The IPFS decentralised web is made up of all the computers (nodes) connected to it. Data is therefore stored on many different computers.'
)}
</p>
<p className="mb-8">
{t(
"The information provided on this website does not constitute investment advice, financial advice, trading advice, or any other sort of advice and you should not treat any of the website's content as such. No party recommends that any cryptoasset should be bought, sold, or held by you via this website. No party ensures the accuracy of information listed on this website or holds any responsibility for any missing or wrong information. You understand that you are using any and all information available here at your own risk."
'DISCLAIMER_P6',
"The information provided on this website does not constitute investment advice, financial advice, trading advice, or any other sort of advice and you should not treat any of the website's content as such. No party recommends that any cryptoasset should be bought, sold, or held by you via this website. No party ensures the accuracy of information listed on this website or holds any responsibility for any missing or wrong information. You understand that you are using any and all information available here at your own risk."
)}
</p>
<p className="mb-8">
{t(
'Additionally, just as you can access email protocols such as SMTP through multiple email clients, you can potentially access the Vega Protocol through many web or mobile interfaces. You are responsible for doing your own diligence on those interfaces to understand the associated risks and any fees.'
'DISCLAIMER_P7',
'Additionally, just as you can access email protocols such as SMTP through multiple email clients, you can potentially access the Vega Protocol through many web or mobile interfaces. You are responsible for doing your own diligence on those interfaces to understand the associated risks and any fees.'
)}
</p>
</>
+21 -5
View File
@@ -1,11 +1,27 @@
import { t } from '@vegaprotocol/i18n';
import { useEffect } from 'react';
import { titlefy } from '@vegaprotocol/utils';
import { ErrorBoundary } from '../../components/error-boundary';
import { FeesContainer } from '../../components/fees-container';
import { useT } from '../../lib/use-t';
import { usePageTitleStore } from '../../stores';
export const Fees = () => {
const t = useT();
const title = t('Fees');
const { updateTitle } = usePageTitleStore((store) => ({
updateTitle: store.updateTitle,
}));
useEffect(() => {
updateTitle(titlefy([title]));
}, [updateTitle, title]);
return (
<div className="container p-4 mx-auto">
<h1 className="px-4 pb-4 text-2xl">{t('Fees')}</h1>
<FeesContainer />
</div>
<ErrorBoundary feature="fees">
<div className="container p-4 mx-auto">
<h1 className="px-4 pb-4 text-2xl">{title}</h1>
<FeesContainer />
</div>
</ErrorBoundary>
);
};

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