Compare commits

...
Author SHA1 Message Date
daniel1302 85a70cb172 fix: linter issue 2023-02-08 16:51:42 +01:00
Daniel 3a7e9e72af feat: archive logs in cypres pr run 2023-02-08 15:46:28 +01:00
mattrussell36 5d613396e1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-08 12:09:14 +00:00
Sam Keen da551f9d3c feat(governance): replace proposal and vote busEvents with subscriptions (#2862) 2023-02-08 09:42:20 +00:00
Edd 47e4861fdb fix(explorer): use position decimal places to format size in order (#2861) 2023-02-08 08:22:27 +00:00
mattrussell36 1a85a89440 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-08 06:06:13 +00:00
mattrussell36 7ab412a8f7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-08 00:12:40 +00:00
Edd 5a14174a81 feat(explorer): add issuesignatures tx view (#2867) 2023-02-07 18:17:00 +00:00
mattrussell36 5e00b93783 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-07 18:06:49 +00:00
Edd 31d9b023e6 feat(explorer): change party to pubkey (#2868) 2023-02-07 18:00:26 +00:00
mattrussell36 103e503a47 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-07 12:07:30 +00:00
Maciek 1952cb0e78 fix(trading): inform the user his connection to wallet is lost (#2863) 2023-02-07 11:31:15 +01:00
mattrussell36 69340f4ddf chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-07 06:06:15 +00:00
mattrussell36 c52bf2200e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-07 00:10:59 +00:00
Matthew Russell 8dccee69f2 chore(trading): remove unnecessary sentry capture from asyncrenderer component (#2869) 2023-02-06 15:21:39 -08:00
Art c7a6fdd879 chore(trading): new toasts designs (#2779) 2023-02-06 20:09:56 +00:00
Matthew Russell 8bcdaf4cda feat(trading): key to key transfers (#2784) 2023-02-06 11:35:40 -08:00
mattrussell36 3eb1359504 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-06 18:08:25 +00:00
Sam Keen 39cf8ad4d6 feat(governance): remove some performance info from validator mouseover (#2865) 2023-02-06 17:08:34 +00:00
Edd faef98f0ae fix(explorer): type generation broken in an oracle refactor (#2859) 2023-02-06 13:29:23 +00:00
macqbat 710e2daa27 chore(trading): notification component redesign (#2845) 2023-02-06 13:31:35 +01:00
daro-maj 06ea3924fa chore(trading): increase withdraw ac test coverage (#2853) 2023-02-06 13:27:12 +01:00
mattrussell36 965e2d8972 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-06 12:09:01 +00:00
m.ray 73de2fed43 fix(trading): when order is rejected change tx toast intent (#2851) 2023-02-06 11:44:04 +00:00
Sam Keen 536859e067 feat(governance): visual tweaks to main nav (#2839) 2023-02-06 11:18:14 +00:00
Sam Keen 54bfaef473 fix(governance): empty div disrupts other page elements (#2855) 2023-02-06 10:35:26 +00:00
Matthew Russell e2cad707a7 chore(trading): add validator testnet env file (#2852) 2023-02-06 09:04:34 +00:00
mattrussell36 ec8d9798ab chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-06 06:08:16 +00:00
mattrussell36 e629c1e81a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-06 00:10:27 +00:00
mattrussell36 25feed793c chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-05 18:08:10 +00:00
mattrussell36 2867367e16 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-05 12:07:47 +00:00
mattrussell36 50b408e74d chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-05 06:05:57 +00:00
mattrussell36 8f531c7c05 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-05 00:13:19 +00:00
mattrussell36 350d16fee1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-04 18:07:27 +00:00
mattrussell36 c052c66266 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-04 12:06:25 +00:00
mattrussell36 e2032df236 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-04 06:07:41 +00:00
Matthew Russell 9ece19869d chore(trading): update order subs to not use busevents (#2849) 2023-02-03 16:12:20 -08:00
Joe Tsang 22abc8160c test(token): pending balances (#2843) 2023-02-03 19:26:17 +00:00
Edd b1a7a22bf9 feat(explorer): add protocol upgrade view (#2802) 2023-02-03 19:25:36 +00:00
mattrussell36 c4b38cc0dc chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-03 18:05:46 +00:00
m.ray 44d6d931d5 fix(trading): update async renderer on error (#2842) 2023-02-03 16:52:10 +00:00
m.ray 7f1e47d7fd fix(trading): remove price flash cell from PNL (#2829) 2023-02-03 14:59:24 +00:00
Art 0eddfa4073 fix(ui-toolkit): dark and light shades mismatch (#2841) 2023-02-03 12:33:13 +00:00
mattrussell36 83a034ce91 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-03 12:06:17 +00:00
5ab5aa01a2 feat(trading): 2803 console announcement banner (#2830)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2023-02-03 10:34:32 +00:00
mattrussell36 b22f9156b5 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-03 06:07:49 +00:00
mattrussell36 bab5e2018b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-03 00:12:30 +00:00
macqbat 3f7692ce75 chore(trading): add alpha font to trading (#2833) 2023-02-02 19:25:14 +01:00
mattrussell36 b69fb3b0e5 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-02 18:08:33 +00:00
macqbat 83af6e74f6 chore(trading): no data message in charts (#2816) 2023-02-02 18:43:16 +01:00
m.ray b9908003ba fix(trading): fix symbol on order estimates (#2827) 2023-02-02 13:30:47 +00:00
Sam KeenandMatthew Russell 1f9af79215 feat(ui-toolkit): mainnet sims announcement banner (#2806)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-02-02 13:13:55 +00:00
Sam Keen e31e40a7ef feat(ui-toolkit): mainnet sims announcement banner (#2806) 2023-02-02 12:56:22 +00:00
mattrussell36 81f6b3cc15 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-02 12:08:12 +00:00
mattrussell36 8adb208a91 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-02 06:06:32 +00:00
mattrussell36 545c3a17d2 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-02 00:09:59 +00:00
mattrussell36 ad76988f63 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-01 18:08:30 +00:00
Sam KeenandDexter d2bbd7e1fc feat(governance): pending balances: add event listeners (#2541)
Co-authored-by: Dexter <dexter.edwards93@gmail.com>
2023-02-01 16:02:50 +00:00
macqbat fb1ebb3bdf chore(trading): remove noise form the test logs (#2801) 2023-02-01 16:58:47 +01:00
m.ray b2489537ef fix(trading): market data and auction time not updating (#2813) 2023-02-01 14:08:49 +00:00
Sam Keen 382a7ea411 feat(governance): body can scroll again after clicking 'back to staking' (#2785) 2023-02-01 12:56:25 +00:00
mattrussell36 1ae2b4c153 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-01 12:06:46 +00:00
mattrussell36 e8875e817e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-01 06:06:26 +00:00
mattrussell36 4a01c880f3 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-01 00:10:41 +00:00
mattrussell36 f7f00dc7bb chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-31 18:07:31 +00:00
macqbat d151b6e923 chore(trading): add sub statuses of opening auction trading mode (#2797) 2023-01-31 17:31:55 +01:00
Sam Keen 8f8e9c1061 feat(ui-toolkit): announcement banner to highlight mainnet sims (#2800) 2023-01-31 16:12:44 +00:00
m.ray b40358a723 fix(trading): consolidate view as user mode (#2778) 2023-01-31 16:04:52 +00:00
Art 01f0934da3 chore(ui-toolkit): new colour palette (#2783) 2023-01-31 16:33:16 +01:00
mattrussell36 df7755dbc4 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-31 12:06:33 +00:00
Joe Tsang 9073234040 test(ci): fix tags in cypress workflow (#2788) 2023-01-31 11:35:42 +00:00
Art 053cd0fa27 fix(trading): asset option on mobile got overflown (#2782) 2023-01-31 11:10:55 +01:00
mattrussell36 961dc88dc7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-31 06:08:30 +00:00
mattrussell36 b16607a844 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-31 00:13:30 +00:00
Matthew Russell d0d804631c chore(ci): add nx scope linting for pr title (#2781) 2023-01-30 21:06:18 +00:00
daro-maj 3e778a88dc chore: capsule tests refactor and increase deposit ac (#2773) 2023-01-30 20:35:58 +01:00
Edd dbb09c9c79 fix(explorer): correct calculation for whether party txs list has more txs (#2774) 2023-01-30 18:23:09 +00:00
Edd 06f44b67de fix(explorer): tx viewer dropdown did not correctly represent state (#2780) 2023-01-30 18:17:47 +00:00
Joe Tsang 1861852852 test(2704): proposals with market (#2775) 2023-01-30 18:06:04 +00:00
mattrussell36 3ee0eee80d chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 12:09:00 +00:00
mattrussell36 69ce870a81 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 06:06:56 +00:00
mattrussell36 d8467c3206 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-30 00:12:51 +00:00
mattrussell36 de87f40a01 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-29 18:08:12 +00:00
247 changed files with 6041 additions and 2440 deletions
+14
View File
@@ -50,6 +50,20 @@ jobs:
projects=[${projects// /,}] projects=[${projects// /,}]
echo PROJECTS=$projects >> $GITHUB_ENV echo PROJECTS=$projects >> $GITHUB_ENV
# Rename required because some of the files contains the colon character (in the dates)
- name: Rename files to allow archive
if: ${{ always() }}
run: |
while read -r file; do
mv "${file}" "$(echo ${file} | sed 's|:|-|g')"
done< <(find /home/runner/.vegacapsule/testnet/logs -type f)
- uses: actions/upload-artifact@v3
if: ${{ always() }}
with:
name: logs-${{ matrix.project }}
path: /home/runner/.vegacapsule/testnet/logs
outputs: outputs:
projects: ${{ env.PROJECTS }} projects: ${{ env.PROJECTS }}
+1 -2
View File
@@ -64,12 +64,11 @@ jobs:
###### ######
- name: Run Cypress tests - name: Run Cypress tests
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome --env.grepTags="${{ inputs.tags }}"
working-directory: frontend-monorepo working-directory: frontend-monorepo
env: env:
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }} CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }} CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}
CYPRESS_grepTags: ${{ inputs.tags }}
###### ######
## Upload logs ## Upload logs
+7 -5
View File
@@ -8,14 +8,16 @@ jobs:
lint_pr: lint_pr:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node.js 16 - name: Use Node.js 16
id: Node id: Node
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: 16.14.0 node-version: 16.14.0
- name: Install commitlint cli and config - name: Install root dependencies
run: npm install @commitlint/cli @commitlint/config-conventional run: yarn install
- name: Create config
run: echo "module.exports = {extends:['@commitlint/config-conventional']};" > commitlint.config.js
- name: Check PR title - name: Check PR title
run: echo "${{ github.event.pull_request.title }}" | npx commitlint run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
+2 -2
View File
@@ -6,7 +6,7 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"} NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
NX_TENDERMINT_URL=https://tm.n01.sandbox.vega.xyz NX_TENDERMINT_URL=https://tm.sandbox.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.sandbox.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://tm.sandbox.vega.xyz/websocket
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz
+1
View File
@@ -6,3 +6,4 @@ NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_VEGA_GOVERNANCE_URL=https://stagnet3.token.vega.xyz NX_VEGA_GOVERNANCE_URL=https://stagnet3.token.vega.xyz
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases/
+10
View File
@@ -8,6 +8,7 @@ import { Main } from './components/main';
import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider'; import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider';
import type { InMemoryCacheConfig } from '@apollo/client'; import type { InMemoryCacheConfig } from '@apollo/client';
import { Footer } from './components/footer/footer'; import { Footer } from './components/footer/footer';
import { AnnouncementBanner, ExternalLink } from '@vegaprotocol/ui-toolkit';
function App() { function App() {
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
@@ -40,6 +41,15 @@ function App() {
return ( return (
<TendermintWebsocketProvider> <TendermintWebsocketProvider>
<NetworkLoader cache={cacheConfig}> <NetworkLoader cache={cacheConfig}>
<AnnouncementBanner>
<div className="font-alpha calt uppercase text-center text-lg text-white">
<span className="pr-4">The Mainnet sims are live!</span>
<ExternalLink href="https://fairground.wtf/">
Come help stress test the network
</ExternalLink>
</div>
</AnnouncementBanner>
<div className={layoutClasses}> <div className={layoutClasses}>
<Header menuOpen={menuOpen} setMenuOpen={setMenuOpen} /> <Header menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<Nav menuOpen={menuOpen} /> <Nav menuOpen={menuOpen} />
@@ -2,6 +2,7 @@ query ExplorerMarket($id: ID!) {
market(id: $id) { market(id: $id) {
id id
decimalPlaces decimalPlaces
positionDecimalPlaces
tradableInstrument { tradableInstrument {
instrument { instrument {
name name
@@ -8,7 +8,7 @@ export type ExplorerMarketQueryVariables = Types.Exact<{
}>; }>;
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null }; export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null };
export const ExplorerMarketDocument = gql` export const ExplorerMarketDocument = gql`
@@ -16,6 +16,7 @@ export const ExplorerMarketDocument = gql`
market(id: $id) { market(id: $id) {
id id
decimalPlaces decimalPlaces
positionDecimalPlaces
tradableInstrument { tradableInstrument {
instrument { instrument {
name name
@@ -55,6 +55,7 @@ describe('Market link component', () => {
market: { market: {
id: '123', id: '123',
decimalPlaces: 5, decimalPlaces: 5,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data', state: 'irrelevant-test-data',
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
@@ -117,7 +117,7 @@ const NestedDataListItem = ({
)} )}
</h4> </h4>
{!hasChildren && ( {!hasChildren && (
<code className="text-vega-light-400 mb-2 last:mb-0 dark:text-vega-dark-400 break-all"> <code className="text-vega-light-100 mb-2 last:mb-0 dark:text-vega-dark-100 break-all">
{JSON.stringify(value, null, ' ')} {JSON.stringify(value, null, ' ')}
</code> </code>
)} )}
@@ -19,6 +19,7 @@ fragment ExplorerDeterministicOrderFields on Order {
market { market {
id id
decimalPlaces decimalPlaces
positionDecimalPlaces
tradableInstrument { tradableInstrument {
instrument { instrument {
name name
@@ -3,7 +3,7 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client'; import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client'; import * as Apollo from '@apollo/client';
const defaultOptions = {} as const; const defaultOptions = {} as const;
export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } }; export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } };
export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{ export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
orderId: Types.Scalars['ID']; orderId: Types.Scalars['ID'];
@@ -11,7 +11,7 @@ export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
}>; }>;
export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } } }; export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } } };
export const ExplorerDeterministicOrderFieldsFragmentDoc = gql` export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
fragment ExplorerDeterministicOrderFields on Order { fragment ExplorerDeterministicOrderFields on Order {
@@ -35,6 +35,7 @@ export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
market { market {
id id
decimalPlaces decimalPlaces
positionDecimalPlaces
tradableInstrument { tradableInstrument {
instrument { instrument {
name name
@@ -61,6 +61,7 @@ function renderExistingAmend(id: string, version: number, amend: Amend) {
__typename: 'Market', __typename: 'Market',
id: '789', id: '789',
state: 'STATUS_ACTIVE', state: 'STATUS_ACTIVE',
positionDecimalPlaces: 2,
decimalPlaces: '5', decimalPlaces: '5',
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
@@ -88,6 +89,7 @@ function renderExistingAmend(id: string, version: number, amend: Amend) {
market: { market: {
id: '789', id: '789',
decimalPlaces: 5, decimalPlaces: 5,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data', state: 'irrelevant-test-data',
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
@@ -4,6 +4,7 @@ import { MarketLink } from '../links';
import PriceInMarket from '../price-in-market/price-in-market'; import PriceInMarket from '../price-in-market/price-in-market';
import { Time } from '../time'; import { Time } from '../time';
import { sideText, statusText, tifFull, tifShort } from './lib/order-labels'; import { sideText, statusText, tifFull, tifShort } from './lib/order-labels';
import SizeInMarket from '../size-in-market/size-in-market';
export interface DeterministicOrderDetailsProps { export interface DeterministicOrderDetailsProps {
id: string; id: string;
@@ -90,7 +91,7 @@ const DeterministicOrderDetails = ({
<div className="mb-12 md:mb-0"> <div className="mb-12 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-4">{t('Size')}</h2> <h2 className="text-2xl font-bold text-dark mb-4">{t('Size')}</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0"> <h5 className="text-lg font-medium text-gray-500 mb-0">
{o.size} <SizeInMarket size={o.size} marketId={o.market.id} />
</h5> </h5>
</div> </div>
@@ -38,6 +38,7 @@ const mock = {
__typename: 'Market', __typename: 'Market',
id: '789', id: '789',
state: 'STATE_ACTIVE', state: 'STATE_ACTIVE',
positionDecimalPlaces: 2,
decimalPlaces: 2, decimalPlaces: 2,
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
@@ -90,6 +90,7 @@ describe('Order TX Summary component', () => {
market: { market: {
id: '123', id: '123',
decimalPlaces: 2, decimalPlaces: 2,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data', state: 'irrelevant-test-data',
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
@@ -37,6 +37,7 @@ const fullMock = {
market: { market: {
id: '123', id: '123',
decimalPlaces: 2, decimalPlaces: 2,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data', state: 'irrelevant-test-data',
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
@@ -1,5 +1,4 @@
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import React from 'react';
import { StatusMessage } from '../status-message'; import { StatusMessage } from '../status-message';
interface RenderFetchedProps { interface RenderFetchedProps {
@@ -66,7 +66,9 @@ export const Search = () => {
className="text-white" className="text-white"
hasError={Boolean(error?.message)} hasError={Boolean(error?.message)}
type="text" type="text"
placeholder={t('Enter block number, party id or transaction hash')} placeholder={t(
'Enter block number, public key or transaction hash'
)}
/> />
{error?.message && ( {error?.message && (
<div className="bg-white border border-t-0 border-accent absolute top-[100%] flex-1 w-full pb-2 px-2 rounded-b text-black"> <div className="bg-white border border-t-0 border-accent absolute top-[100%] flex-1 w-full pb-2 px-2 rounded-b text-black">
@@ -0,0 +1,69 @@
import { MemoryRouter } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing';
import type { MockedResponse } from '@apollo/client/testing';
import { render } from '@testing-library/react';
import SizeInMarket from './size-in-market';
import type { DecimalSource } from './size-in-market';
import { ExplorerMarketDocument } from '../links/market-link/__generated__/Market';
function renderComponent(
price: string,
marketId: string,
mocks: MockedResponse[],
decimalSource: DecimalSource = 'MARKET'
) {
return (
<MockedProvider mocks={mocks} addTypename={false}>
<MemoryRouter>
<SizeInMarket
marketId={marketId}
size={price}
decimalSource={decimalSource}
/>
</MemoryRouter>
</MockedProvider>
);
}
const fullMock = {
request: {
query: ExplorerMarketDocument,
variables: {
id: '123',
},
},
result: {
data: {
market: {
id: '123',
decimalPlaces: 2,
positionDecimalPlaces: 2,
state: 'irrelevant-test-data',
tradableInstrument: {
instrument: {
name: 'test dai',
product: {
__typename: 'Future',
quoteName: 'dai',
settlementAsset: {
decimals: 18,
},
},
},
},
},
},
},
};
describe('Size in Market component', () => {
it('Renders the raw size when there is no market data', () => {
const res = render(renderComponent('100', '123', []));
expect(res.getByText('100')).toBeInTheDocument();
});
it('Renders the formatted size when market data is fetched', async () => {
const res = render(renderComponent('100', '123', [fullMock]));
expect(await res.findByText('1.00')).toBeInTheDocument();
});
});
@@ -0,0 +1,41 @@
import { addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market';
export type DecimalSource = 'MARKET';
export type PriceInMarketProps = {
marketId: string;
size: string | number;
decimalSource?: DecimalSource;
};
/**
* Given a market ID and an order size it will fetch the market
* order size, and format the size accordingly
*/
const SizeInMarket = ({
marketId,
size,
decimalSource = 'MARKET',
}: PriceInMarketProps) => {
const { data } = useExplorerMarketQuery({
variables: { id: marketId },
fetchPolicy: 'cache-first',
});
let label = size;
if (data) {
if (decimalSource === 'MARKET' && data.market?.positionDecimalPlaces) {
label = addDecimalsFormatNumber(size, data.market.positionDecimalPlaces);
}
}
return (
<label>
<span>{label}</span>
</label>
);
};
export default SizeInMarket;
@@ -0,0 +1,62 @@
import { t } from '@vegaprotocol/react-helpers';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table';
import { BlockLink } from '../../links';
import { StatusMessage } from '../../status-message';
import { ENV } from '../../../config/env';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import type { components } from '../../../../types/explorer';
interface TxDetailsProtocolUpgradeProps {
txData: BlockExplorerTransactionResult | undefined;
pubKey: string | undefined;
blockData: TendermintBlocksResponse | undefined;
}
/**
* Validator event: Protocol Upgrade proposal
*/
export const TxDetailsProtocolUpgrade = ({
txData,
pubKey,
blockData,
}: TxDetailsProtocolUpgradeProps) => {
if (!txData) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const upgrade: components['schemas']['v1ProtocolUpgradeProposal'] =
txData.command.protocolUpgradeProposal;
if (!upgrade || !upgrade.upgradeBlockHeight || !upgrade.vegaReleaseTag) {
return (
<StatusMessage>{t('Invalid upgrade proposal format')}</StatusMessage>
);
}
const urlBase = ENV.dataSources.vegaRepoUrl;
const release = upgrade.vegaReleaseTag;
return (
<TableWithTbody className="mb-8">
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
<TableRow modifier="bordered">
<TableCell>{t('Upgrade at block')}</TableCell>
<TableCell>
<BlockLink height={upgrade.upgradeBlockHeight} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Upgrade to')}</TableCell>
<TableCell>
<ExternalLink href={`${urlBase}${release}`}>
{upgrade.vegaReleaseTag}
</ExternalLink>
</TableCell>
</TableRow>
</TableWithTbody>
);
};
@@ -19,6 +19,8 @@ import { TxDetailsLiquidityAmendment } from './tx-liquidity-amend';
import { TxDetailsLiquidityCancellation } from './tx-liquidity-cancel'; import { TxDetailsLiquidityCancellation } from './tx-liquidity-cancel';
import { TxDetailsDataSubmission } from './tx-data-submission'; import { TxDetailsDataSubmission } from './tx-data-submission';
import { TxProposalVote } from './tx-proposal-vote'; import { TxProposalVote } from './tx-proposal-vote';
import { TxDetailsProtocolUpgrade } from './tx-details-protocol-upgrade';
import { TxDetailsIssueSignatures } from './tx-issue-signatures';
interface TxDetailsWrapperProps { interface TxDetailsWrapperProps {
txData: BlockExplorerTransactionResult | undefined; txData: BlockExplorerTransactionResult | undefined;
@@ -66,10 +68,14 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
// These come from https://github.com/vegaprotocol/vega/blob/develop/core/txn/command.go#L72-L98 // These come from https://github.com/vegaprotocol/vega/blob/develop/core/txn/command.go#L72-L98
switch (txData.type) { switch (txData.type) {
case 'Issue Signatures':
return TxDetailsIssueSignatures;
case 'Submit Order': case 'Submit Order':
return TxDetailsOrder; return TxDetailsOrder;
case 'Submit Oracle Data': case 'Submit Oracle Data':
return TxDetailsDataSubmission; return TxDetailsDataSubmission;
case 'Protocol Upgrade':
return TxDetailsProtocolUpgrade;
case 'Cancel Order': case 'Cancel Order':
return TxDetailsOrderCancel; return TxDetailsOrderCancel;
case 'Amend Order': case 'Amend Order':
@@ -11,8 +11,7 @@ interface TxDetailsGenericProps {
} }
/** /**
* If there is not yet a custom component for a transaction, just display * A node is
* the basic details. This allows someone to view the decoded transaction.
*/ */
export const TxDetailsGeneric = ({ export const TxDetailsGeneric = ({
txData, txData,
@@ -0,0 +1,77 @@
import { t } from '@vegaprotocol/react-helpers';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableRow, TableCell, TableWithTbody } from '../../table';
import type { components } from '../../../../types/explorer';
import {
EthExplorerLink,
EthExplorerLinkTypes,
} from '../../links/eth-explorer-link/eth-explorer-link';
import { NodeLink } from '../../links';
type Command = components['schemas']['v1IssueSignatures'];
const kind: Record<components['schemas']['v1NodeSignatureKind'], string> = {
NODE_SIGNATURE_KIND_UNSPECIFIED: 'Unspecified',
NODE_SIGNATURE_KIND_ASSET_NEW: 'New asset',
NODE_SIGNATURE_KIND_ASSET_WITHDRAWAL: 'Asset withdrawal',
NODE_SIGNATURE_KIND_ASSET_UPDATE: ' Asset update',
NODE_SIGNATURE_KIND_ERC20_MULTISIG_SIGNER_ADDED: 'Multisig signer added',
NODE_SIGNATURE_KIND_ERC20_MULTISIG_SIGNER_REMOVED: 'Multisig signer removed',
};
interface TxDetailsGenericProps {
txData: BlockExplorerTransactionResult | undefined;
pubKey: string | undefined;
blockData: TendermintBlocksResponse | undefined;
}
/**
* If there is not yet a custom component for a transaction, just display
* the basic details. This allows someone to view the decoded transaction.
*/
export const TxDetailsIssueSignatures = ({
txData,
pubKey,
blockData,
}: TxDetailsGenericProps) => {
if (!txData) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const cmd: Command = txData.command;
const k = cmd.kind ? kind[cmd.kind] : null;
return (
<TableWithTbody className="mb-8">
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
{k ? (
<TableRow modifier="bordered">
<TableCell>{t('Kind')}</TableCell>
<TableCell>{k}</TableCell>
</TableRow>
) : null}
{cmd.submitter ? (
<TableRow modifier="bordered">
<TableCell>{t('ETH key')}</TableCell>
<TableCell>
<EthExplorerLink
id={cmd.submitter}
type={EthExplorerLinkTypes.address}
/>
</TableCell>
</TableRow>
) : null}
{cmd.validatorNodeId ? (
<TableRow modifier="bordered">
<TableCell>{t('Validator')}</TableCell>
<TableCell>
<NodeLink id={cmd.validatorNodeId} />
</TableCell>
</TableRow>
) : null}
</TableWithTbody>
);
};
@@ -1,10 +1,11 @@
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import { MarketLink } from '../../links'; import { MarketLink } from '../../links';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared'; import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table'; import { TableCell, TableRow, TableWithTbody } from '../../table';
import type { components } from '../../../../types/explorer'; import type { components } from '../../../../types/explorer';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
export type LiquidityCancellation = export type LiquidityCancellation =
components['schemas']['v1LiquidityProvisionCancellation']; components['schemas']['v1LiquidityProvisionCancellation'];
@@ -63,7 +63,7 @@ export const TxDataView = ({ txData, blockData }: TxDataViewProps) => {
<Select <Select
placeholder="View as..." placeholder="View as..."
onChange={(v) => setShowTxData(v.target.value as ShowTxDataType)} onChange={(v) => setShowTxData(v.target.value as ShowTxDataType)}
value={'JSON'} value={showTxData}
> >
<option value={'JSON'}>JSON</option> <option value={'JSON'}>JSON</option>
<option value={'base64'}>Base64</option> <option value={'base64'}>Base64</option>
+2
View File
@@ -10,6 +10,7 @@ const truthy = ['1', 'true'];
export const ENV = { export const ENV = {
// Data sources // Data sources
// Environment // Environment
env: windowOrDefault('NX_VEGA_ENV'),
dsn: windowOrDefault('NX_EXPLORER_SENTRY_DSN'), dsn: windowOrDefault('NX_EXPLORER_SENTRY_DSN'),
dataSources: { dataSources: {
blockExplorerUrl: windowOrDefault('NX_BLOCK_EXPLORER'), blockExplorerUrl: windowOrDefault('NX_BLOCK_EXPLORER'),
@@ -17,6 +18,7 @@ export const ENV = {
tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'), tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'),
ethExplorerUrl: windowOrDefault('NX_ETHERSCAN_URL'), ethExplorerUrl: windowOrDefault('NX_ETHERSCAN_URL'),
governanceUrl: windowOrDefault('NX_VEGA_GOVERNANCE_URL'), governanceUrl: windowOrDefault('NX_VEGA_GOVERNANCE_URL'),
vegaRepoUrl: windowOrDefault('NX_VEGA_REPO_URL'),
}, },
flags: { flags: {
assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')), assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')),
+5 -4
View File
@@ -5,6 +5,7 @@ import type {
BlockExplorerTransactions, BlockExplorerTransactions,
} from '../routes/types/block-explorer-response'; } from '../routes/types/block-explorer-response';
import { DATA_SOURCES } from '../config'; import { DATA_SOURCES } from '../config';
import isNumber from 'lodash/isNumber';
export interface TxsStateProps { export interface TxsStateProps {
txsData: BlockExplorerTransactionResult[]; txsData: BlockExplorerTransactionResult[];
@@ -54,15 +55,15 @@ export const useTxsData = ({ limit, filters }: IUseTxsData) => {
} = useFetch<BlockExplorerTransactions>(url, {}, false); } = useFetch<BlockExplorerTransactions>(url, {}, false);
useEffect(() => { useEffect(() => {
if (data?.transactions?.length) { if (data && isNumber(data?.transactions?.length)) {
setTxsState((prev) => ({ setTxsState((prev) => ({
txsData: [...prev.txsData, ...data.transactions], txsData: [...prev.txsData, ...data.transactions],
hasMoreTxs: true, hasMoreTxs: data.transactions.length > 0,
lastCursor: lastCursor:
data.transactions[data.transactions.length - 1].cursor || '', data.transactions[data.transactions.length - 1]?.cursor || '',
})); }));
} }
}, [setTxsState, data?.transactions]); }, [setTxsState, data]);
const loadTxs = useCallback(() => { const loadTxs = useCallback(() => {
return refetch({ return refetch({
@@ -10,7 +10,7 @@ export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec',
export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>; export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null }; export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } } } } | null> | null } | null };
export type ExplorerOracleSpecByIdQueryVariables = Types.Exact<{ export type ExplorerOracleSpecByIdQueryVariables = Types.Exact<{
id: Types.Scalars['ID']; id: Types.Scalars['ID'];
@@ -73,7 +73,7 @@ export const ExplorerOracleDataSourceFragmentDoc = gql`
`; `;
export const ExplorerOracleDataConnectionFragmentDoc = gql` export const ExplorerOracleDataConnectionFragmentDoc = gql`
fragment ExplorerOracleDataConnection on OracleSpec { fragment ExplorerOracleDataConnection on OracleSpec {
dataConnection(pagination: {first: 1}) { dataConnection {
pageInfo { pageInfo {
hasNextPage hasNextPage
} }
@@ -113,13 +113,11 @@ export const ExplorerOracleSpecsDocument = gql`
edges { edges {
node { node {
...ExplorerOracleDataSource ...ExplorerOracleDataSource
...ExplorerOracleDataConnection
} }
} }
} }
} }
${ExplorerOracleDataSourceFragmentDoc} ${ExplorerOracleDataSourceFragmentDoc}`;
${ExplorerOracleDataConnectionFragmentDoc}`;
/** /**
* __useExplorerOracleSpecsQuery__ * __useExplorerOracleSpecsQuery__
@@ -22,7 +22,7 @@ export type SourceType =
interface OracleDetailsProps { interface OracleDetailsProps {
id: string; id: string;
dataSource: ExplorerOracleDataSourceFragment; dataSource: ExplorerOracleDataSourceFragment;
dataConnection: ExplorerOracleDataConnectionFragment; dataConnection?: ExplorerOracleDataConnectionFragment;
// Defaults to false. Hides the count of 'broadcasts' this oracle has seen // Defaults to false. Hides the count of 'broadcasts' this oracle has seen
showBroadcasts?: boolean; showBroadcasts?: boolean;
} }
@@ -41,7 +41,8 @@ export const OracleDetails = ({
showBroadcasts = false, showBroadcasts = false,
}: OracleDetailsProps) => { }: OracleDetailsProps) => {
const sourceType = dataSource.dataSourceSpec.spec.data.sourceType; const sourceType = dataSource.dataSourceSpec.spec.data.sourceType;
const reportsCount: number = dataConnection.dataConnection.edges?.length || 0; const reportsCount: number =
dataConnection?.dataConnection.edges?.length || 0;
return ( return (
<div> <div>
@@ -63,7 +64,9 @@ export const OracleDetails = ({
</TableRow> </TableRow>
</TableWithTbody> </TableWithTbody>
<OracleFilter data={dataSource} /> <OracleFilter data={dataSource} />
{showBroadcasts ? <OracleData data={dataConnection} /> : null} {showBroadcasts && dataConnection ? (
<OracleData data={dataConnection} />
) : null}
</div> </div>
); );
}; };
@@ -28,7 +28,7 @@ const Oracles = () => {
<OracleDetails <OracleDetails
id={id} id={id}
dataSource={o?.node} dataSource={o?.node}
dataConnection={o?.node} showBroadcasts={false}
/> />
<details> <details>
<summary className="pointer">JSON</summary> <summary className="pointer">JSON</summary>
@@ -10,7 +10,7 @@ import { useDocumentTitle } from '../../../hooks/use-document-title';
export const JumpToParty = () => { export const JumpToParty = () => {
const navigate = useNavigate(); const navigate = useNavigate();
useDocumentTitle(['Parties']); useDocumentTitle(['Public keys']);
const handleSubmit = (e: React.SyntheticEvent) => { const handleSubmit = (e: React.SyntheticEvent) => {
e.preventDefault(); e.preventDefault();
@@ -27,8 +27,8 @@ export const JumpToParty = () => {
}; };
return ( return (
<JumpTo <JumpTo
label={t('Go to party')} label={t('Go to public key')}
placeholder={t('Party id')} placeholder={t('Public key')}
inputId="party-input" inputId="party-input"
inputType="text" inputType="text"
inputName="partyId" inputName="partyId"
@@ -40,7 +40,7 @@ export const JumpToParty = () => {
const Parties = () => { const Parties = () => {
return ( return (
<section> <section>
<RouteTitle data-testid="parties-header">{t('Parties')}</RouteTitle> <RouteTitle data-testid="parties-header">{t('Public keys')}</RouteTitle>
<JumpToParty /> <JumpToParty />
</section> </section>
); );
@@ -14,7 +14,7 @@ type PartyIdErrorProps = {
const PartyIdError = ({ id, error }: PartyIdErrorProps) => { const PartyIdError = ({ id, error }: PartyIdErrorProps) => {
const end = isValidPartyId(id) const end = isValidPartyId(id)
? t('No accounts or transactions found for: ') ? t('No accounts or transactions found for: ')
: 'Invalid party id: '; : 'Invalid public key: ';
return ( return (
<section> <section>
<p> <p>
@@ -16,7 +16,7 @@ import { PartyAccounts } from './components/party-accounts';
const Party = () => { const Party = () => {
const { party } = useParams<{ party: string }>(); const { party } = useParams<{ party: string }>();
useDocumentTitle(['Parties', party || '-']); useDocumentTitle(['Public keys', party || '-']);
const partyId = toNonHex(party ? party : ''); const partyId = toNonHex(party ? party : '');
const { isMobile } = useScreenDimensions(); const { isMobile } = useScreenDimensions();
const visibleChars = useMemo(() => (isMobile ? 10 : 14), [isMobile]); const visibleChars = useMemo(() => (isMobile ? 10 : 14), [isMobile]);
@@ -44,7 +44,7 @@ const Party = () => {
/> />
) : ( ) : (
<Panel> <Panel>
<p>No party found for key {party}</p> <p>No data found for public key {party}</p>
</Panel> </Panel>
); );
@@ -71,7 +71,7 @@ const Party = () => {
className="font-alpha uppercase font-xl mb-4 text-zinc-800 dark:text-zinc-200" className="font-alpha uppercase font-xl mb-4 text-zinc-800 dark:text-zinc-200"
data-testid="parties-header" data-testid="parties-header"
> >
{t('Party')} {t('Public key')}
</h1> </h1>
{partyRes.data ? ( {partyRes.data ? (
<> <>
@@ -38,7 +38,7 @@ const Tx = () => {
to={`/${Routes.TX}`} to={`/${Routes.TX}`}
> >
<Icon <Icon
className="text-vega-light-300 dark:text-vega-light-300" className="text-vega-light-150 dark:text-vega-light-150"
name={IconNames.CHEVRON_LEFT} name={IconNames.CHEVRON_LEFT}
/> />
All Transactions All Transactions
Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

File diff suppressed because it is too large Load Diff
+12
View File
@@ -16,4 +16,16 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
#Test configuration variables #Test configuration variables
CYPRESS_FAIRGROUND=false CYPRESS_FAIRGROUND=false
CYPRESS_VEGA_URL=http://localhost:3028/query CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
CYPRESS_EXPLORER_URL=https://explorer.fairground.wtf
CYPRESS_FAUCET_URL=http://localhost:1790/api/v1/mint
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY=02ecea…342f65
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=7f9cf0…c25535
CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN= CYPRESS_VEGA_WALLET_API_TOKEN=
@@ -2,27 +2,29 @@
"changes": { "changes": {
"decimalPlaces": "5", "decimalPlaces": "5",
"positionDecimalPlaces": "5", "positionDecimalPlaces": "5",
"lpPriceRange": "10",
"instrument": { "instrument": {
"name": "Oranges Daily", "name": "Token test market",
"code": "ORANGES.24h", "code": "Token.24h",
"future": { "future": {
"settlementAsset": "8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4", "settlementAsset": "fBTC",
"quoteName": "tEuro", "quoteName": "fBTC",
"settlementDataDecimals": 5,
"dataSourceSpecForSettlementData": { "dataSourceSpecForSettlementData": {
"external": {
"oracle": {
"signers": [ "signers": [
{ {
"signer": { "pubKey": {
"__typename": "ETHAddress", "key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
"address": "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"
} }
} }
], ],
"filters": [ "filters": [
{ {
"key": { "key": {
"name": "prices.BTC.value", "name": "prices.ETH.value",
"type": "TYPE_INTEGER" "type": "TYPE_INTEGER",
"numberDecimalPlaces": "0"
}, },
"conditions": [ "conditions": [
{ {
@@ -32,26 +34,27 @@
] ]
} }
] ]
}
}
}, },
"dataSourceSpecForTradingTermination": { "dataSourceSpecForTradingTermination": {
"signers": [ "signers": [
{ {
"signer": { "pubKey": {
"__typename": "ETHAddress", "key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
"address": "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"
} }
} }
], ],
"filters": [ "filters": [
{ {
"key": { "key": {
"name": "vegaprotocol.builtin.timestamp", "name": "trading.terminated.ETH5",
"type": "TYPE_TIMESTAMP" "type": "TYPE_BOOLEAN"
}, },
"conditions": [ "conditions": [
{ {
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL", "operator": "OPERATOR_EQUALS",
"value": "1648684800000000000" "value": "true"
} }
] ]
} }
@@ -59,7 +62,7 @@
}, },
"dataSourceSpecBinding": { "dataSourceSpecBinding": {
"settlementPriceProperty": "prices.BTC.value", "settlementPriceProperty": "prices.BTC.value",
"tradingTerminationProperty": "vegaprotocol.builtin.timestamp" "tradingTerminationProperty": "trading.terminated.ETH5"
} }
} }
}, },
@@ -1,24 +1,21 @@
{ {
"marketId": "315a8e48db0a292c92b617264728048c82c20efc922c75fd292fc54e5c727c81",
"changes": {
"instrument": { "instrument": {
"code": "ORANGES.24h", "code": "TEST.24h",
"future": { "future": {
"quoteName": "tEuro", "quoteName": "fUSDC",
"settlementDataDecimals": 5, "settlementDataDecimals": 5,
"dataSourceSpecForSettlementData": { "dataSourceSpecForSettlementData": {
"signers": [ "signers": [
{ {
"signer": { "pubKey": {
"__typename": "ETHAddress", "key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
"address": "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"
} }
} }
], ],
"filters": [ "filters": [
{ {
"key": { "key": {
"name": "prices.BTC.value", "name": "prices.ETH.value",
"type": "TYPE_INTEGER" "type": "TYPE_INTEGER"
}, },
"conditions": [ "conditions": [
@@ -33,17 +30,16 @@
"dataSourceSpecForTradingTermination": { "dataSourceSpecForTradingTermination": {
"signers": [ "signers": [
{ {
"signer": { "pubKey": {
"__typename": "ETHAddress", "key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
"address": "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"
} }
} }
], ],
"filters": [ "filters": [
{ {
"key": { "key": {
"name": "vegaprotocol.builtin.timestamp", "name": "trading.terminated.ETH5",
"type": "TYPE_TIMESTAMP" "type": "TYPE_BOOLEAN"
}, },
"conditions": [ "conditions": [
{ {
@@ -55,8 +51,8 @@
] ]
}, },
"dataSourceSpecBinding": { "dataSourceSpecBinding": {
"settlementPriceProperty": "prices.BTC.value", "settlementPriceProperty": "prices.ETH.value",
"tradingTerminationProperty": "vegaprotocol.builtin.timestamp" "tradingTerminationProperty": "trading.terminated.ETH5"
} }
} }
}, },
@@ -79,5 +75,4 @@
"sigma": 0.3 "sigma": 0.3
} }
} }
}
} }
@@ -1 +1 @@
123 0123245
@@ -11,6 +11,7 @@ const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const dialogCloseButton = '[data-testid="dialog-close"]'; const dialogCloseButton = '[data-testid="dialog-close"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]'; const viewProposalButton = '[data-testid="view-proposal-btn"]';
const openProposals = '[data-testid="open-proposals"]'; const openProposals = '[data-testid="open-proposals"]';
const closedProposals = '[data-testid="closed-proposals"]';
const proposalVoteProgressForPercentage = const proposalVoteProgressForPercentage =
'[data-testid="vote-progress-indicator-percentage-for"]'; '[data-testid="vote-progress-indicator-percentage-for"]';
const proposalVoteProgressAgainstPercentage = const proposalVoteProgressAgainstPercentage =
@@ -22,7 +23,9 @@ const proposalVoteProgressAgainstTokens =
const changeVoteButton = '[data-testid="change-vote-button"]'; const changeVoteButton = '[data-testid="change-vote-button"]';
const proposalDetailsTitle = '[data-testid="proposal-title"]'; const proposalDetailsTitle = '[data-testid="proposal-title"]';
const proposalDetailsDescription = '[data-testid="proposal-description"]'; const proposalDetailsDescription = '[data-testid="proposal-description"]';
const proposalStatus = '[data-testid="proposal-status"]';
const rawProposalData = '[data-testid="proposal-data"]'; const rawProposalData = '[data-testid="proposal-data"]';
const votesTable = '[data-testid="votes-table"]';
const minVoteButton = '[data-testid="min-vote"]'; const minVoteButton = '[data-testid="min-vote"]';
const maxVoteButton = '[data-testid="max-vote"]'; const maxVoteButton = '[data-testid="max-vote"]';
const voteButtons = '[data-testid="vote-buttons"]'; const voteButtons = '[data-testid="vote-buttons"]';
@@ -37,6 +40,10 @@ const txTimeout = Cypress.env('txTimeout');
const epochTimeout = Cypress.env('epochTimeout'); const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 }; const proposalTimeout = { timeout: 14000 };
const minCloseDays = 2;
const maxCloseDays = 3;
const requiredParticipation = 0.001;
const governanceProposalType = { const governanceProposalType = {
NETWORK_PARAMETER: 'Network parameter', NETWORK_PARAMETER: 'Network parameter',
NEW_MARKET: 'New market', NEW_MARKET: 'New market',
@@ -65,21 +72,6 @@ context(
network_parameters['governance.proposal.freeform.requiredMajority'] * network_parameters['governance.proposal.freeform.requiredMajority'] *
100 100
).as('requiredMajority'); ).as('requiredMajority');
cy.wrap(
network_parameters[
'governance.proposal.freeform.requiredParticipation'
] * 100
).as('requiredParticipation');
cy.wrap(
network_parameters['governance.proposal.freeform.minClose'].split(
'h'
)[0] / 24
).as('minCloseDays');
cy.wrap(
network_parameters['governance.proposal.freeform.maxClose'].split(
'h'
)[0] / 24
).as('maxCloseDays');
cy.wrap( cy.wrap(
network_parameters['governance.proposal.freeform.minClose'].split( network_parameters['governance.proposal.freeform.minClose'].split(
'h' 'h'
@@ -108,21 +100,6 @@ context(
0.00001, 0.00001,
'Asserting that value is at least 0.00001 for network parameter minVoterBalance' 'Asserting that value is at least 0.00001 for network parameter minVoterBalance'
); );
assert.isAtLeast(
parseFloat(this.requiredParticipation),
0.00001,
'Asserting that value is at least 0.00001 for network parameter requiredParticipation'
);
assert.isAtLeast(
parseInt(this.minCloseDays),
1,
'Asserting that value is at least 1 for network parameter minCloseDays'
);
assert.isAtLeast(
parseInt(this.maxCloseDays),
parseInt(this.minCloseDays + 1),
'Asserting that network parameter maxCloseDays is at least 1 day higher than minCloseDays'
);
// workaround for first eth tx hanging // workaround for first eth tx hanging
associateTokenStartOfTests(); associateTokenStartOfTests();
} }
@@ -182,10 +159,10 @@ context(
this.minProposerBalance this.minProposerBalance
); );
let proposalDays = [ let proposalDays = [
this.minCloseDays + 1, minCloseDays + 1,
this.maxCloseDays, maxCloseDays,
this.minCloseDays + 3, minCloseDays + 3,
this.minCloseDays + 2, minCloseDays + 2,
]; ];
for (var index = 0; index < proposalDays.length; index++) { for (var index = 0; index < proposalDays.length; index++) {
cy.go_to_make_new_proposal(governanceProposalType.RAW); cy.go_to_make_new_proposal(governanceProposalType.RAW);
@@ -227,6 +204,7 @@ context(
cy.navigate_to('validators'); cy.navigate_to('validators');
cy.click_on_validator_from_list(0); cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2'); cy.staking_validator_page_add_stake('2');
cy.close_staking_dialog();
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2'); cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
@@ -297,10 +275,12 @@ context(
}); });
}); });
// Skipping test due to bug: #1320 // 3001-VOTE-071
it.skip('Newly created freeform proposals list - shows proposal participation - both met and not', function () { it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
createFreeformProposal(this.minProposerBalance); const proposalTitle = generateProposalTitle();
cy.get_submitted_proposal_from_proposal_list() createFreeformProposal(this.minProposerBalance, proposalTitle);
cy.get_submitted_proposal_from_proposal_list(proposalTitle)
.as('submittedProposal') .as('submittedProposal')
.within(() => { .within(() => {
// 3001-VOTE-039 // 3001-VOTE-039
@@ -312,7 +292,7 @@ context(
.invoke('text') .invoke('text')
.then((totalSupply) => { .then((totalSupply) => {
let tokensRequiredToAchieveResult = parseFloat( let tokensRequiredToAchieveResult = parseFloat(
(totalSupply.replace(/,/g, '') * this.requiredParticipation) / 100 (totalSupply.replace(/,/g, '') * requiredParticipation) / 100
).toFixed(2); ).toFixed(2);
cy.ensure_specified_unstaked_tokens_are_associated( cy.ensure_specified_unstaked_tokens_are_associated(
tokensRequiredToAchieveResult tokensRequiredToAchieveResult
@@ -321,16 +301,17 @@ context(
cy.get('@submittedProposal').within(() => cy.get('@submittedProposal').within(() =>
cy.get(viewProposalButton).click() cy.get(viewProposalButton).click()
); );
cy.get_proposal_information_from_table('Participation met') cy.get_proposal_information_from_table('Token participation met')
.contains('👍') .contains('👍')
.should('be.visible'); .should('be.visible');
cy.navigate_to('proposals'); cy.navigate_to('proposals');
cy.get('@submittedProposal').within(() => cy.get('@submittedProposal').within(() =>
cy.get(voteStatus).should('have.text', 'Participation met') cy.get(voteStatus).should('have.text', 'Set to pass')
); );
}); });
}); });
// 3001-VOTE-055
it('Newly created raw proposal details - shows proposal title and full description', function () { it('Newly created raw proposal details - shows proposal title and full description', function () {
createRawProposal(this.minProposerBalance); createRawProposal(this.minProposerBalance);
cy.get('@rawProposal').then((rawProposal) => { cy.get('@rawProposal').then((rawProposal) => {
@@ -357,6 +338,7 @@ context(
}); });
}); });
// 3001-VOTE-043
it('Newly created freeform proposal details - shows proposed and closing dates', function () { it('Newly created freeform proposal details - shows proposed and closing dates', function () {
const closingVoteHrs = '72'; const closingVoteHrs = '72';
const proposalTitle = generateProposalTitle(); const proposalTitle = generateProposalTitle();
@@ -399,6 +381,7 @@ context(
it('Newly created proposal details - shows default status set to fail', function () { it('Newly created proposal details - shows default status set to fail', function () {
// 3001-VOTE-037 // 3001-VOTE-037
// 3001-VOTE-040 // 3001-VOTE-040
// 3001-VOTE-067
createRawProposal(this.minProposerBalance); createRawProposal(this.minProposerBalance);
cy.get('@rawProposal').then((rawProposal) => { cy.get('@rawProposal').then((rawProposal) => {
cy.get_submitted_proposal_from_proposal_list( cy.get_submitted_proposal_from_proposal_list(
@@ -413,15 +396,17 @@ context(
.should('be.visible'); .should('be.visible');
// 3001-VOTE-062 // 3001-VOTE-062
// 3001-VOTE-040 // 3001-VOTE-040
// 3001-VOTE-070
cy.get_proposal_information_from_table('Token majority met') cy.get_proposal_information_from_table('Token majority met')
.contains('👎') .contains('👎')
.should('be.visible'); .should('be.visible');
// 3001-VOTE-068
cy.get_proposal_information_from_table('Token participation met') cy.get_proposal_information_from_table('Token participation met')
.contains('👎') .contains('👎')
.should('be.visible'); .should('be.visible');
}); });
// 3001-VOTE-080 3001-VOTE-090 // 3001-VOTE-080 3001-VOTE-090 3001-VOTE-069 3001-VOTE-072 3001-VOTE-073
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () { it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
createRawProposal(this.minProposerBalance); createRawProposal(this.minProposerBalance);
cy.get('@rawProposal').then((rawProposal) => { cy.get('@rawProposal').then((rawProposal) => {
@@ -446,7 +431,7 @@ context(
.contains(votedDate) .contains(votedDate)
.should('be.visible'); .should('be.visible');
}); });
cy.get(proposalVoteProgressForPercentage) cy.get(proposalVoteProgressForPercentage) // 3001-VOTE-072
.contains('100.00%') .contains('100.00%')
.and('be.visible'); .and('be.visible');
cy.get(proposalVoteProgressAgainstPercentage) cy.get(proposalVoteProgressAgainstPercentage)
@@ -466,10 +451,10 @@ context(
.and('be.visible'); .and('be.visible');
// 3001-VOTE-061 // 3001-VOTE-061
cy.get_proposal_information_from_table('Participation required') cy.get_proposal_information_from_table('Participation required')
.contains(`${this.requiredParticipation}%`) .contains(`${requiredParticipation}%`)
.should('be.visible'); .should('be.visible');
// 3001-VOTE-066 // 3001-VOTE-066
cy.get_proposal_information_from_table('Majority Required') cy.get_proposal_information_from_table('Majority Required') // 3001-VOTE-073
.contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`) .contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`)
.should('be.visible'); .should('be.visible');
cy.get_proposal_information_from_table('Number of voting parties') cy.get_proposal_information_from_table('Number of voting parties')
@@ -512,7 +497,7 @@ context(
.invoke('text') .invoke('text')
.then((totalSupply) => { .then((totalSupply) => {
let tokensRequiredToAchieveResult = parseFloat( let tokensRequiredToAchieveResult = parseFloat(
(totalSupply.replace(/,/g, '') * this.requiredParticipation) / 100 (totalSupply.replace(/,/g, '') * requiredParticipation) / 100
).toFixed(2); ).toFixed(2);
cy.ensure_specified_unstaked_tokens_are_associated( cy.ensure_specified_unstaked_tokens_are_associated(
tokensRequiredToAchieveResult tokensRequiredToAchieveResult
@@ -536,6 +521,11 @@ context(
cy.get(proposalVoteProgressAgainstTokens) cy.get(proposalVoteProgressAgainstTokens)
.contains('0.00') .contains('0.00')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table(
'Total tokens voted percentage'
)
.should('have.text', '0.00%')
.and('be.visible');
cy.get_proposal_information_from_table('Tokens for proposal') cy.get_proposal_information_from_table('Tokens for proposal')
.should('have.text', tokensRequiredToAchieveResult) .should('have.text', tokensRequiredToAchieveResult)
.and('be.visible'); .and('be.visible');
@@ -588,6 +578,7 @@ context(
); );
}); });
// 3001-VOTE-006
it('Creating a proposal - proposal rejected - able to access rejected proposals', function () { it('Creating a proposal - proposal rejected - able to access rejected proposals', function () {
cy.ensure_specified_unstaked_tokens_are_associated( cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance this.minProposerBalance
@@ -649,6 +640,7 @@ context(
cy.get(dialogCloseButton).click(); cy.get(dialogCloseButton).click();
}); });
// 3002-PROP-009
it('Unable to create a proposal - when some but not enough tokens are associated', function () { it('Unable to create a proposal - when some but not enough tokens are associated', function () {
cy.ensure_specified_unstaked_tokens_are_associated( cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance - 0.000001 this.minProposerBalance - 0.000001
@@ -669,7 +661,7 @@ context(
}); });
it('Unable to create a freeform proposal - when json parent section contains unexpected field', function () { it('Unable to create a freeform proposal - when json parent section contains unexpected field', function () {
// 3001-VOTE-038 // 3001-VOTE-038 3002-PROP-013 3002-PROP-014
cy.ensure_specified_unstaked_tokens_are_associated( cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance this.minProposerBalance
); );
@@ -695,6 +687,9 @@ context(
'Invalid params: the transaction is malformed' 'Invalid params: the transaction is malformed'
); );
cy.get(dialogCloseButton).click(); cy.get(dialogCloseButton).click();
cy.get(rawProposalData)
.invoke('val')
.should('contain', "i shouldn't be here");
}); });
it('Unable to create a freeform proposal - when json terms section contains unexpected field', function () { it('Unable to create a freeform proposal - when json terms section contains unexpected field', function () {
@@ -792,6 +787,107 @@ context(
cy.contains('You voted: Against').should('be.visible'); cy.contains('You voted: Against').should('be.visible');
}); });
// 3001-VOTE-006
it('Able to view enacted proposal', function () {
cy.createMarket();
cy.reload();
cy.wait_for_spinner();
cy.get(closedProposals).within(() => {
cy.get(proposalDetailsTitle).should(
'have.text',
'Add Lorem Ipsum market'
);
cy.get(proposalStatus).should('have.text', 'Enacted ');
cy.get(viewProposalButton).click();
});
cy.getByTestId('proposal-type').should('have.text', 'New market');
cy.get_proposal_information_from_table('State')
.contains('Enacted')
.and('be.visible');
cy.get(votesTable).within(() => {
cy.contains('Vote passed.').should('be.visible');
cy.contains('Voting has ended.').should('be.visible');
});
});
// 3001-VOTE-047
it('Able to enact freeform proposal', function () {
const proposalTitle = 'Add New free form proposal with short enactment';
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance
);
cy.sendWalletTxFreeFormProposal();
cy.navigate_to('proposals');
cy.reload();
cy.wait_for_spinner();
cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
cy.get_proposal_information_from_table('State')
.contains('Open')
.and('be.visible');
cy.vote_for_proposal('for');
cy.get_proposal_information_from_table('State')
.contains('Enacted', epochTimeout)
.and('be.visible');
});
// 3001-VOTE-046 3001-VOTE-044 3001-VOTE-074 3001-VOTE-074
it('Able to enact proposal by voting', function () {
const proposalTitle = 'Add New proposal with short enactment';
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance
);
cy.sendWalletTxUpdateNetworkProposal();
cy.navigate_to('proposals');
cy.reload();
cy.wait_for_spinner();
cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
cy.get_proposal_information_from_table('State')
.contains('Open')
.and('be.visible');
cy.vote_for_proposal('for');
cy.get_proposal_information_from_table('State') // 3001-VOTE-047
.contains('Passed', txTimeout)
.and('be.visible');
cy.get_proposal_information_from_table('State')
.contains('Enacted', epochTimeout)
.and('be.visible');
cy.get(votesTable).within(() => {
cy.contains('Vote passed.').should('be.visible');
cy.contains('Voting has ended.').should('be.visible');
});
cy.get(proposalVoteProgressForPercentage)
.contains('100.00%')
.and('be.visible');
});
// 3001-VOTE-048 3001-VOTE-049
it('Able to fail proposal due to lack of participation', function () {
const proposalTitle = 'Add New free form proposal with short enactment';
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance
);
cy.sendWalletTxFreeFormProposal();
cy.navigate_to('proposals');
cy.reload();
cy.wait_for_spinner();
cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
cy.get_proposal_information_from_table('State')
.contains('Open')
.and('be.visible');
cy.get_proposal_information_from_table('State') // 3001-VOTE-047
.contains('Declined', txTimeout)
.and('be.visible');
cy.get_proposal_information_from_table('Rejection reason')
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
.and('be.visible');
});
function createRawProposal(proposerBalance) { function createRawProposal(proposerBalance) {
if (proposerBalance) if (proposerBalance)
cy.ensure_specified_unstaked_tokens_are_associated(proposerBalance); cy.ensure_specified_unstaked_tokens_are_associated(proposerBalance);
@@ -1,3 +1,7 @@
const proposalListItem = '[data-testid="proposals-list-item"]';
const openProposals = '[data-testid="open-proposals"]';
const proposalType = '[data-testid="proposal-type"]';
const proposalDetails = '[data-testid="proposal-details"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]'; const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]'; const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
const proposalValidationDeadline = const proposalValidationDeadline =
@@ -209,18 +213,15 @@ context(
); );
}); });
// skipped because no markets available to select in capsule
it.skip('Able to submit update market proposal', function () { it.skip('Able to submit update market proposal', function () {
const marketId =
'315a8e48db0a292c92b617264728048c82c20efc922c75fd292fc54e5c727c81';
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_MARKET); cy.go_to_make_new_proposal(governanceProposalType.UPDATE_MARKET);
cy.get(newProposalTitle).type('Test update asset proposal'); cy.get(newProposalTitle).type('Test update market proposal');
cy.get(newProposalDescription).type('E2E test for proposals'); cy.get(newProposalDescription).type('E2E test for proposals');
cy.get(proposalMarketSelect).select(marketId); cy.get(proposalMarketSelect).select('Test market 1');
cy.get('[data-testid="update-market-details"]').within(() => { cy.get('[data-testid="update-market-details"]').within(() => {
cy.get('dd').eq(0).should('have.text', 'Oranges Daily'); cy.get('dd').eq(0).should('have.text', 'Test market 1');
cy.get('dd').eq(1).should('have.text', 'ORANGES.24h'); cy.get('dd').eq(1).should('have.text', 'TEST.24h');
cy.get('dd').eq(2).should('have.text', marketId); cy.get('dd').eq(2).should('not.be.empty');
}); });
cy.fixture('/proposals/update-market').then((updateMarketProposal) => { cy.fixture('/proposals/update-market').then((updateMarketProposal) => {
let newUpdateMarketProposal = JSON.stringify(updateMarketProposal); let newUpdateMarketProposal = JSON.stringify(updateMarketProposal);
@@ -281,12 +282,28 @@ context(
}); });
it('Able to submit update asset proposal using min deadline', function () { it('Able to submit update asset proposal using min deadline', function () {
const assetId =
'ebcd94151ae1f0d39a4bde3b21a9c7ae81a80ea4352fb075a92e07608d9c953d';
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_ASSET); cy.go_to_make_new_proposal(governanceProposalType.UPDATE_ASSET);
enterUpdateAssetProposalDetails(); enterUpdateAssetProposalDetails();
cy.get(minVoteDeadline).click(); cy.get(minVoteDeadline).click();
cy.get(minEnactDeadline).click(); cy.get(minEnactDeadline).click();
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait_for_proposal_submitted(); cy.wait_for_proposal_submitted();
cy.navigate_to('proposals');
cy.get(openProposals).within(() => {
cy.get(proposalType)
.contains('Update asset')
.parentsUntil(proposalListItem)
.within(() => {
cy.get(proposalDetails).should('contain.text', assetId); // 3001-VOTE-029
cy.getByTestId('view-proposal-btn').click();
});
});
cy.get_proposal_information_from_table('Proposed enactment') // 3001-VOTE-044
.invoke('text')
.should('not.be.empty');
}); });
it('Able to submit update asset proposal using max deadline', function () { it('Able to submit update asset proposal using max deadline', function () {
@@ -37,8 +37,8 @@ context(
function () { function () {
cy.reload(); cy.reload();
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.connectVegaWallet();
cy.ethereum_wallet_connect(); cy.ethereum_wallet_connect();
cy.connectVegaWallet();
cy.vega_wallet_teardown(); cy.vega_wallet_teardown();
cy.navigate_to('validators'); cy.navigate_to('validators');
} }
@@ -57,7 +57,16 @@ context(
//0005-ETXN-006 //0005-ETXN-006
//0005-ETXN-003 //0005-ETXN-003
//0005-ETXN-005 //0005-ETXN-005
cy.staking_page_associate_tokens('2'); cy.staking_page_associate_tokens('2', { skipConfirmation: true });
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
// 0005-ETXN-002 // 0005-ETXN-002
cy.get(ethWalletAssociatedBalances, txTimeout) cy.get(ethWalletAssociatedBalances, txTimeout)
@@ -98,6 +107,15 @@ context(
cy.staking_page_disassociate_tokens('2'); cy.staking_page_disassociate_tokens('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.get(ethWalletAssociatedBalances, txTimeout).should('not.exist'); cy.get(ethWalletAssociatedBalances, txTimeout).should('not.exist');
cy.get(ethWalletTotalAssociatedBalance, txTimeout) cy.get(ethWalletTotalAssociatedBalance, txTimeout)
@@ -194,7 +212,19 @@ context(
// 1004-ASSO-024 // 1004-ASSO-024
// 1004-ASSO-023 // 1004-ASSO-023
cy.staking_page_associate_tokens('2', { type: 'contract' }); cy.staking_page_associate_tokens('2', {
type: 'contract',
skipConfirmation: true,
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.get(ethWalletAssociatedBalances, txTimeout) cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort) .contains(vegaWalletPublicKeyShort)
@@ -210,7 +240,19 @@ context(
}); });
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0); cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
cy.staking_page_disassociate_tokens('1', { type: 'contract' }); cy.staking_page_disassociate_tokens('1', {
type: 'contract',
skipConfirmation: true,
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '1.00');
cy.validate_wallet_currency('Total associated after pending', '1.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.get(ethWalletAssociatedBalances, txTimeout) cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort) .contains(vegaWalletPublicKeyShort)
@@ -286,6 +328,35 @@ context(
}); });
// 1004-ASSO-004 // 1004-ASSO-004
it('Pending association outside of app is shown', function () {
cy.vega_wallet_associate('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.validate_wallet_currency('Associated', '2.00');
});
it('Disassociation outside of app is shown', function () {
cy.staking_page_associate_tokens('2');
cy.validate_wallet_currency('Associated', '2.00');
cy.vega_wallet_disassociate('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.validate_wallet_currency('Associated', '0.00');
});
it('Able to associate tokens to different public key of connected vega wallet', function () { it('Able to associate tokens to different public key of connected vega wallet', function () {
cy.get(ethWalletAssociateButton).first().click(); cy.get(ethWalletAssociateButton).first().click();
cy.get(associateWalletRadioButton).click(); cy.get(associateWalletRadioButton).click();
@@ -310,6 +381,7 @@ context(
'vegaWalletPublicKey2Short' 'vegaWalletPublicKey2Short'
)} can now participate in governance and nominate a validator with your associated $VEGA.` )} can now participate in governance and nominate a validator with your associated $VEGA.`
); );
cy.staking_page_disassociate_all_tokens();
}); });
}); });
} }
@@ -20,7 +20,10 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
it('Able to connect public key via wallet', function () { it('Able to connect public key via wallet', function () {
verifyConnectedToPubKey(); verifyConnectedToPubKey();
cy.getByTestId('currency-title').should('contain.text', 'USDC (fake)'); cy.getByTestId('currency-title', Cypress.env('epochTimeout')).should(
'contain.text',
'USDC (fake)'
);
}); });
it('Able to connect public key using url', function () { it('Able to connect public key using url', function () {
@@ -321,6 +321,8 @@ context(
'200000', '200000',
vegaWalletPublicKey vegaWalletPublicKey
); );
cy.reload();
cy.wait_for_spinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); cy.ethereum_wallet_connect();
}); });
@@ -46,6 +46,6 @@ Cypress.Commands.add('verify_page_header', (text) => {
}); });
Cypress.Commands.add('wait_for_spinner', () => { Cypress.Commands.add('wait_for_spinner', () => {
cy.get(navigation.pageSpinner).should('exist'); cy.get(navigation.pageSpinner, Cypress.env('epochTimeout')).should('exist');
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist'); cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
}); });
+1
View File
@@ -6,6 +6,7 @@ import './governance.functions.js';
import './wallet-eth.functions.js'; import './wallet-eth.functions.js';
import './wallet-teardown.functions.js'; import './wallet-teardown.functions.js';
import './wallet-vega.functions.js'; import './wallet-vega.functions.js';
import './proposal.functions.js';
import registerCypressGrep from '@cypress/grep'; import registerCypressGrep from '@cypress/grep';
import { aliasGQLQuery } from '@vegaprotocol/cypress'; import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock'; import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
@@ -0,0 +1,103 @@
import { addSeconds, millisecondsToSeconds } from 'date-fns';
const walletName = Cypress.env('vegaWalletName');
const walletPubKey = Cypress.env('vegaWalletPublicKey');
const walletLocation = Cypress.env('vegaWalletLocation');
const walletPassphraseFile = './src/fixtures/wallet/passphrase';
Cypress.Commands.add('sendWalletTxUpdateNetworkProposal', () => {
const MIN_CLOSE_SEC = 8;
const MIN_ENACT_SEC = 5;
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
cy.exec(
`vegawallet transaction send --wallet ${walletName} --pubkey ${walletPubKey} -p ${walletPassphraseFile} --network DV '{
"proposalSubmission": {
"rationale": {
"title": "Add New proposal with short enactment",
"description": "E2E enactment test"
},
"terms": {
"updateNetworkParameter": {
"changes": {
"key": "governance.proposal.updateNetParam.minProposerBalance",
"value": "2"
}
},
"closingTimestamp": ${closingTimestamp},
"enactmentTimestamp": ${enactmentTimestamp}
}
}
}' --home ${walletLocation}`,
{ failOnNonZeroExit: false }
)
.its('stderr')
.should('contain', '');
});
Cypress.Commands.add('sendWalletTxUpdateAssetProposal', () => {
const MIN_CLOSE_SEC = 8;
const MIN_ENACT_SEC = 5;
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
cy.exec(
`vegawallet transaction send --wallet ${walletName} --pubkey ${walletPubKey} -p ${walletPassphraseFile} --network DV '{
"proposalSubmission": {
"rationale": {
"title": "Update Asset set to fail",
"description": "E2E fail test"
},
"terms": {
"updateAsset": {
"assetId": "ebcd94151ae1f0d39a4bde3b21a9c7ae81a80ea4352fb075a92e07608d9c953d",
"changes": {
"quantum": "1",
"erc20": {
"withdrawThreshold": "10",
"lifetimeLimit": "10"
}
}
},
"closingTimestamp": ${closingTimestamp},
"enactmentTimestamp": ${enactmentTimestamp}
}
}
}' --home ${walletLocation}`,
{ failOnNonZeroExit: false }
)
.its('stderr')
.should('contain', '');
});
Cypress.Commands.add('sendWalletTxFreeFormProposal', () => {
const MIN_CLOSE_SEC = 5;
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
cy.exec(
`vegawallet transaction send --wallet ${walletName} --pubkey ${walletPubKey} -p ${walletPassphraseFile} --network DV '{
"proposalSubmission": {
"rationale": {
"title": "Add New free form proposal with short enactment",
"description": "E2E enactment test"
},
"terms": {
"newFreeform": {},
"closingTimestamp": ${closingTimestamp}
}
}
}' --home ${walletLocation}`,
{ failOnNonZeroExit: false }
)
.its('stderr')
.should('contain', '');
});
@@ -58,6 +58,8 @@ Cypress.Commands.add('staking_validator_page_remove_stake', (stake) => {
Cypress.Commands.add('staking_page_associate_tokens', (amount, options) => { Cypress.Commands.add('staking_page_associate_tokens', (amount, options) => {
let approve = options && options.approve ? options.approve : false; let approve = options && options.approve ? options.approve : false;
let type = options && options.type ? options.type : 'wallet'; let type = options && options.type ? options.type : 'wallet';
let skipConfirmation =
options && options.skipConfirmation ? options.skipConfirmation : false;
cy.highlight(`Associating ${amount} tokens from ${type}`); cy.highlight(`Associating ${amount} tokens from ${type}`);
cy.get(ethWalletAssociateButton).first().click(); cy.get(ethWalletAssociateButton).first().click();
@@ -79,6 +81,8 @@ Cypress.Commands.add('staking_page_associate_tokens', (amount, options) => {
); );
} }
cy.get(tokenSubmitButton, txTimeout).should('be.enabled').click(); cy.get(tokenSubmitButton, txTimeout).should('be.enabled').click();
if (!skipConfirmation) {
cy.contains( cy.contains(
`Associating with Vega key. Waiting for ${Cypress.env( `Associating with Vega key. Waiting for ${Cypress.env(
'blockConfirmations' 'blockConfirmations'
@@ -89,6 +93,7 @@ Cypress.Commands.add('staking_page_associate_tokens', (amount, options) => {
'can now participate in governance and nominate a validator', 'can now participate in governance and nominate a validator',
txTimeout txTimeout
).should('be.visible'); ).should('be.visible');
}
}); });
Cypress.Commands.add('staking_page_disassociate_tokens', (amount, options) => { Cypress.Commands.add('staking_page_disassociate_tokens', (amount, options) => {
@@ -216,3 +221,19 @@ Cypress.Commands.add('close_staking_dialog', () => {
cy.get('a').should('have.text', 'Back to Staking').click(); cy.get('a').should('have.text', 'Back to Staking').click();
}); });
}); });
Cypress.Commands.add(
'validate_wallet_currency',
(currencyTitle, expectedAmount) => {
cy.get("[data-testid='currency-title']")
.contains(currencyTitle)
.parent()
.parent()
.within(() => {
cy.getByTestId('currency-value', txTimeout).should(
'have.text',
expectedAmount
);
});
}
);
@@ -8,7 +8,6 @@ import {
import { ethers, Wallet } from 'ethers'; import { ethers, Wallet } from 'ethers';
const vegaWalletContainer = '[data-testid="vega-wallet"]'; const vegaWalletContainer = '[data-testid="vega-wallet"]';
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic'); const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic');
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey'); const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress'); const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
@@ -43,6 +42,11 @@ before('Vega wallet teardown prep', function () {
}); });
}); });
beforeEach(function () {
cy.wrap(this.stakingBridgeContract).as('stakingBridgeContract');
cy.wrap(this.vestingContract).as('vestingContract');
});
Cypress.Commands.add('deposit_asset', function (assetEthAddress) { Cypress.Commands.add('deposit_asset', function (assetEthAddress) {
cy.get('@signer', { log: false }).then((signer) => { cy.get('@signer', { log: false }).then((signer) => {
// Approve asset // Approve asset
@@ -91,29 +95,18 @@ Cypress.Commands.add('faucet_asset', function (assetEthAddress) {
}); });
Cypress.Commands.add('vega_wallet_teardown', function () { Cypress.Commands.add('vega_wallet_teardown', function () {
cy.get(vegaWalletContainer).within(() => { cy.get('body').then(($body) => {
cy.get(vegaWalletAssociatedBalance) if ($body.find('[data-testid="eth-wallet-associated-balances"]').length) {
.first()
.invoke('text')
.then((balance) => {
if (balance != '0.00') {
cy.vega_wallet_teardown_vesting(this.vestingContract); cy.vega_wallet_teardown_vesting(this.vestingContract);
cy.vega_wallet_teardown_staking(this.stakingBridgeContract); cy.vega_wallet_teardown_staking(this.stakingBridgeContract);
} }
}); });
cy.get(vegaWalletContainer).within(() => {
cy.get('[data-testid="associated-amount"]', { timeout: 30000 }).should( cy.get('[data-testid="associated-amount"]', { timeout: 30000 }).should(
'contain.text', 'contain.text',
'0.00' '0.00'
); );
}); });
cy.get(vegaWalletContainer).within(() => {
cy.get(vegaWalletAssociatedBalance, { timeout: transactionTimeout }).should(
'contain',
'0.00',
{ timeout: transactionTimeout }
);
});
}); });
Cypress.Commands.add( Cypress.Commands.add(
@@ -176,6 +169,22 @@ Cypress.Commands.add('vega_wallet_teardown_vesting', (vestingContract) => {
}); });
}); });
Cypress.Commands.add('vega_wallet_associate', (amount) => {
amount = amount + '0'.repeat(18);
cy.highlight('Associating tokens');
cy.get('@stakingBridgeContract').then((stakingBridgeContract) => {
stakingBridgeContract.stake(amount, vegaWalletPubKey);
});
});
Cypress.Commands.add('vega_wallet_disassociate', (amount) => {
amount = amount + '0'.repeat(18);
cy.highlight('Disassociating tokens');
cy.get('@stakingBridgeContract').then((stakingBridgeContract) => {
stakingBridgeContract.remove_stake(amount, vegaWalletPubKey);
});
});
Cypress.Commands.add('wait_for_transaction', (tx) => { Cypress.Commands.add('wait_for_transaction', (tx) => {
cy.wrap(tx.wait(1).catch(cy.log), { timeout: transactionTimeout }); cy.wrap(tx.wait(1).catch(cy.log), { timeout: transactionTimeout });
}); });
+1 -1
View File
@@ -1,7 +1,7 @@
# App configuration variables # App configuration variables
NX_VEGA_ENV=TESTNET NX_VEGA_ENV=TESTNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_URL=https://api.n10.testnet.vega.xyz/graphql NX_VEGA_URL=https://api.n08.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}' NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+6 -1
View File
@@ -12,5 +12,10 @@ export default {
moduleNameMapper: { moduleNameMapper: {
'^d3-(.*)$': `d3-$1/dist/d3-$1`, '^d3-(.*)$': `d3-$1/dist/d3-$1`,
}, },
collectCoverageFrom: ['**/*.{ts,tsx}', '!**/node_modules/**'], collectCoverageFrom: [
'**/*.{ts,tsx}',
'!**/node_modules/**',
'!**/__generated__/**',
'!**/__generated___/**',
],
}; };
+3 -2
View File
@@ -8,6 +8,7 @@ import { AppLoader } from './app-loader';
import { NetworkInfo } from '@vegaprotocol/network-info'; import { NetworkInfo } from '@vegaprotocol/network-info';
import { BalanceManager } from './components/balance-manager'; import { BalanceManager } from './components/balance-manager';
import { EthWallet } from './components/eth-wallet'; import { EthWallet } from './components/eth-wallet';
import { AppLayout } from './components/page-templates/app-layout';
import { TemplateSidebar } from './components/page-templates/template-sidebar'; import { TemplateSidebar } from './components/page-templates/template-sidebar';
import { TransactionModal } from './components/transactions-modal'; import { TransactionModal } from './components/transactions-modal';
import { VegaWallet } from './components/vega-wallet'; import { VegaWallet } from './components/vega-wallet';
@@ -88,14 +89,14 @@ const Web3Container = ({
<AppLoader> <AppLoader>
<BalanceManager> <BalanceManager>
<> <>
<div className="app w-full max-w-[1500px] mx-auto grid grid-rows-[min-content_min-content_1fr_min-content] min-h-full border-neutral-700 lg:border-l lg:border-r lg:text-body-large"> <AppLayout>
<TemplateSidebar sidebar={sideBar}> <TemplateSidebar sidebar={sideBar}>
<AppRouter /> <AppRouter />
</TemplateSidebar> </TemplateSidebar>
<footer className="p-4 border-t border-neutral-700"> <footer className="p-4 border-t border-neutral-700">
<NetworkInfo /> <NetworkInfo />
</footer> </footer>
</div> </AppLayout>
<VegaWalletDialogs /> <VegaWalletDialogs />
<TransactionModal /> <TransactionModal />
<WithdrawalDialog /> <WithdrawalDialog />
@@ -2,20 +2,24 @@ import * as Sentry from '@sentry/react';
import { toBigNum } from '@vegaprotocol/react-helpers'; import { toBigNum } from '@vegaprotocol/react-helpers';
import { useEthereumConfig } from '@vegaprotocol/web3'; import { useEthereumConfig } from '@vegaprotocol/web3';
import { useWeb3React } from '@web3-react/core'; import { useWeb3React } from '@web3-react/core';
import React from 'react'; import { useEffect } from 'react';
import { useAppState } from '../../contexts/app-state/app-state-context'; import { useAppState } from '../../contexts/app-state/app-state-context';
import { useContracts } from '../../contexts/contracts/contracts-context'; import { useContracts } from '../../contexts/contracts/contracts-context';
import { useGetAssociationBreakdown } from '../../hooks/use-get-association-breakdown'; import { useGetAssociationBreakdown } from '../../hooks/use-get-association-breakdown';
import { useGetUserTrancheBalances } from '../../hooks/use-get-user-tranche-balances'; import { useGetUserTrancheBalances } from '../../hooks/use-get-user-tranche-balances';
import { useBalances } from '../../lib/balances/balances-store'; import { useBalances } from '../../lib/balances/balances-store';
import type { ReactElement } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useListenForStakingEvents as useListenForAssociationEvents } from '../../hooks/use-listen-for-staking-events';
interface BalanceManagerProps { interface BalanceManagerProps {
children: React.ReactElement; children: ReactElement;
} }
export const BalanceManager = ({ children }: BalanceManagerProps) => { export const BalanceManager = ({ children }: BalanceManagerProps) => {
const contracts = useContracts(); const contracts = useContracts();
const { pubKey } = useVegaWallet();
const { account } = useWeb3React(); const { account } = useWeb3React();
const { const {
appState: { decimals }, appState: { decimals },
@@ -23,6 +27,20 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
const { updateBalances: updateStoreBalances } = useBalances(); const { updateBalances: updateStoreBalances } = useBalances();
const { config } = useEthereumConfig(); const { config } = useEthereumConfig();
const numberOfConfirmations = config?.confirmations || 0;
useListenForAssociationEvents(
contracts?.staking.contract,
pubKey,
numberOfConfirmations
);
useListenForAssociationEvents(
contracts?.vesting.contract,
pubKey,
numberOfConfirmations
);
const getUserTrancheBalances = useGetUserTrancheBalances( const getUserTrancheBalances = useGetUserTrancheBalances(
account || '', account || '',
contracts?.vesting contracts?.vesting
@@ -34,7 +52,7 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
); );
// update balances on connect to Ethereum // update balances on connect to Ethereum
React.useEffect(() => { useEffect(() => {
const updateBalances = async () => { const updateBalances = async () => {
if (!account || !config) return; if (!account || !config) return;
try { try {
@@ -75,13 +93,13 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
]); ]);
// This use effect hook is very expensive and is kept separate to prevent expensive reloading of data. // This use effect hook is very expensive and is kept separate to prevent expensive reloading of data.
React.useEffect(() => { useEffect(() => {
if (account) { if (account) {
getUserTrancheBalances(); getUserTrancheBalances();
} }
}, [account, getUserTrancheBalances]); }, [account, getUserTrancheBalances]);
React.useEffect(() => { useEffect(() => {
if (account) { if (account) {
getAssociationBreakdown(); getAssociationBreakdown();
} }
@@ -72,8 +72,8 @@ export const LockedProgress = ({
unlocked, unlocked,
leftLabel, leftLabel,
rightLabel, rightLabel,
leftColor = Colors.vega.pink, leftColor = Colors.vega.pink.DEFAULT,
rightColor = Colors.vega.green, rightColor = Colors.vega.green.DEFAULT,
decimals = 2, decimals = 2,
}: LockedProgressProps) => { }: LockedProgressProps) => {
const lockedPercentage = React.useMemo(() => { const lockedPercentage = React.useMemo(() => {
@@ -18,7 +18,7 @@ export const NavDropDown = ({ navbarTheme }: { navbarTheme: NavbarTheme }) => {
<AppNavLink <AppNavLink
name={ name={
<NavDropdownMenuTrigger <NavDropdownMenuTrigger
className="w-auto text-capMenu" className="w-auto flex items-center"
data-testid="state-trigger" data-testid="state-trigger"
onClick={() => setOpen(!isOpen)} onClick={() => setOpen(!isOpen)}
> >
@@ -38,6 +38,7 @@ export const NavDropDown = ({ navbarTheme }: { navbarTheme: NavbarTheme }) => {
name={t(r.name)} name={t(r.name)}
path={r.path} path={r.path}
navbarTheme={'inherit'} navbarTheme={'inherit'}
subNav={true}
end={true} end={true}
fullWidth={true} fullWidth={true}
/> />
+10 -5
View File
@@ -13,6 +13,7 @@ interface AppNavLinkProps {
target?: HTMLAttributeAnchorTarget; target?: HTMLAttributeAnchorTarget;
end?: boolean; end?: boolean;
fullWidth?: boolean; fullWidth?: boolean;
subNav?: boolean;
} }
export const AppNavLink = ({ export const AppNavLink = ({
@@ -23,28 +24,32 @@ export const AppNavLink = ({
testId, testId,
end = false, end = false,
fullWidth = false, fullWidth = false,
subNav = false,
}: AppNavLinkProps) => { }: AppNavLinkProps) => {
const borderClasses = classNames('absolute h-1 w-full bottom-[-1px] left-0', { const borderClasses = classNames(
'absolute h-0.5 w-full bottom-[-1px] left-0',
{
'bg-black dark:bg-vega-yellow': navbarTheme !== 'yellow', 'bg-black dark:bg-vega-yellow': navbarTheme !== 'yellow',
'bg-black': navbarTheme === 'yellow', 'bg-black': navbarTheme === 'yellow',
}); }
);
return ( return (
<NavLink <NavLink
key={path} key={path}
data-testid={testId} data-testid={testId}
to={{ pathname: path }} to={{ pathname: path }}
className={getNavLinkClassNames(navbarTheme, fullWidth)} className={getNavLinkClassNames(navbarTheme, fullWidth, subNav)}
target={target} target={target}
end={end} end={end}
> >
{({ isActive }) => { {({ isActive }) => {
return ( return (
<> <div className={subNav ? 'inline-block relative pb-1' : undefined}>
{name} {name}
{isActive && ( {isActive && (
<span data-testid="link-active" className={borderClasses} /> <span data-testid="link-active" className={borderClasses} />
)} )}
</> </div>
); );
}} }}
</NavLink> </NavLink>
+1 -2
View File
@@ -22,9 +22,8 @@ const renderComponent = (initialEntries?: string[]) => {
}; };
describe('nav', () => { describe('nav', () => {
it('Renders title and logo with link to home', () => { it('Renders logo with link to home', () => {
renderComponent(); renderComponent();
expect(screen.getByText('Governance')).toBeInTheDocument();
expect(screen.getByTestId('logo-link')).toHaveProperty( expect(screen.getByTestId('logo-link')).toHaveProperty(
'href', 'href',
'http://localhost/' 'http://localhost/'
+10 -4
View File
@@ -3,7 +3,8 @@ import { NetworkSwitcher } from '@vegaprotocol/environment';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { TOP_LEVEL_ROUTES } from '../../routes/routes'; import { TOP_LEVEL_ROUTES } from '../../routes/routes';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import vegaWhite from '../../images/vega_white.png'; import logoWhiteText from '../../images/logo-white-text.png';
import logoBlackText from '../../images/logo-black-text.png';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import { NavDrawer } from './nav-draw'; import { NavDrawer } from './nav-draw';
import { Nav as ToolkitNav } from '@vegaprotocol/ui-toolkit'; import { Nav as ToolkitNav } from '@vegaprotocol/ui-toolkit';
@@ -46,14 +47,19 @@ export const Nav = ({ navbarTheme = 'inherit' }: NavbarProps) => {
navbarTheme={navbarTheme} navbarTheme={navbarTheme}
icon={ icon={
<Link to="/" data-testid="logo-link"> <Link to="/" data-testid="logo-link">
<img alt="Vega" src={vegaWhite} height={30} width={30} /> <img
alt="Vega"
src={navbarTheme === 'yellow' ? logoBlackText : logoWhiteText}
height={30}
width={250}
/>
</Link> </Link>
} }
title={t('Governance')} title={undefined}
titleContent={<NetworkSwitcher />} titleContent={<NetworkSwitcher />}
> >
{isDesktop ? ( {isDesktop ? (
<nav className="flex items-center flex-1 px-2"> <nav className="flex items-center flex-1 px-4">
{TOP_LEVEL_ROUTES.map((r) => ( {TOP_LEVEL_ROUTES.map((r) => (
<AppNavLink <AppNavLink
key={r.path} key={r.path}
@@ -0,0 +1,21 @@
import classNames from 'classnames';
import { useVegaWallet } from '@vegaprotocol/wallet';
import type { ReactNode } from 'react';
interface AppLayoutProps {
children: ReactNode;
}
export const AppLayout = ({ children }: AppLayoutProps) => {
const { isReadOnly } = useVegaWallet();
const AppLayoutClasses = classNames(
'app w-full max-w-[1500px] mx-auto grid min-h-full',
'border-neutral-700 lg:border-l lg:border-r',
'lg:text-body-large',
{
'grid-rows-[repeat(2,min-content)_1fr_min-content]': !isReadOnly,
'grid-rows-[repeat(3,min-content)_1fr_min-content]': isReadOnly,
}
);
return <div className={AppLayoutClasses}>{children}</div>;
};
@@ -1,5 +1,9 @@
import { Networks, useEnvironment } from '@vegaprotocol/environment'; import { Networks, useEnvironment } from '@vegaprotocol/environment';
import { ViewingAsBanner } from '@vegaprotocol/ui-toolkit'; import {
ViewingAsBanner,
AnnouncementBanner,
ExternalLink,
} from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import React from 'react'; import React from 'react';
@@ -15,12 +19,18 @@ export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) {
const { isReadOnly, pubKey, disconnect } = useVegaWallet(); const { isReadOnly, pubKey, disconnect } = useVegaWallet();
return ( return (
<> <>
<AnnouncementBanner>
<div className="font-alpha calt uppercase text-center text-lg text-white">
<span className="pr-4">The Mainnet sims are live!</span>
<ExternalLink href="https://fairground.wtf/">
Come help stress test the network
</ExternalLink>
</div>
</AnnouncementBanner>
<Nav navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'} /> <Nav navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'} />
{isReadOnly ? ( {isReadOnly ? (
<ViewingAsBanner pubKey={pubKey} disconnect={disconnect} /> <ViewingAsBanner pubKey={pubKey} disconnect={disconnect} />
) : ( ) : null}
<div />
)}
<div className="w-full border-b border-neutral-700 lg:grid lg:grid-rows-[1fr] lg:grid-cols-[1fr_450px]"> <div className="w-full border-b border-neutral-700 lg:grid lg:grid-rows-[1fr] lg:grid-cols-[1fr_450px]">
<main className="col-start-1 p-4">{children}</main> <main className="col-start-1 p-4">{children}</main>
<aside className="col-start-2 row-start-1 row-span-2 hidden lg:block p-4 bg-banner bg-contain border-l border-neutral-700"> <aside className="col-start-2 row-start-1 row-span-2 hidden lg:block p-4 bg-banner bg-contain border-l border-neutral-700">
@@ -25,6 +25,8 @@ import { usePollForDelegations } from './hooks';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet'; import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit'; import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit';
import { toBigNum } from '@vegaprotocol/react-helpers'; import { toBigNum } from '@vegaprotocol/react-helpers';
import { usePendingBalancesStore } from '../../hooks/use-pending-balances-manager';
import { StakingEventType } from '../../hooks/use-get-association-breakdown';
export const VegaWallet = () => { export const VegaWallet = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -119,6 +121,10 @@ interface VegaWalletConnectedProps {
} }
const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => { const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
const pendingBalances = usePendingBalancesStore(
(state) => state.pendingBalances
);
const { t } = useTranslation(); const { t } = useTranslation();
const { const {
appDispatch, appDispatch,
@@ -126,6 +132,27 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
} = useAppState(); } = useAppState();
const { delegations, currentStakeAvailable, delegatedNodes, accounts } = const { delegations, currentStakeAvailable, delegatedNodes, accounts } =
usePollForDelegations(); usePollForDelegations();
const amountRemoved = BigNumber.sum.apply(null, [
new BigNumber(0),
...pendingBalances
.filter(({ event }) => event === StakingEventType.Stake_Removed)
.map(({ args }) => toBigNum(args?.[1].toString(), decimals)),
]);
const amountAdded = BigNumber.sum.apply(null, [
new BigNumber(0),
...pendingBalances
.filter(({ event }) => event === StakingEventType.Stake_Deposited)
.map(({ args }) => toBigNum(args?.[1].toString(), decimals)),
]);
const totalPending = React.useMemo(
() => amountRemoved.plus(amountAdded),
[amountAdded, amountRemoved]
);
const pendingStakeAmount = React.useMemo(
() => currentStakeAvailable.plus(amountAdded).minus(amountRemoved),
[amountAdded, amountRemoved, currentStakeAvailable]
);
const unstaked = React.useMemo(() => { const unstaked = React.useMemo(() => {
const totalDelegated = delegations.reduce<BigNumber>( const totalDelegated = delegations.reduce<BigNumber>(
@@ -161,6 +188,26 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
symbol="VEGA" symbol="VEGA"
balance={currentStakeAvailable} balance={currentStakeAvailable}
/> />
{totalPending.eq(0) ? null : (
<>
<WalletCardAsset
image={vegaWhite}
decimals={decimals}
name="VEGA"
subheading={t('Pending association')}
symbol="VEGA"
balance={totalPending}
/>
<WalletCardAsset
image={vegaWhite}
decimals={decimals}
name="VEGA"
subheading={t('Total associated after pending')}
symbol="VEGA"
balance={pendingStakeAmount}
/>
</>
)}
<div data-testid="vega-wallet-balance-unstaked"> <div data-testid="vega-wallet-balance-unstaked">
<WalletCardRow label={t('unstaked')} value={unstaked} /> <WalletCardRow label={t('unstaked')} value={unstaked} />
</div> </div>
+7 -4
View File
@@ -30,9 +30,12 @@ export function useAnimateValue(
) { ) {
elRef.current?.animate( elRef.current?.animate(
[ [
{ backgroundColor: customColors.vega.pink, color: colors.white },
{ {
backgroundColor: customColors.vega.pink, backgroundColor: customColors.vega.pink.DEFAULT,
color: colors.white,
},
{
backgroundColor: customColors.vega.pink.DEFAULT,
color: colors.white, color: colors.white,
offset: 0.8, offset: 0.8,
}, },
@@ -53,11 +56,11 @@ export function useAnimateValue(
elRef.current?.animate( elRef.current?.animate(
[ [
{ {
backgroundColor: customColors.vega.green, backgroundColor: customColors.vega.green.DEFAULT,
color: colors.white, color: colors.white,
}, },
{ {
backgroundColor: customColors.vega.green, backgroundColor: customColors.vega.green.DEFAULT,
color: colors.white, color: colors.white,
offset: 0.8, offset: 0.8,
}, },
@@ -11,6 +11,11 @@ import { useAppState } from '../contexts/app-state/app-state-context';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { useBalances } from '../lib/balances/balances-store'; import { useBalances } from '../lib/balances/balances-store';
export enum StakingEventType {
Stake_Removed = 'Stake_Removed',
Stake_Deposited = 'Stake_Deposited',
}
export function useGetAssociationBreakdown( export function useGetAssociationBreakdown(
ethAddress: string, ethAddress: string,
staking: StakingBridge, staking: StakingBridge,
@@ -63,8 +68,8 @@ function combineStakeEventsByVegaKey(
const res = events.reduce((obj, e) => { const res = events.reduce((obj, e) => {
const vegaKey = e.args?.vega_public_key; const vegaKey = e.args?.vega_public_key;
const amount = parseEventAmount(e, decimals); const amount = parseEventAmount(e, decimals);
const isDeposit = e.event === 'Stake_Deposited'; const isDeposit = e.event === StakingEventType.Stake_Deposited;
const isRemove = e.event === 'Stake_Removed'; const isRemove = e.event === StakingEventType.Stake_Removed;
if (!isDeposit && !isRemove) return obj; if (!isDeposit && !isRemove) return obj;
@@ -0,0 +1,102 @@
import { useListenForPendingEthEvents } from './use-listen-for-pending-eth-events';
import { renderHook, cleanup, waitFor } from '@testing-library/react';
import type { Contract, EventFilter, Event } from 'ethers';
let contract: Contract;
let filter: EventFilter;
let addPendingTxs: (event: Event[]) => void;
let removePendingTx: (event: Event) => void;
let resetPendingTxs: () => void;
beforeEach(() => {
contract = {
on: jest.fn(),
off: jest.fn(),
queryFilter: jest.fn().mockResolvedValue([]),
} as unknown as Contract;
filter = {} as EventFilter;
addPendingTxs = jest.fn();
removePendingTx = jest.fn();
resetPendingTxs = jest.fn();
});
jest.mock('@web3-react/core', () => ({
useWeb3React: () => ({
provider: {
getBlockNumber: jest.fn().mockResolvedValue(1),
},
}),
}));
describe('useListenForPendingEthEvents', () => {
it('listens for events on contract', async () => {
renderHook(() =>
useListenForPendingEthEvents(
1,
contract,
filter,
addPendingTxs,
removePendingTx,
resetPendingTxs
)
);
expect(contract.on).toHaveBeenCalledWith(filter, expect.any(Function));
cleanup();
expect(contract.off).toHaveBeenCalledWith(filter, expect.any(Function));
});
it('waits for correct number of confirmations before removing tx from pending txs', async () => {
renderHook(() => {
useListenForPendingEthEvents(
2,
contract,
filter,
addPendingTxs,
removePendingTx,
resetPendingTxs
);
});
const listener = (contract.on as jest.Mock).mock.calls[0][1];
const event = {
getTransaction: jest.fn().mockResolvedValue({
wait: jest.fn().mockResolvedValue({}),
}),
} as unknown as Event;
listener(null, null, null, event);
expect(addPendingTxs).toHaveBeenCalledWith([event]);
expect(removePendingTx).not.toHaveBeenCalled();
await waitFor(() => {
expect(removePendingTx).toHaveBeenCalledWith(event);
});
});
it('gets existing transactions', async () => {
const event = {
getTransaction: jest.fn().mockResolvedValue({
wait: jest.fn().mockResolvedValue(null),
}),
} as unknown as Event;
contract.queryFilter = jest.fn().mockResolvedValue([event]);
renderHook(() => {
useListenForPendingEthEvents(
2,
contract,
filter,
addPendingTxs,
removePendingTx,
resetPendingTxs
);
});
await waitFor(() => {
expect(contract.queryFilter).toHaveBeenCalledWith(filter, -1);
expect(addPendingTxs).toHaveBeenCalledWith([event]);
});
});
});
@@ -0,0 +1,103 @@
import { useWeb3React } from '@web3-react/core';
import { useCallback, useEffect } from 'react';
import * as Sentry from '@sentry/react';
import type { Contract, Event, EventFilter } from 'ethers';
export const useListenForPendingEthEvents = (
numberOfConfirmations: number,
contract: Contract | undefined,
filter: EventFilter | null,
addPendingTxs: (event: Event[]) => void,
removePendingTx: (event: Event) => void,
resetPendingTxs: () => void
) => {
const { provider } = useWeb3React();
/**
* Add listener for the ethereum events on the contract passed in for the filter passed in.
* Push the event into the store and wait for the correct number of confirmations before removing it.
*/
useEffect(() => {
if (!contract || !filter) {
return;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const listener = async (...args: any[]) => {
try {
const event = args[3] as Event;
addPendingTxs([event]);
const tx = await event.getTransaction();
await tx.wait(numberOfConfirmations);
removePendingTx(event);
} catch (e) {
Sentry.captureException(`Error listening for pending eth events ${e}`);
}
};
contract.on(filter, listener);
return () => {
contract.off(filter, listener);
};
}, [addPendingTxs, contract, filter, numberOfConfirmations, removePendingTx]);
/**
* Get all transactions that exist on the blockchain but have yet to reach the number of confirmations
*/
const getExistingTransactions = useCallback(async () => {
const blockNumber = (await provider?.getBlockNumber()) || 0;
if (!filter || !contract) {
return [];
}
try {
return await contract.queryFilter(
filter,
blockNumber - numberOfConfirmations
);
} catch (e) {
Sentry.captureException(`Error getting existing transactions ${e}`);
return [];
}
}, [contract, filter, numberOfConfirmations, provider]);
const waitForExistingTransactions = useCallback(
(events: Event[], numberOfConfirmations: number) => {
events.map(async (event) => {
try {
const tx = await event.getTransaction();
await tx.wait(Math.max(numberOfConfirmations, 0));
removePendingTx(event);
} catch (e) {
Sentry.captureException(
`Error waiting for existing transactions ${e}`
);
}
});
},
[removePendingTx]
);
useEffect(() => {
let cancelled = false;
resetPendingTxs();
getExistingTransactions().then((events) => {
if (!cancelled) {
addPendingTxs([...events]);
waitForExistingTransactions([...events], numberOfConfirmations);
}
});
return () => {
cancelled = true;
};
}, [
addPendingTxs,
getExistingTransactions,
numberOfConfirmations,
resetPendingTxs,
waitForExistingTransactions,
]);
};
@@ -0,0 +1,56 @@
import { useMemo } from 'react';
import { usePendingBalancesStore } from './use-pending-balances-manager';
import type { Contract } from 'ethers';
import { useListenForPendingEthEvents } from './use-listen-for-pending-eth-events';
import { prepend0x } from '@vegaprotocol/smart-contracts';
export const useListenForStakingEvents = (
contract: Contract | undefined,
vegaPublicKey: string | null,
numberOfConfirmations: number
) => {
const { addPendingTxs, removePendingTx, resetPendingTxs } =
usePendingBalancesStore((state) => ({
addPendingTxs: state.addPendingTxs,
removePendingTx: state.removePendingTx,
resetPendingTxs: state.resetPendingTxs,
}));
const addFilter = useMemo(
() =>
vegaPublicKey && contract
? contract.filters.Stake_Deposited(null, null, prepend0x(vegaPublicKey))
: null,
[contract, vegaPublicKey]
);
const removeFilter = useMemo(
() =>
vegaPublicKey && contract
? contract.filters.Stake_Removed(null, null, prepend0x(vegaPublicKey))
: null,
[contract, vegaPublicKey]
);
/**
* Listen for all add stake events
*/
useListenForPendingEthEvents(
numberOfConfirmations,
contract,
addFilter,
addPendingTxs,
removePendingTx,
resetPendingTxs
);
/**
* Listen for all remove stake events
*/
useListenForPendingEthEvents(
numberOfConfirmations,
contract,
removeFilter,
addPendingTxs,
removePendingTx,
resetPendingTxs
);
};
@@ -0,0 +1,76 @@
import { act } from '@testing-library/react-hooks';
import { usePendingBalancesStore } from './use-pending-balances-manager';
import type { Event } from 'ethers';
afterEach(() => {
usePendingBalancesStore.setState((state) => ({
...state,
pendingBalances: [],
}));
});
const event1 = { transactionHash: 'tx1' } as Event;
const event2 = { transactionHash: 'tx2' } as Event;
describe('usePendingBalancesStore', () => {
it('should add new events to the pendingBalances state and remove duplicates', () => {
const { addPendingTxs } = usePendingBalancesStore.getState();
const duplicateEvent = { transactionHash: 'tx1' } as Event;
act(() => {
addPendingTxs([event1, duplicateEvent]);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
event1,
]);
act(() => {
addPendingTxs([event2]);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
event1,
event2,
]);
});
it('should remove a specific event from the pendingBalances state', () => {
const { addPendingTxs, removePendingTx } =
usePendingBalancesStore.getState();
const eventToRemove = { transactionHash: 'tx1' } as Event;
act(() => {
addPendingTxs([eventToRemove, event2]);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
eventToRemove,
event2,
]);
act(() => {
removePendingTx(eventToRemove);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
event2,
]);
});
it('should reset the pendingBalances state', () => {
const { addPendingTxs, resetPendingTxs } =
usePendingBalancesStore.getState();
act(() => {
addPendingTxs([event1, event2]);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
event1,
event2,
]);
act(() => {
resetPendingTxs();
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([]);
});
});
@@ -0,0 +1,35 @@
import type { Event } from 'ethers';
import uniqBy from 'lodash/uniqBy';
import create from 'zustand';
export type PendingTxsStore = {
pendingBalances: Event[];
addPendingTxs: (event: Event[]) => void;
removePendingTx: (event: Event) => void;
resetPendingTxs: () => void;
};
export const usePendingBalancesStore = create<PendingTxsStore>((set, get) => ({
pendingBalances: [],
addPendingTxs: (event: Event[]) => {
set({
pendingBalances: uniqBy(
[...get().pendingBalances, ...event],
'transactionHash'
),
});
},
removePendingTx: (event: Event) => {
set({
pendingBalances: [
...get().pendingBalances.filter(
({ transactionHash }) => transactionHash !== event.transactionHash
),
],
});
},
resetPendingTxs: () => {
set({ pendingBalances: [] });
},
}));
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

@@ -15,7 +15,7 @@ export const ProposalFormTransactionDialog = ({
finalizedProposal, finalizedProposal,
TransactionDialog, TransactionDialog,
}: ProposalFormTransactionDialogProps) => { }: ProposalFormTransactionDialogProps) => {
// Render a custom complete UI if the proposal was rejected other wise // Render a custom complete UI if the proposal was rejected otherwise
// pass undefined so that the default vega transaction dialog UI gets used // pass undefined so that the default vega transaction dialog UI gets used
const completeContent = finalizedProposal?.rejectionReason ? ( const completeContent = finalizedProposal?.rejectionReason ? (
<p>{finalizedProposal.rejectionReason}</p> <p>{finalizedProposal.rejectionReason}</p>
@@ -102,7 +102,7 @@ export const VoteDetails = ({
</table> </table>
</section> </section>
)} )}
<section> <section data-testid="votes-table">
<SubHeading title={t('tokenVotes')} /> <SubHeading title={t('tokenVotes')} />
<p> <p>
<span> <span>
@@ -90,23 +90,16 @@ describe('Raw proposal form', () => {
}, },
result: { result: {
data: { data: {
busEvents: [ proposals: {
{
__typename: 'BusEvent',
type: Schema.BusEventType.Proposal,
event: {
__typename: 'Proposal', __typename: 'Proposal',
id: '2fca514cebf9f465ae31ecb4c5721e3a6f5f260425ded887ca50ba15b81a5d50', id: '2fca514cebf9f465ae31ecb4c5721e3a6f5f260425ded887ca50ba15b81a5d50',
reference: 'proposal-reference', reference: 'proposal-reference',
state: Schema.ProposalState.STATE_OPEN, state: Schema.ProposalState.STATE_OPEN,
rejectionReason: rejectionReason:
Schema.ProposalRejectionReason Schema.ProposalRejectionReason.PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE,
.PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE,
errorDetails: 'error-details', errorDetails: 'error-details',
}, },
}, },
],
},
}, },
delay: 300, delay: 300,
}; };
@@ -177,7 +177,7 @@ interface TotalPenaltiesRendererProps {
performanceScore: string; performanceScore: string;
performancePenalty: string; performancePenalty: string;
overstakedAmount: string; overstakedAmount: string;
overstakedPenalty: string; overstakingPenalty: string;
totalPenalties: string; totalPenalties: string;
}; };
} }
@@ -192,20 +192,10 @@ export const TotalPenaltiesRenderer = ({
description={ description={
<> <>
<div> <div>
<span>
{t('performancePenalty')}: {data.performancePenalty} {t('performancePenalty')}: {data.performancePenalty}
</span>
<span className="pl-2">
({t('score')} {data.performanceScore})
</span>
</div> </div>
<div> <div>
<span> {t('overstakedPenalty')}: {data.overstakingPenalty}
{t('overstakedPenalty')}: {data.overstakedPenalty}
</span>
<span className="pl-2">
({t('overstaked')} {data.overstakedAmount})
</span>
</div> </div>
<div> <div>
{t('totalPenalties')}:{' '} {t('totalPenalties')}:{' '}
@@ -1,6 +1,6 @@
import { Dialog, Icon, Intent } from '@vegaprotocol/ui-toolkit'; import { Dialog, Icon, Intent } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import Routes from '../../routes'; import Routes from '../../routes';
import type { StakeAction } from './staking-form'; import type { StakeAction } from './staking-form';
import { Actions, RemoveType } from './staking-form'; import { Actions, RemoveType } from './staking-form';
@@ -23,6 +23,7 @@ export const StakeSuccess = ({
toggleDialog, toggleDialog,
}: StakeSuccessProps) => { }: StakeSuccessProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate();
const isAdd = action === Actions.Add; const isAdd = action === Actions.Add;
const title = isAdd const title = isAdd
? t('stakeAddSuccessTitle', { amount }) ? t('stakeAddSuccessTitle', { amount })
@@ -44,7 +45,15 @@ export const StakeSuccess = ({
<div> <div>
<p>{message}</p> <p>{message}</p>
<p> <p>
<Link className="underline" to={Routes.VALIDATORS}> <Link
className="underline"
to={Routes.VALIDATORS}
onClick={(event) => {
event.preventDefault();
toggleDialog();
setTimeout(() => navigate(Routes.VALIDATORS), 0);
}}
>
{t('backToStaking')} {t('backToStaking')}
</Link> </Link>
</p> </p>
@@ -29,7 +29,7 @@ export const TrancheProgress = ({
<span className="tranches__progress-title">{t('Locked')}</span> <span className="tranches__progress-title">{t('Locked')}</span>
<ProgressBar <ProgressBar
width={220} width={220}
color={Colors.vega.pink} color={Colors.vega.pink.DEFAULT}
percentage={lockedPercentage} percentage={lockedPercentage}
/> />
<span className="tranches__progress-numbers"> <span className="tranches__progress-numbers">
@@ -40,7 +40,7 @@ export const TrancheProgress = ({
<span className="tranches__progress-title">{t('Redeemed')}</span> <span className="tranches__progress-title">{t('Redeemed')}</span>
<ProgressBar <ProgressBar
width={220} width={220}
color={Colors.vega.green} color={Colors.vega.green.DEFAULT}
percentage={removedPercentage} percentage={removedPercentage}
/> />
<span className="tranches__progress-numbers"> <span className="tranches__progress-numbers">
@@ -34,10 +34,10 @@ export const VestingChart = () => {
<AreaChart data={data}> <AreaChart data={data}>
<defs> <defs>
{[ {[
['pink', Colors.vega.pink], ['pink', Colors.vega.pink.DEFAULT],
['green', Colors.vega.green], ['green', Colors.vega.green.DEFAULT],
['orange', Colors.warning], ['orange', Colors.warning],
['yellow', Colors.vega.yellow], ['yellow', Colors.vega.yellow.DEFAULT],
].map(([key, color]) => ( ].map(([key, color]) => (
<linearGradient key={key} id={key} x1="0" y1="0" x2="0" y2="1"> <linearGradient key={key} id={key} x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={color} stopOpacity={0.85} /> <stop offset="0%" stopColor={color} stopOpacity={0.85} />
@@ -97,7 +97,7 @@ export const VestingChart = () => {
dot={false} dot={false}
type="linear" type="linear"
dataKey="team" dataKey="team"
stroke={Colors.vega.pink} stroke={Colors.vega.pink.DEFAULT}
fill="url(#pink)" fill="url(#pink)"
yAxisId={0} yAxisId={0}
strokeWidth={2} strokeWidth={2}
@@ -109,7 +109,7 @@ export const VestingChart = () => {
dot={false} dot={false}
type="monotone" type="monotone"
dataKey="earlyInvestors" dataKey="earlyInvestors"
stroke={Colors.vega.green} stroke={Colors.vega.green.DEFAULT}
fill="url(#green)" fill="url(#green)"
yAxisId={0} yAxisId={0}
strokeWidth={2} strokeWidth={2}
@@ -121,7 +121,7 @@ export const VestingChart = () => {
dot={false} dot={false}
type="monotone" type="monotone"
dataKey="publicSale" dataKey="publicSale"
stroke={Colors.vega.yellow} stroke={Colors.vega.yellow.DEFAULT}
fill="url(#yellow)" fill="url(#yellow)"
yAxisId={0} yAxisId={0}
strokeWidth={2} strokeWidth={2}
+6
View File
@@ -13,3 +13,9 @@
@apply mb-2 text-neutral-400; @apply mb-2 text-neutral-400;
} }
} }
@layer components {
.border-default {
@apply border-vega-dark-200;
}
}
+222 -74
View File
@@ -21,15 +21,127 @@ const orderUpdatedAt = 'updatedAt';
const assetSelectField = 'select[name="asset"]'; const assetSelectField = 'select[name="asset"]';
const amountField = 'input[name="amount"]'; const amountField = 'input[name="amount"]';
const txTimeout = Cypress.env('txTimeout'); const txTimeout = Cypress.env('txTimeout');
const btcName = 'BTC (local)'; const sepoliaUrl = Cypress.env('ETHERSCAN_URL');
const btcName =
'BTC (local)5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c - tBTC';
const vegaName =
'Vegab4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b - VEGA';
const btcSymbol = 'tBTC'; const btcSymbol = 'tBTC';
const vegaSymbol = 'VEGA';
const usdcSymbol = 'fUSDC'; const usdcSymbol = 'fUSDC';
const toastContent = 'toast-content'; const toastContent = 'toast-content';
const ordersTab = 'Orders'; const ordersTab = 'Orders';
const depositsTab = 'Deposits'; const depositsTab = 'Deposits';
const toastCloseBtn = 'toast-close'; const toastCloseBtn = 'toast-close';
const price = '390';
const size = '0.0005';
const newPrice = '200';
const completeWithdrawalBtn = 'complete-withdrawal';
// Because the tests are run on a live network to optimize time, the tests are interdependent and must be run in the given order.
describe('capsule - without MultiSign', { tags: '@slow' }, () => {
before(() => {
cy.createMarket();
cy.get('@markets').then((markets) => {
cy.wrap(markets[0]).as('market');
});
});
beforeEach(() => {
cy.setVegaWallet();
});
it('can deposit', function () {
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
// 1001-DEPO-001
// 1001-DEPO-002
// 1001-DEPO-003
// 1001-DEPO-005
// 1001-DEPO-006
// 1001-DEPO-007
// 1001-DEPO-008
// 1001-DEPO-009
// 1001-DEPO-010
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
cy.getByTestId('deposit-approve-submit').click();
cy.getByTestId('dialog-title').should('contain.text', 'Approve complete');
cy.get('[data-testid="Return to deposit"]').click();
cy.get(amountField).clear().type('10');
cy.getByTestId('deposit-submit').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
`Transaction confirmedYour transaction has been confirmed.View on EtherscanDeposit 10.00 ${btcSymbol}`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId('Collateral').click();
cy.highlight('deposit verification');
cy.getByTestId('asset', txTimeout).should('contain.text', btcSymbol);
cy.getByTestId(depositsTab).click();
cy.get('.ag-cell-value', txTimeout).should('contain.text', btcSymbol);
cy.get('[col-id="status"]').should('not.have.text', 'Open', txTimeout);
cy.get('[col-id="txHash"]')
.should('have.length.above', 2)
.eq(1)
.parent()
.within(() => {
cy.get('[col-id="asset.symbol"]').should('have.text', btcSymbol);
cy.get('[col-id="amount"]').should('have.text', '10.00');
cy.get('[col-id="createdTimestamp"]').should('not.be.empty');
cy.get('[col-id="status"]').should('have.text', 'Finalized');
cy.get('[col-id="txHash"]')
.find('a')
.should('have.attr', 'href')
.and('contain', `${sepoliaUrl}/tx/0x`);
});
});
it('can not withdrawal because of no MultiSign', function () {
// 1002-WITH-022
// 1002-WITH-023
cy.getByTestId('Withdrawals').click();
cy.getByTestId('withdraw-dialog-button').click();
cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
cy.get(amountField).clear().type('1');
cy.getByTestId('submit-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
'Funds unlocked'
);
cy.getByTestId('tab-withdrawals').within(() => {
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get('[col-id="status"]').should('contain.text', 'Pending');
});
});
cy.highlight('withdrawals verification');
cy.getByTestId('toast-complete-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
'Error occurredprocessing response error'
);
cy.getByTestId(completeWithdrawalBtn).should(
'contain.text',
'Complete withdrawal'
);
});
});
// TODO: ensure this test runs only if capsule is running via workflow
describe('capsule', { tags: '@slow' }, () => { describe('capsule', { tags: '@slow' }, () => {
before(() => { before(() => {
cy.createMarket(); cy.createMarket();
@@ -50,8 +162,8 @@ describe('capsule', { tags: '@slow' }, () => {
marketId: market.id, marketId: market.id,
type: Schema.OrderType.TYPE_LIMIT, type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_BUY, side: Schema.Side.SIDE_BUY,
size: '0.0005', size: size,
price: '390', price: price,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC, timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
}; };
const rawPrice = removeDecimal(order.price, market.decimalPlaces); const rawPrice = removeDecimal(order.price, market.decimalPlaces);
@@ -64,7 +176,8 @@ describe('capsule', { tags: '@slow' }, () => {
cy.getByTestId(toastContent).should( cy.getByTestId(toastContent).should(
'contain.text', 'contain.text',
`ConfirmedYour transaction has been confirmed View in block explorerSubmit order - activeTEST.24h+0.0005 @ 390.00 ${usdcSymbol}` `ConfirmedYour transaction has been confirmed View in block explorerSubmit order - activeTEST.24h+${order.size} @ ${order.price}.00 ${usdcSymbol}`,
{ matchCase: false }
); );
cy.getByTestId(toastCloseBtn).click(); cy.getByTestId(toastCloseBtn).click();
// orderbook cells are keyed by price level // orderbook cells are keyed by price level
@@ -75,7 +188,7 @@ describe('capsule', { tags: '@slow' }, () => {
.should('contain.text', rawSize); .should('contain.text', rawSize);
cy.getByTestId(ordersTab).click(); cy.getByTestId(ordersTab).click();
cy.getByTestId('edit').should('contain.text', 'Edit'); cy.getByTestId('edit', txTimeout).should('contain.text', 'Edit');
cy.getByTestId('tab-orders').within(() => { cy.getByTestId('tab-orders').within(() => {
cy.get('.ag-center-cols-container') cy.get('.ag-center-cols-container')
.children() .children()
@@ -113,35 +226,43 @@ describe('capsule', { tags: '@slow' }, () => {
checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderCreatedAt); checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderCreatedAt);
}); });
}); });
//edit order });
it('can edit order', function () {
cy.getByTestId(ordersTab).click(); cy.getByTestId(ordersTab).click();
cy.getByTestId('edit').first().should('be.visible').click(); cy.getByTestId('edit').first().should('be.visible').click();
cy.getByTestId('dialog-title').should('contain.text', 'Edit order'); cy.getByTestId('dialog-title').should('contain.text', 'Edit order');
cy.get('#limitPrice').focus().clear().type('200'); cy.get('#limitPrice').focus().clear().type(newPrice);
cy.getByTestId('edit-order').find('[type="submit"]').click(); cy.getByTestId('edit-order').find('[type="submit"]').click();
cy.getByTestId(toastContent).should( cy.getByTestId(toastContent).should(
'contain.text', 'contain.text',
`ConfirmedYour transaction has been confirmed View in block explorerEdit order - activeTEST.24h+0.0005 @ 200.00 ${usdcSymbol}+0.0005 @ 200.00 ${usdcSymbol}` `ConfirmedYour 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(ordersTab).click(); cy.getByTestId(ordersTab).click();
cy.getByTestId(toastCloseBtn).click();
cy.get('.ag-center-cols-container') cy.get('.ag-center-cols-container')
.children() .children()
.first() .first()
.within(() => { .within(() => {
cy.get(`[col-id='${orderPrice}']`).then(($price) => { cy.get(`[col-id='${orderPrice}']`).then(($price) => {
expect(parseFloat($price.text())).to.equal(parseFloat('200')); expect(parseFloat($price.text())).to.equal(parseFloat(newPrice));
}); });
checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderUpdatedAt); checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderUpdatedAt);
}); });
//cancel order });
it('can cancel order', function () {
cy.getByTestId(ordersTab).click(); cy.getByTestId(ordersTab).click();
cy.getByTestId('cancel').first().click(); cy.getByTestId('cancel').first().click();
cy.getByTestId(toastContent).should( cy.getByTestId(toastContent).should(
'contain.text', 'contain.text',
`ConfirmedYour transaction has been confirmed View in block explorerCancel order - cancelledTEST.24h+0.0005 @ 200.00 ${usdcSymbol}` `ConfirmedYour transaction has been confirmed View in block explorerCancel order - cancelledTEST.24h+${size} @ ${newPrice}.00 ${usdcSymbol}`,
{ matchCase: false }
); );
cy.getByTestId(toastCloseBtn).click(); cy.getByTestId(toastCloseBtn).click({ multiple: true });
cy.getByTestId('tab-orders') cy.getByTestId('tab-orders')
.get('.ag-center-cols-container') .get('.ag-center-cols-container')
@@ -151,78 +272,29 @@ describe('capsule', { tags: '@slow' }, () => {
.should('contain.text', OrderStatusMapping.STATUS_CANCELLED); .should('contain.text', OrderStatusMapping.STATUS_CANCELLED);
}); });
it('can deposit and withdrawal', function () { it('can withdrawal', function () {
// 1001-DEPO-001 // 1002-WITH-0014
// 1001-DEPO-002
// 1001-DEPO-003
// 1001-DEPO-005
// 1001-DEPO-006
// 1001-DEPO-007
// 1001-DEPO-008
// 1001-DEPO-009
// 1002-WITH-001
// 1002-WITH-006 // 1002-WITH-006
// 1002-WITH-009 // 1002-WITH-009
// 002-WITH-011 // 1002-WITH-011
// 1002-WITH-024 // 1002-WITH-024
// 1002-WITH-012 // 1002-WITH-012
// 1002-WITH-013 // 1002-WITH-013
// 1002-WITH-014 // 1002-WITH-014
// 1002-WITH-015 // 1002-WITH-015
// 1002-WITH-016 // 1002-WITH-016
// 1002-WITH-017
// 1002-WITH-019 // 1002-WITH-019
// 1002-WITH-020
// 1002-WITH-021
cy.visit('/#/portfolio'); cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist'); cy.get('main[data-testid="/portfolio"]').should('exist');
cy.highlight('creating deposit');
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
cy.get(assetSelectField, txTimeout).select(btcName);
cy.getByTestId('deposit-approve-submit').click();
cy.getByTestId('dialog-title').should('contain.text', 'Approve complete');
cy.get('[data-testid="Return to deposit"]').click();
cy.get(amountField).clear().type('1');
cy.getByTestId('deposit-submit').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
`Transaction completedYour transaction has been completedView on EtherscanDeposit 1.00 ${btcSymbol}`
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId('Collateral').click();
cy.highlight('deposit verification');
cy.getByTestId('asset', txTimeout).should('contain.text', btcSymbol);
// need to reload page to see deposit history complete
cy.reload();
cy.getByTestId(depositsTab).click();
cy.get('.ag-cell-value', txTimeout).should('contain.text', btcSymbol);
cy.get('[col-id="status"]').should('not.have.text', 'Open', txTimeout);
cy.get('[col-id="txHash"]')
.should('have.length.above', 2)
.eq(1)
.parent()
.within(() => {
cy.get('[col-id="asset.symbol"]').should('have.text', btcSymbol);
cy.get('[col-id="amount"]').should('have.text', '1.00');
cy.get('[col-id="createdTimestamp"]').should('not.be.empty');
cy.get('[col-id="status"]').should('have.text', 'Finalized');
cy.get('[col-id="txHash"]')
.find('a')
.should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/tx');
});
cy.highlight('creating withdrawals');
cy.getByTestId('Withdrawals').click(); cy.getByTestId('Withdrawals').click();
cy.getByTestId('withdraw-dialog-button').click(); cy.getByTestId('withdraw-dialog-button').click();
connectEthereumWallet('Unknown'); connectEthereumWallet('Unknown');
cy.get(assetSelectField).select(btcName); cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
cy.get(amountField).clear().type('1'); cy.get(amountField).clear().type('1');
cy.getByTestId('submit-withdrawal').click(); cy.getByTestId('submit-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should( cy.getByTestId(toastContent, txTimeout).should(
@@ -241,12 +313,13 @@ describe('capsule', { tags: '@slow' }, () => {
cy.highlight('withdrawals verification'); cy.highlight('withdrawals verification');
cy.getByTestId('toast-complete-withdrawal').click(); cy.getByTestId('toast-complete-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should( cy.getByTestId(toastContent, txTimeout).should(
'contain.text', 'contain.text',
'Transaction completed' 'Transaction confirmed'
); );
cy.getByTestId('complete-withdrawal', txTimeout).should('not.exist'); cy.getByTestId(completeWithdrawalBtn).eq(0, txTimeout).should('not.exist');
cy.get('[col-id="txHash"]', txTimeout) cy.get('[col-id="txHash"]', txTimeout)
.should('have.length.above', 1) .should('have.length.above', 1)
@@ -258,17 +331,92 @@ describe('capsule', { tags: '@slow' }, () => {
cy.get('[col-id="details.receiverAddress"]') cy.get('[col-id="details.receiverAddress"]')
.find('a') .find('a')
.should('have.attr', 'href') .should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/address/'); .and('contain', `${sepoliaUrl}/address/`);
cy.get('[col-id="createdTimestamp"]').should('not.be.empty'); cy.get('[col-id="createdTimestamp"]').should('not.be.empty');
cy.get('[col-id="withdrawnTimestamp"]').should('not.be.empty'); cy.get('[col-id="withdrawnTimestamp"]').should('not.be.empty');
cy.get('[col-id="status"]').should('have.text', 'Completed'); cy.get('[col-id="status"]').should('have.text', 'Completed');
cy.get('[col-id="txHash"]') cy.get('[col-id="txHash"]')
.find('a') .find('a')
.should('have.attr', 'href') .should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/tx/0x'); .and('contain', `${sepoliaUrl}/tx/0x`);
}); });
// comment because of bug #2819
// cy.getByTestId('withdraw-dialog-button').click();
// cy.getByTestId('BALANCE_AVAILABLE_value').should('have.text', '0')
});
it('approved amount is less than deposit', function () {
// 1001-DEPO-006
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
cy.get(amountField).clear().type('20000000');
cy.getByTestId('deposit-approve-submit').should('be.visible');
});
it('withdraw - delay verification', function () {
// 1001-DEPO-007
// 1001-DEPO-024
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
cy.get(assetSelectField, txTimeout).select(vegaName, { force: true });
cy.getByTestId('deposit-approve-submit').click();
cy.getByTestId('dialog-title').should('contain.text', 'Approve complete');
cy.get('[data-testid="Return to deposit"]').click();
cy.get(amountField).clear().type('10000');
cy.getByTestId('deposit-submit').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
`Your transaction has been confirmed.`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId('Collateral').click();
cy.highlight('deposit verification');
cy.getByTestId('asset', txTimeout).should('contain.text', vegaSymbol);
cy.getByTestId(depositsTab).click();
cy.get('.ag-cell-value', txTimeout).should('contain.text', vegaSymbol);
cy.get('[col-id="status"]').should('not.have.text', 'Open', txTimeout);
cy.get('[col-id="txHash"]')
.should('have.length.above', 2)
.eq(1)
.parent()
.within(() => {
cy.get('[col-id="asset.symbol"]').should('have.text', vegaSymbol);
cy.get('[col-id="amount"]').should('have.text', '10,000.00');
cy.get('[col-id="createdTimestamp"]').should('not.be.empty');
cy.get('[col-id="status"]').should('have.text', 'Finalized');
cy.get('[col-id="txHash"]')
.find('a')
.should('have.attr', 'href')
.and('contain', `${sepoliaUrl}/tx/0x`);
});
cy.getByTestId('Withdrawals').click();
cy.getByTestId('withdraw-dialog-button').click();
cy.get(assetSelectField, txTimeout).select(vegaName, { force: true });
cy.get(amountField).clear().type('10000');
cy.getByTestId('DELAY_TIME_value').should('have.text', '5 days');
cy.getByTestId('submit-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
'Your funds have been unlocked'
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId(completeWithdrawalBtn).first().should('be.visible').click();
cy.getByTestId(toastContent, txTimeout).should('contain.text', 'Delayed');
}); });
}); });
function checkIfDataAndTimeOfCreationAndUpdateIsEqual(date: string) { function checkIfDataAndTimeOfCreationAndUpdateIsEqual(date: string) {
cy.get(`[col-id='${date}'] .ag-cell-wrapper`) cy.get(`[col-id='${date}'] .ag-cell-wrapper`)
.children('span') .children('span')
@@ -56,6 +56,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
}); });
it('insufficient funds', () => { it('insufficient funds', () => {
// 1001-DEPO-005
// Deposit amount is valid, but less than approved. This will always be the case because our // Deposit amount is valid, but less than approved. This will always be the case because our
// CI wallet wont have approved any assets // CI wallet wont have approved any assets
cy.get(amountField) cy.get(amountField)
@@ -4,6 +4,7 @@ const marketInfoBtn = 'Info';
const row = 'key-value-table-row'; const row = 'key-value-table-row';
const marketTitle = 'accordion-title'; const marketTitle = 'accordion-title';
const externalLink = 'external-link'; const externalLink = 'external-link';
const accordionContent = 'accordion-content';
describe('market info is displayed', { tags: '@smoke' }, () => { describe('market info is displayed', { tags: '@smoke' }, () => {
before(() => { before(() => {
@@ -179,7 +180,8 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
'termination.BTC.value' 'termination.BTC.value'
); );
cy.getByTestId(externalLink) cy.getByTestId(accordionContent)
.find(`[data-testid="${externalLink}"]`)
.should('have.attr', 'href') .should('have.attr', 'href')
.and('contain', '/oracles'); .and('contain', '/oracles');
}); });
@@ -187,12 +189,14 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
it('proposal displayed', () => { it('proposal displayed', () => {
cy.getByTestId(marketTitle).contains('Proposal').click(); cy.getByTestId(marketTitle).contains('Proposal').click();
cy.getByTestId(externalLink) cy.getByTestId(accordionContent)
.find(`[data-testid="${externalLink}"]`)
.first() .first()
.should('have.text', 'View governance proposal') .should('have.text', 'View governance proposal')
.and('have.attr', 'href') .and('have.attr', 'href')
.and('contain', '/proposals/market-0'); .and('contain', '/proposals/market-0');
cy.getByTestId(externalLink) cy.getByTestId(accordionContent)
.find(`[data-testid="${externalLink}"]`)
.eq(1) .eq(1)
.should('have.text', 'Propose a change to market') .should('have.text', 'Propose a change to market')
.and('have.attr', 'href') .and('have.attr', 'href')
+52 -1
View File
@@ -1,4 +1,7 @@
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { marketQuery } from '@vegaprotocol/mock';
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
describe('markets table', { tags: '@smoke' }, () => { describe('markets table', { tags: '@smoke' }, () => {
beforeEach(() => { beforeEach(() => {
@@ -101,7 +104,8 @@ describe('markets table', { tags: '@smoke' }, () => {
'have.length', 'have.length',
10 10
); );
cy.getByTestId('external-link') cy.getByTestId('tab-proposed-markets')
.find('[data-testid="external-link"]')
.should('have.length', 11) .should('have.length', 11)
.last() .last()
.should('have.text', 'Propose a new market') .should('have.text', 'Propose a new market')
@@ -111,6 +115,53 @@ describe('markets table', { tags: '@smoke' }, () => {
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market` `${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market`
); );
}); });
it('opening auction subsets should be properly displayed', () => {
cy.mockTradingPage(
Schema.MarketState.STATE_ACTIVE,
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION
);
cy.mockGQL((req) => {
const override = {
market: {
tradableInstrument: {
instrument: {
name: `opening auction MARKET`,
},
},
state: Schema.MarketState.STATE_ACTIVE,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
},
};
const market = marketQuery(override);
aliasGQLQuery(req, 'Market', market);
aliasGQLQuery(req, 'ProposalOfMarket', {
proposal: { terms: { enactmentDatetime: '2023-01-31 12:00:01' } },
});
});
cy.visit('/');
cy.visit('#/markets/market-0');
cy.getByTestId('item-value').contains('Opening auction').realHover();
cy.getByTestId('opening-auction-sub-status').should(
'contain.text',
'Opening auction: Not enough liquidity to open'
);
const now = new Date(Date.parse('2023-01-30 12:00:01')).getTime();
cy.clock(now, ['Date']); // Set "now" to BEFORE reservation
cy.visit('/');
cy.visit('#/markets/market-0');
cy.getByTestId('item-value').contains('Opening auction').realHover();
cy.getByTestId('opening-auction-sub-status').should(
'contain.text',
`Opening auction: Closing on ${getDateTimeFormat().format(
new Date('2023-01-31 12:00:01')
)}`
);
cy.clock().then((clock) => {
clock.restore();
});
});
}); });
function openMarketDropDown() { function openMarketDropDown() {
@@ -452,7 +452,7 @@ describe('limit order validations', { tags: '@smoke' }, () => {
//7002-SORD-018 //7002-SORD-018
cy.getByTestId(orderPriceField) cy.getByTestId(orderPriceField)
.siblings('label') .siblings('label')
.should('have.text', 'Price (tBTC)'); .should('have.text', 'Price (BTC)');
}); });
it('must see warning when placing an order with expiry date in past', () => { it('must see warning when placing an order with expiry date in past', () => {
@@ -454,8 +454,4 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
); );
}); });
}); });
it.skip('tbd for 7003-MORD', () => {
// NOT COVERED: must see the reference, offset and direction for each part pegged order - waiting for clarification
// NOT COVERED: must see the reference, offset and direction for each part liquidity order order - waiting for clarification
});
}); });
@@ -41,6 +41,7 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
cy.get(toAddressField).should('have.value', ethAddressValue); cy.get(toAddressField).should('have.value', ethAddressValue);
}); });
it('min amount', () => { it('min amount', () => {
// 1002-WITH-010
selectAsset(ASSET_SEPOLIA_TBTC); selectAsset(ASSET_SEPOLIA_TBTC);
cy.get(amountField).clear().type('0'); cy.get(amountField).clear().type('0');
cy.getByTestId(submitWithdrawBtn).click(); cy.getByTestId(submitWithdrawBtn).click();
@@ -50,6 +51,8 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
); );
}); });
it('max amount', () => { it('max amount', () => {
// 1002-WITH-005
// 1002-WITH-008
selectAsset(ASSET_EURO); // Will be above maximum because the vega wallet doesn't have any collateral selectAsset(ASSET_EURO); // Will be above maximum because the vega wallet doesn't have any collateral
cy.get(amountField).clear().type('1001', { delay: 100 }); cy.get(amountField).clear().type('1001', { delay: 100 });
cy.getByTestId(submitWithdrawBtn).click(); cy.getByTestId(submitWithdrawBtn).click();
@@ -60,6 +63,7 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
}); });
it('can set amount using use maximum button', () => { it('can set amount using use maximum button', () => {
// 1002-WITH-004
selectAsset(ASSET_SEPOLIA_TBTC); selectAsset(ASSET_SEPOLIA_TBTC);
cy.getByTestId(useMaximumAmount).click(); cy.getByTestId(useMaximumAmount).click();
cy.get(amountField).should('have.value', '1000.00000'); cy.get(amountField).should('have.value', '1000.00000');
@@ -68,6 +72,9 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
describe('withdraw actions', { tags: '@regression' }, () => { describe('withdraw actions', { tags: '@regression' }, () => {
// this is extremely ugly hack, but setting it properly in contract is too much effort for such simple validation // this is extremely ugly hack, but setting it properly in contract is too much effort for such simple validation
// 1002-WITH-018
const withdrawalThreshold = const withdrawalThreshold =
Cypress.env('VEGA_ENV') === 'CUSTOM' ? '0.00' : '100.00'; Cypress.env('VEGA_ENV') === 'CUSTOM' ? '0.00' : '100.00';
before(() => { before(() => {
@@ -88,6 +95,8 @@ describe('withdraw actions', { tags: '@regression' }, () => {
}); });
it('triggers transaction when submitted', () => { it('triggers transaction when submitted', () => {
// 1002-WITH-002
// 1002-WITH-003
selectAsset(ASSET_SEPOLIA_TBTC); selectAsset(ASSET_SEPOLIA_TBTC);
cy.getByTestId('BALANCE_AVAILABLE_label').should( cy.getByTestId('BALANCE_AVAILABLE_label').should(
'contain.text', 'contain.text',
@@ -108,7 +117,4 @@ describe('withdraw actions', { tags: '@regression' }, () => {
cy.getByTestId(submitWithdrawBtn).click(); cy.getByTestId(submitWithdrawBtn).click();
cy.getByTestId('toast').should('contain.text', 'Awaiting confirmation'); cy.getByTestId('toast').should('contain.text', 'Awaiting confirmation');
}); });
it.skip('creates a withdrawal on submit'); // Needs capsule
it.skip('creates a withdrawal on submit and prompts to complete withdrawal'); // Needs capsule
}); });
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+1
View File
@@ -9,6 +9,7 @@ NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/ NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session" NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases
+1
View File
@@ -7,3 +7,4 @@ NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"h
NX_VEGA_TOKEN_URL=https://token.vega.xyz NX_VEGA_TOKEN_URL=https://token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://mainnet-mirror.token.vega.xyz NX_VEGA_TOKEN_URL=https://mainnet-mirror.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+1
View File
@@ -7,3 +7,4 @@ NX_VEGA_NETWORKS={\"DEVNET\":\"https://dev.token.vega.xyz\",\"STAGNET3\":\"https
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+13
View File
@@ -0,0 +1,13 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
@@ -5,7 +5,7 @@ import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
export const DepositsContainer = () => { export const DepositsContainer = () => {
const { pubKey } = useVegaWallet(); const { pubKey, isReadOnly } = useVegaWallet();
const { data, loading, error } = useDataProvider({ const { data, loading, error } = useDataProvider({
dataProvider: depositsProvider, dataProvider: depositsProvider,
variables: { partyId: pubKey || '' }, variables: { partyId: pubKey || '' },
@@ -30,6 +30,7 @@ export const DepositsContainer = () => {
/> />
</div> </div>
</div> </div>
{!isReadOnly && (
<div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2"> <div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2">
<Button <Button
size="sm" size="sm"
@@ -39,6 +40,7 @@ export const DepositsContainer = () => {
{t('Deposit')} {t('Deposit')}
</Button> </Button>
</div> </div>
)}
</div> </div>
); );
}; };
@@ -9,7 +9,7 @@ import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { VegaWalletContainer } from '../../components/vega-wallet-container'; import { VegaWalletContainer } from '../../components/vega-wallet-container';
export const WithdrawalsContainer = () => { export const WithdrawalsContainer = () => {
const { pubKey } = useVegaWallet(); const { pubKey, isReadOnly } = useVegaWallet();
const { data, loading, error } = useDataProvider({ const { data, loading, error } = useDataProvider({
dataProvider: withdrawalProvider, dataProvider: withdrawalProvider,
variables: { partyId: pubKey || '' }, variables: { partyId: pubKey || '' },
@@ -36,6 +36,7 @@ export const WithdrawalsContainer = () => {
/> />
</div> </div>
</div> </div>
{!isReadOnly && (
<div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2"> <div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2">
<Button <Button
size="sm" size="sm"
@@ -45,6 +46,7 @@ export const WithdrawalsContainer = () => {
{t('Make withdrawal')} {t('Make withdrawal')}
</Button> </Button>
</div> </div>
)}
</div> </div>
</VegaWalletContainer> </VegaWalletContainer>
); );

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