diff --git a/apps/governance/.env b/apps/governance/.env index 266d00b1b..367b8fcda 100644 --- a/apps/governance/.env +++ b/apps/governance/.env @@ -22,8 +22,6 @@ NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/ NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket -NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn -NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet #Test configuration variables CYPRESS_FAIRGROUND=false diff --git a/apps/governance/.env.capsule b/apps/governance/.env.capsule index b8814b856..4c371f3e2 100644 --- a/apps/governance/.env.capsule +++ b/apps/governance/.env.capsule @@ -19,6 +19,9 @@ NX_DELEGATIONS_PAGINATION=50 NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz NX_VEGA_REST_URL=http://localhost:3008/api/v2/ +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet + NX_TENDERMINT_URL=http://localhost:26617 NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket @@ -26,4 +29,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket CYPRESS_FAIRGROUND=false # Cosmic elevator flags -NX_SUCCESSOR_MARKETS=false \ No newline at end of file +NX_SUCCESSOR_MARKETS=false diff --git a/apps/governance/.env.devnet b/apps/governance/.env.devnet index 51aa96100..71625ea77 100644 --- a/apps/governance/.env.devnet +++ b/apps/governance/.env.devnet @@ -14,8 +14,11 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou NX_VEGA_REST_URL=https://api.n00.devnet1.vega.xyz/api/v2/ NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996 +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet + NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/ NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket # Cosmic elevator flags -NX_SUCCESSOR_MARKETS=true \ No newline at end of file +NX_SUCCESSOR_MARKETS=true diff --git a/apps/governance/.env.mainnet b/apps/governance/.env.mainnet index 9ac987b42..7a2e15d5c 100644 --- a/apps/governance/.env.mainnet +++ b/apps/governance/.env.mainnet @@ -14,9 +14,11 @@ NX_DELEGATIONS_PAGINATION=50 NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json NX_VEGA_REST_URL=https://api.vega.community/api/v2/ +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet NX_TENDERMINT_URL=https://be.vega.community NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket # Cosmic elevator flags -NX_SUCCESSOR_MARKETS=false \ No newline at end of file +NX_SUCCESSOR_MARKETS=false diff --git a/apps/governance/.env.mainnet-mirror b/apps/governance/.env.mainnet-mirror index 22fd23a50..a847576e3 100644 --- a/apps/governance/.env.mainnet-mirror +++ b/apps/governance/.env.mainnet-mirror @@ -13,9 +13,11 @@ NX_DELEGATIONS_PAGINATION=50 NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-mirror-k8s.ops.vega.xyz NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json NX_VEGA_REST_URL=https://api.mainnet-mirror.vega.rocks/api/v2/ +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket # Cosmic elevator flags -NX_SUCCESSOR_MARKETS=false \ No newline at end of file +NX_SUCCESSOR_MARKETS=false diff --git a/apps/governance/.env.stagnet1 b/apps/governance/.env.stagnet1 index 53f1e733f..a83edd54e 100644 --- a/apps/governance/.env.stagnet1 +++ b/apps/governance/.env.stagnet1 @@ -10,8 +10,11 @@ NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/ +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet + NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket # Cosmic elevator flags -NX_SUCCESSOR_MARKETS=true \ No newline at end of file +NX_SUCCESSOR_MARKETS=true diff --git a/apps/governance/.env.testnet b/apps/governance/.env.testnet index 0a817b1d2..2e64b5662 100644 --- a/apps/governance/.env.testnet +++ b/apps/governance/.env.testnet @@ -15,8 +15,11 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/ NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996 +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet + NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket # Cosmic elevator flags -NX_SUCCESSOR_MARKETS=true \ No newline at end of file +NX_SUCCESSOR_MARKETS=true diff --git a/apps/governance/.env.validators-testnet b/apps/governance/.env.validators-testnet index 0064e8152..17e335022 100644 --- a/apps/governance/.env.validators-testnet +++ b/apps/governance/.env.validators-testnet @@ -12,8 +12,11 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou NX_VEGA_REST_URL=https://api-validators-testnet.vega.rocks/api/v2/ NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996 +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet + NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega. # Cosmic elevator flags -NX_SUCCESSOR_MARKETS=false \ No newline at end of file +NX_SUCCESSOR_MARKETS=false diff --git a/apps/trading-e2e/.env b/apps/trading-e2e/.env index f6970c049..a575afdea 100644 --- a/apps/trading-e2e/.env +++ b/apps/trading-e2e/.env @@ -36,4 +36,4 @@ CYPRESS_VEGA_WALLET_API_TOKEN= # Cosmic elevator flags (MUST be doubled with CYPRESS_ prefix) NX_SUCCESSOR_MARKETS=true -CYPRESS_NX_SUCCESSOR_MARKETS=true \ No newline at end of file +CYPRESS_NX_SUCCESSOR_MARKETS=true diff --git a/apps/trading-e2e/src/integration/trading-deal-ticket-basics.cy.ts b/apps/trading-e2e/src/integration/trading-deal-ticket-basics.cy.ts index 0b2d1036a..b892ca01a 100644 --- a/apps/trading-e2e/src/integration/trading-deal-ticket-basics.cy.ts +++ b/apps/trading-e2e/src/integration/trading-deal-ticket-basics.cy.ts @@ -23,7 +23,7 @@ describe('deal ticket basics', { tags: '@smoke' }, () => { // 0003-WTXN-001 cy.getByTestId('connect-vega-wallet'); // Not connected cy.getByTestId(placeOrderBtn).should('exist'); - cy.getByTestId('get-started-button').should('exist'); + cy.getByTestId('order-connect-wallet').should('exist'); }); it('must be able to select order direction - long/short', function () { @@ -44,7 +44,7 @@ describe('deal ticket basics', { tags: '@smoke' }, () => { mockConnectWallet(); cy.getByTestId(toggleLimit).click(); cy.getByTestId(orderPriceField).clear().type('101'); - cy.getByTestId('get-started-button').click(); + cy.getByTestId('order-connect-wallet').click(); cy.getByTestId('dialog-content').should('be.visible'); cy.getByTestId('connectors-list') .find('[data-testid="connector-jsonRpc"]') diff --git a/apps/trading/.env b/apps/trading/.env index bd619e109..21058b8bb 100644 --- a/apps/trading/.env +++ b/apps/trading/.env @@ -12,8 +12,7 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72 -NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn -NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet + # Cosmic elevator flags NX_SUCCESSOR_MARKETS=true diff --git a/apps/trading/.env.capsule b/apps/trading/.env.capsule index d2a3ef8be..149f153bd 100644 --- a/apps/trading/.env.capsule +++ b/apps/trading/.env.capsule @@ -12,6 +12,8 @@ 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 NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/ NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session" diff --git a/apps/trading/.env.devnet b/apps/trading/.env.devnet index 52112f1bf..e4c6958a0 100644 --- a/apps/trading/.env.devnet +++ b/apps/trading/.env.devnet @@ -13,6 +13,8 @@ NX_VEGA_DOCS_URL=# NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet # Cosmic elevator flags NX_SUCCESSOR_MARKETS=true diff --git a/apps/trading/.env.mainnet b/apps/trading/.env.mainnet index 134a47026..708a34153 100644 --- a/apps/trading/.env.mainnet +++ b/apps/trading/.env.mainnet @@ -13,6 +13,8 @@ NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports NX_VEGA_CONSOLE_URL=https://console.vega.xyz +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-mainnet/codfcglpplgmmlokgilfkpcjnmkbfiel +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet-mainnet # TAG name of the current app version - TODO: bump to the latest upon release NX_APP_VERSION=v0.20.21-core-0.71.6 diff --git a/apps/trading/.env.mainnet-mirror b/apps/trading/.env.mainnet-mirror index a68b8e1e4..e28f506fe 100644 --- a/apps/trading/.env.mainnet-mirror +++ b/apps/trading/.env.mainnet-mirror @@ -13,6 +13,8 @@ NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-mainnet/codfcglpplgmmlokgilfkpcjnmkbfiel +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet-mainnet # TAG name of the current app version - TODO: bump to the latest upon release NX_APP_VERSION=v0.20.19-core-0.71.6 diff --git a/apps/trading/.env.stagnet1 b/apps/trading/.env.stagnet1 index 7a75a6ee0..91425161b 100644 --- a/apps/trading/.env.stagnet1 +++ b/apps/trading/.env.stagnet1 @@ -13,9 +13,11 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet # Cosmic elevator flags NX_SUCCESSOR_MARKETS=true NX_STOP_ORDERS=true # NX_ICEBERG_ORDERS -# NX_PRODUCT_PERPETUALS \ No newline at end of file +# NX_PRODUCT_PERPETUALS diff --git a/apps/trading/.env.testnet b/apps/trading/.env.testnet index 5958b71b6..bf23f97a2 100644 --- a/apps/trading/.env.testnet +++ b/apps/trading/.env.testnet @@ -14,6 +14,8 @@ NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports NX_VEGA_CONSOLE_URL=https://console.fairground.wtf +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet # Cosmic elevator flags NX_SUCCESSOR_MARKETS=true @@ -22,4 +24,4 @@ NX_ICEBERG_ORDERS=true # NX_PRODUCT_PERPETUALS NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz -NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket \ No newline at end of file +NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket diff --git a/apps/trading/.env.validators-testnet b/apps/trading/.env.validators-testnet index 2461252a1..11f5f217e 100644 --- a/apps/trading/.env.validators-testnet +++ b/apps/trading/.env.validators-testnet @@ -15,6 +15,9 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks +NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn +NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet + # Cosmic elevator flags NX_SUCCESSOR_MARKETS=false NX_STOP_ORDERS=false diff --git a/apps/trading/components/constants.ts b/apps/trading/components/constants.ts index f1168e6ce..4e9781d22 100644 --- a/apps/trading/components/constants.ts +++ b/apps/trading/components/constants.ts @@ -1,10 +1,2 @@ -import { t } from '@vegaprotocol/i18n'; - export const THROTTLE_UPDATE_TIME = 500; export const ONBOARDING_VIEWED_KEY = 'vega_onboarding_viewed'; -export const MAINNET_WELCOME_HEADER = t( - 'Trade cash settled futures on the fully decentralised Vega network.' -); -export const TESTNET_WELCOME_HEADER = t( - 'Try out trading cash settled futures on the fully decentralised Vega network (Testnet).' -); diff --git a/apps/trading/components/welcome-dialog/get-started.spec.tsx b/apps/trading/components/welcome-dialog/get-started.spec.tsx index b8fcf6865..01ff2dbdf 100644 --- a/apps/trading/components/welcome-dialog/get-started.spec.tsx +++ b/apps/trading/components/welcome-dialog/get-started.spec.tsx @@ -1,16 +1,36 @@ +import { MemoryRouter } from 'react-router-dom'; import type { VegaWalletContextShape } from '@vegaprotocol/wallet'; import { VegaWalletContext } from '@vegaprotocol/wallet'; import { GetStarted } from './get-started'; import { render, screen } from '@testing-library/react'; +let mockStep = 1; +jest.mock('./use-get-onboarding-step', () => ({ + ...jest.requireActual('./use-get-onboarding-step'), + useGetOnboardingStep: jest.fn(() => mockStep), +})); + describe('GetStarted', () => { const renderComponent = (context: Partial = {}) => { return render( - - - + + + + + ); }; + const checkTicks = (elements: Element[]) => { + elements.forEach((item, i) => { + if (i + 1 < mockStep) { + expect(item.querySelector('[data-testid="icon-tick"]')).toBeTruthy(); + } + }); + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); it('renders full get started content if not connected and no browser wallet detected', () => { renderComponent(); @@ -20,12 +40,71 @@ describe('GetStarted', () => { it('renders connect prompt if no pubKey but wallet installed', () => { globalThis.window.vega = {} as Vega; renderComponent(); - expect(screen.getByTestId('order-connect-wallet')).toBeInTheDocument(); + expect(screen.getByTestId('get-started-banner')).toBeInTheDocument(); globalThis.window.vega = undefined as unknown as Vega; }); it('renders nothing if connected', () => { + mockStep = 0; const { container } = renderComponent({ pubKey: 'my-pubkey' }); expect(container).toBeEmptyDOMElement(); }); + + it('steps should be ticked', () => { + const navigatorGetter: jest.SpyInstance = jest.spyOn( + window.navigator, + 'userAgent', + 'get' + ); + navigatorGetter.mockReturnValue('Chrome'); + mockStep = 1; + const { rerender, container } = renderComponent(); + expect(screen.queryByTestId('icon-tick')).not.toBeInTheDocument(); + expect(screen.getByTestId('get-wallet-button')).toBeInTheDocument(); + + mockStep = 2; + rerender( + + + + + + ); + checkTicks(screen.getAllByRole('listitem')); + expect(screen.getByRole('button', { name: 'Connect' })).toBeInTheDocument(); + + mockStep = 3; + rerender( + + + + + + ); + checkTicks(screen.getAllByRole('listitem')); + expect(screen.getByRole('button', { name: 'Deposit' })).toBeInTheDocument(); + + mockStep = 4; + rerender( + + + + + + ); + checkTicks(screen.getAllByRole('listitem')); + expect(screen.getByRole('button', { name: 'Dismiss' })).toBeInTheDocument(); + + mockStep = 5; + rerender( + + + + + + ); + expect(container).toBeEmptyDOMElement(); + }); }); diff --git a/apps/trading/components/welcome-dialog/get-started.tsx b/apps/trading/components/welcome-dialog/get-started.tsx index 3889a7662..580a8c899 100644 --- a/apps/trading/components/welcome-dialog/get-started.tsx +++ b/apps/trading/components/welcome-dialog/get-started.tsx @@ -1,36 +1,96 @@ import classNames from 'classnames'; import { t } from '@vegaprotocol/i18n'; -import { ExternalLink, Intent, TradingButton } from '@vegaprotocol/ui-toolkit'; import { + ExternalLink, + Intent, + TradingButton, + VegaIcon, + VegaIconNames, +} from '@vegaprotocol/ui-toolkit'; +import { + GetWalletButton, useVegaWallet, useVegaWalletDialogStore, - isBrowserWalletInstalled, } from '@vegaprotocol/wallet'; import { Networks, useEnvironment } from '@vegaprotocol/environment'; import { useLocalStorage } from '@vegaprotocol/react-helpers'; +import { useNavigate } from 'react-router-dom'; +import { + OnboardingStep, + useGetOnboardingStep, +} from './use-get-onboarding-step'; +import { Links, Routes } from '../../pages/client-router'; +import { useGlobalStore } from '../../stores'; +import { useSidebar, ViewType } from '../sidebar'; import * as constants from '../constants'; interface Props { lead?: string; } -export const GetStarted = ({ lead }: Props) => { - const { pubKey } = useVegaWallet(); - const { VEGA_ENV, VEGA_NETWORKS } = useEnvironment(); - const CANONICAL_URL = VEGA_NETWORKS[VEGA_ENV] || 'https://console.vega.xyz'; - +const GetStartedButton = ({ step }: { step: OnboardingStep }) => { + const navigate = useNavigate(); const [, setOnboardingViewed] = useLocalStorage( constants.ONBOARDING_VIEWED_KEY ); + const update = useGlobalStore((store) => store.update); + const marketId = useGlobalStore((store) => store.marketId); + const link = marketId ? Links[Routes.MARKET](marketId) : Links[Routes.HOME](); + const openVegaWalletDialog = useVegaWalletDialogStore( + (store) => store.openVegaWalletDialog + ); + const setView = useSidebar((store) => store.setView); + let buttonText = t('Get started'); + let onClickHandle = () => { + openVegaWalletDialog(); + }; + if (step === OnboardingStep.ONBOARDING_WALLET_STEP) { + return ; + } else if (step === OnboardingStep.ONBOARDING_CONNECT_STEP) { + buttonText = t('Connect'); + } else if (step === OnboardingStep.ONBOARDING_DEPOSIT_STEP) { + buttonText = t('Deposit'); + onClickHandle = () => { + navigate(link); + setView({ type: ViewType.Deposit }); + update({ onBoardingDismissed: true }); + }; + } else if (step === OnboardingStep.ONBOARDING_ORDER_STEP) { + buttonText = t('Dismiss'); + onClickHandle = () => { + navigate(link); + setView({ type: ViewType.Order }); + setOnboardingViewed('true'); + }; + } + + return ( + + {buttonText} + + ); +}; + +export const GetStarted = ({ lead }: Props) => { + const { pubKey } = useVegaWallet(); + const { VEGA_ENV, VEGA_NETWORKS } = useEnvironment(); + const CANONICAL_URL = VEGA_NETWORKS[VEGA_ENV] || 'https://console.vega.xyz'; + const [onBoardingViewed] = useLocalStorage(constants.ONBOARDING_VIEWED_KEY); + const currentStep = useGetOnboardingStep(); const openVegaWalletDialog = useVegaWalletDialogStore( (store) => store.openVegaWalletDialog ); - const onButtonClick = () => { - openVegaWalletDialog(); - setOnboardingViewed('true'); - }; + const getStartedNeeded = + onBoardingViewed !== 'true' && + currentStep && + currentStep < OnboardingStep.ONBOARDING_COMPLETE_STEP; const wrapperClasses = classNames( 'flex flex-col py-4 px-6 gap-4 rounded', @@ -39,27 +99,48 @@ export const GetStarted = ({ lead }: Props) => { { 'mt-8': !lead } ); - if (!pubKey && !isBrowserWalletInstalled()) { + if (getStartedNeeded) { return (
{lead &&

{lead}

}

{t('Get started')}

-
    -
  • {t('Get a Vega wallet')}
  • -
  • {t('Connect')}
  • -
  • {t('Deposit funds')}
  • -
  • {t('Open a position')}
  • +
      +
    • +
      + {currentStep > OnboardingStep.ONBOARDING_WALLET_STEP && ( + + )} +
      +
      1. {t('Get a Vega wallet')}
      +
    • +
    • +
      + {(currentStep > OnboardingStep.ONBOARDING_CONNECT_STEP || + pubKey) && } +
      +
      2. {t('Connect')}
      +
    • +
    • +
      + {currentStep > OnboardingStep.ONBOARDING_DEPOSIT_STEP && ( + + )} +
      +
      3. {t('Deposit funds')}
      +
    • +
    • +
      + {currentStep > OnboardingStep.ONBOARDING_ORDER_STEP && ( + + )} +
      +
      4. {t('Open a position')}
      +
- - {t('Get started')} - +
{VEGA_ENV === Networks.MAINNET && (

diff --git a/apps/trading/components/welcome-dialog/use-get-onboarding-step.spec.tsx b/apps/trading/components/welcome-dialog/use-get-onboarding-step.spec.tsx new file mode 100644 index 000000000..3c2e6d30f --- /dev/null +++ b/apps/trading/components/welcome-dialog/use-get-onboarding-step.spec.tsx @@ -0,0 +1,97 @@ +import type { ReactNode } from 'react'; +import { renderHook } from '@testing-library/react'; +import { + useGetOnboardingStep, + OnboardingStep, +} from './use-get-onboarding-step'; +import type { VegaWalletContextShape } from '@vegaprotocol/wallet'; +import { VegaWalletContext } from '@vegaprotocol/wallet'; +import { useDataProvider } from '@vegaprotocol/data-provider'; +import { depositsProvider } from '@vegaprotocol/deposits'; +import { aggregatedAccountsDataProvider } from '@vegaprotocol/accounts'; +import { ordersWithMarketProvider } from '@vegaprotocol/orders'; +import { positionsDataProvider } from '@vegaprotocol/positions'; + +let mockData: object[] | null = [{ id: 'item-id' }]; +jest.mock('@vegaprotocol/data-provider', () => ({ + ...jest.requireActual('@vegaprotocol/data-provider'), + useDataProvider: jest.fn(() => ({ data: mockData })), +})); + +let mockContext: Partial = { pubKey: 'test-pubkey' }; + +describe('useGetOnboardingStep', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockData = [{ id: 'item-id' }]; + mockContext = { pubKey: 'test-pubkey' }; + globalThis.window.vega = {} as Vega; + }); + + const wrapper = ({ children }: { children: ReactNode }) => ( + + {children} + + ); + + it('should return properly ONBOARDING_UNKNOWN_STEP', () => { + mockData = null; + const { result } = renderHook(() => useGetOnboardingStep(), { wrapper }); + expect(result.current).toEqual(OnboardingStep.ONBOARDING_UNKNOWN_STEP); + }); + + it('should return properly ONBOARDING_WALLET_STEP', () => { + // @ts-ignore test only purpose + globalThis.window.vega = undefined; + const { result } = renderHook(() => useGetOnboardingStep(), { wrapper }); + expect(result.current).toEqual(OnboardingStep.ONBOARDING_WALLET_STEP); + }); + + it('should return properly ONBOARDING_CONNECT_STEP', () => { + mockContext = { pubKey: null }; + const { result } = renderHook(() => useGetOnboardingStep(), { wrapper }); + expect(result.current).toEqual(OnboardingStep.ONBOARDING_CONNECT_STEP); + }); + + it('should return properly ONBOARDING_DEPOSIT_STEP', async () => { + (useDataProvider as jest.Mock).mockImplementation((args) => { + if ( + args.dataProvider === depositsProvider || + args.dataProvider === aggregatedAccountsDataProvider + ) { + return { data: [] }; + } + return { data: mockData }; + }); + const { result } = renderHook(() => useGetOnboardingStep(), { wrapper }); + await expect(result.current).toEqual( + OnboardingStep.ONBOARDING_DEPOSIT_STEP + ); + }); + + it('should return properly ONBOARDING_ORDER_STEP', async () => { + (useDataProvider as jest.Mock).mockImplementation((args) => { + if ( + args.dataProvider === ordersWithMarketProvider || + args.dataProvider === positionsDataProvider + ) { + return { data: [] }; + } + return { data: mockData }; + }); + const { result } = renderHook(() => useGetOnboardingStep(), { wrapper }); + await expect(result.current).toEqual(OnboardingStep.ONBOARDING_ORDER_STEP); + }); + + it('should return properly ONBOARDING_COMPLETE_STEP', async () => { + (useDataProvider as jest.Mock).mockImplementation(() => { + return { data: mockData }; + }); + const { result } = renderHook(() => useGetOnboardingStep(), { wrapper }); + await expect(result.current).toEqual( + OnboardingStep.ONBOARDING_COMPLETE_STEP + ); + }); +}); diff --git a/apps/trading/components/welcome-dialog/use-get-onboarding-step.ts b/apps/trading/components/welcome-dialog/use-get-onboarding-step.ts new file mode 100644 index 000000000..741def751 --- /dev/null +++ b/apps/trading/components/welcome-dialog/use-get-onboarding-step.ts @@ -0,0 +1,82 @@ +import { isBrowserWalletInstalled, useVegaWallet } from '@vegaprotocol/wallet'; +import { depositsProvider } from '@vegaprotocol/deposits'; +import { useDataProvider } from '@vegaprotocol/data-provider'; +import { ordersWithMarketProvider } from '@vegaprotocol/orders'; +import * as Types from '@vegaprotocol/types'; +import { aggregatedAccountsDataProvider } from '@vegaprotocol/accounts'; +import { positionsDataProvider } from '@vegaprotocol/positions'; +import { useGlobalStore } from '../../stores'; + +export enum OnboardingStep { + ONBOARDING_UNKNOWN_STEP, + ONBOARDING_WALLET_STEP, + ONBOARDING_CONNECT_STEP, + ONBOARDING_DEPOSIT_STEP, + ONBOARDING_ORDER_STEP, + ONBOARDING_COMPLETE_STEP, +} + +export const useGetOnboardingStep = () => { + const connecting = useGlobalStore((store) => store.eagerConnecting); + const { pubKey = '', pubKeys } = useVegaWallet(); + const { data: depositsData } = useDataProvider({ + dataProvider: depositsProvider, + variables: { partyId: pubKey || '' }, + skip: !pubKey, + }); + const { data: collateralData } = useDataProvider({ + dataProvider: aggregatedAccountsDataProvider, + variables: { partyId: pubKey || '' }, + skip: !pubKey, + }); + const collaterals = Boolean(collateralData?.length); + const deposits = + depositsData?.some( + (item) => item.status === Types.DepositStatus.STATUS_FINALIZED + ) || false; + const { data: ordersData } = useDataProvider({ + dataProvider: ordersWithMarketProvider, + variables: { + partyId: pubKey || '', + pagination: { + first: 1, + }, + }, + skip: !pubKey, + }); + const orders = Boolean(ordersData?.length); + + const partyIds = pubKeys?.map((item) => item.publicKey) || []; + const { data: positionsData } = useDataProvider({ + dataProvider: positionsDataProvider, + variables: { + partyIds, + }, + skip: !partyIds?.length, + }); + const positions = Boolean(positionsData?.length); + + const isLoading = Boolean( + (connecting || pubKey) && + (depositsData === null || + ordersData === null || + collateralData === null || + positionsData === null) + ); + if (isLoading) { + return OnboardingStep.ONBOARDING_UNKNOWN_STEP; + } + if (!isBrowserWalletInstalled()) { + return OnboardingStep.ONBOARDING_WALLET_STEP; + } + if (!pubKey) { + return OnboardingStep.ONBOARDING_CONNECT_STEP; + } + if (!deposits && !collaterals) { + return OnboardingStep.ONBOARDING_DEPOSIT_STEP; + } + if (!orders && !positions) { + return OnboardingStep.ONBOARDING_ORDER_STEP; + } + return OnboardingStep.ONBOARDING_COMPLETE_STEP; +}; diff --git a/apps/trading/components/welcome-dialog/welcome-dialog-content.tsx b/apps/trading/components/welcome-dialog/welcome-dialog-content.tsx index c29637f9f..218db85bb 100644 --- a/apps/trading/components/welcome-dialog/welcome-dialog-content.tsx +++ b/apps/trading/components/welcome-dialog/welcome-dialog-content.tsx @@ -3,21 +3,19 @@ import { GetStarted } from './get-started'; import { TradingButton } from '@vegaprotocol/ui-toolkit'; import { useNavigate } from 'react-router-dom'; import { Links, Routes } from '../../pages/client-router'; -import { useLocalStorage } from '@vegaprotocol/react-helpers'; -import * as constants from '../constants'; import { Networks, useEnvironment } from '@vegaprotocol/environment'; import type { ReactNode } from 'react'; +import { useGlobalStore } from '../../stores'; export const WelcomeDialogContent = () => { const { VEGA_ENV } = useEnvironment(); - const [, setOnboardingViewed] = useLocalStorage( - constants.ONBOARDING_VIEWED_KEY - ); + + const update = useGlobalStore((store) => store.update); const navigate = useNavigate(); const browseMarkets = () => { const link = Links[Routes.MARKETS](); navigate(link); - setOnboardingViewed('true'); + update({ onBoardingDismissed: true }); }; const lead = VEGA_ENV === Networks.MAINNET @@ -57,7 +55,7 @@ export const WelcomeDialogContent = () => { {t('Browse the markets')}

-
+
diff --git a/apps/trading/components/welcome-dialog/welcome-dialog.tsx b/apps/trading/components/welcome-dialog/welcome-dialog.tsx index c1b6670bc..7739156ee 100644 --- a/apps/trading/components/welcome-dialog/welcome-dialog.tsx +++ b/apps/trading/components/welcome-dialog/welcome-dialog.tsx @@ -2,31 +2,38 @@ import React from 'react'; import { useNavigate } from 'react-router-dom'; import { Dialog, Intent } from '@vegaprotocol/ui-toolkit'; import { t } from '@vegaprotocol/i18n'; -import { useLocalStorage } from '@vegaprotocol/react-helpers'; import { useEnvironment } from '@vegaprotocol/environment'; -import { isBrowserWalletInstalled } from '@vegaprotocol/wallet'; -import * as constants from '../constants'; +import { useLocalStorage } from '@vegaprotocol/react-helpers'; import { WelcomeDialogContent } from './welcome-dialog-content'; -import { getConfig } from '@vegaprotocol/wallet'; import { Links, Routes } from '../../pages/client-router'; import { useGlobalStore } from '../../stores'; +import { + useGetOnboardingStep, + OnboardingStep, +} from './use-get-onboarding-step'; +import * as constants from '../constants'; export const WelcomeDialog = () => { const { VEGA_ENV } = useEnvironment(); - const [onBoardingViewed, setOnboardingViewed] = useLocalStorage( - constants.ONBOARDING_VIEWED_KEY - ); + const [onBoardingViewed] = useLocalStorage(constants.ONBOARDING_VIEWED_KEY); + const update = useGlobalStore((store) => store.update); + const dismissed = useGlobalStore((store) => store.onBoardingDismissed); + const currentStep = useGetOnboardingStep(); + const navigate = useNavigate(); const isOnboardingDialogNeeded = - onBoardingViewed !== 'true' && !isBrowserWalletInstalled() && !getConfig(); + onBoardingViewed !== 'true' && + currentStep && + currentStep < OnboardingStep.ONBOARDING_COMPLETE_STEP && + !dismissed; const marketId = useGlobalStore((store) => store.marketId); const onClose = () => { - setOnboardingViewed('true'); const link = marketId ? Links[Routes.MARKET](marketId) : Links[Routes.HOME](); navigate(link); + update({ onBoardingDismissed: true }); }; const title = ( diff --git a/apps/trading/pages/_app.page.tsx b/apps/trading/pages/_app.page.tsx index eb74bc937..c3e76a848 100644 --- a/apps/trading/pages/_app.page.tsx +++ b/apps/trading/pages/_app.page.tsx @@ -1,4 +1,4 @@ -import { useMemo, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import Head from 'next/head'; import type { AppProps } from 'next/app'; import { t } from '@vegaprotocol/i18n'; @@ -23,7 +23,7 @@ import { useNodeSwitcherStore, } from '@vegaprotocol/environment'; import './styles.css'; -import { usePageTitleStore } from '../stores'; +import { useGlobalStore, usePageTitleStore } from '../stores'; import DialogsContainer from './dialogs-container'; import ToastsManager from './toasts-manager'; import { @@ -170,7 +170,8 @@ const PartyData = () => { const MaybeConnectEagerly = () => { const { VEGA_ENV, SENTRY_DSN } = useEnvironment(); - useVegaEagerConnect(Connectors); + const update = useGlobalStore((store) => store.update); + const eagerConnecting = useVegaEagerConnect(Connectors); const [isTelemetryApproved] = useTelemetryApproval(); useEthereumEagerConnect( isTelemetryApproved ? { dsn: SENTRY_DSN, env: VEGA_ENV } : {} @@ -182,5 +183,8 @@ const MaybeConnectEagerly = () => { if (query && !pubKey) { connect(Connectors['view']); } + useEffect(() => { + update({ eagerConnecting }); + }, [update, eagerConnecting]); return null; }; diff --git a/apps/trading/stores/global.ts b/apps/trading/stores/global.ts index e5b69fd04..cbd56fd09 100644 --- a/apps/trading/stores/global.ts +++ b/apps/trading/stores/global.ts @@ -4,6 +4,8 @@ import produce from 'immer'; interface GlobalStore { marketId: string | null; + onBoardingDismissed: boolean; + eagerConnecting: boolean; update: (store: Partial>) => void; } @@ -14,6 +16,8 @@ interface PageTitleStore { export const useGlobalStore = create()((set) => ({ marketId: LocalStorage.getItem('marketId') || null, + onBoardingDismissed: false, + eagerConnecting: false, update: (newState) => { set( produce((state: GlobalStore) => { diff --git a/libs/positions/src/lib/positions-data-providers.ts b/libs/positions/src/lib/positions-data-providers.ts index d5c533b83..fb0ad4624 100644 --- a/libs/positions/src/lib/positions-data-providers.ts +++ b/libs/positions/src/lib/positions-data-providers.ts @@ -181,7 +181,7 @@ const getSubscriptionVariables = ( ): PositionsSubscriptionSubscriptionVariables[] => ([] as string[]).concat(variables.partyIds).map((partyId) => ({ partyId })); -const positionsDataProvider = makeDataProvider< +export const positionsDataProvider = makeDataProvider< PositionsQuery, PositionFieldsFragment[], PositionsSubscriptionSubscription, diff --git a/libs/wallet/src/connect-dialog/connect-dialog.tsx b/libs/wallet/src/connect-dialog/connect-dialog.tsx index 8714e5729..acd3ea870 100644 --- a/libs/wallet/src/connect-dialog/connect-dialog.tsx +++ b/libs/wallet/src/connect-dialog/connect-dialog.tsx @@ -204,6 +204,7 @@ const ConnectorList = ({ setWalletUrl: (value: string) => void; isDesktopWalletRunning: boolean | null; }) => { + const { pubKey } = useVegaWallet(); const title = isBrowserWalletInstalled() ? t('Connect Vega wallet') : t('Get a Vega wallet'); @@ -234,7 +235,7 @@ const ConnectorList = ({ onClick={() => onSelect('injected')} /> ) : ( - + )}
@@ -242,6 +243,7 @@ const ConnectorList = ({ type="view" text={t('View as party')} onClick={() => onSelect('view')} + disabled={Boolean(pubKey)} />
@@ -318,7 +320,7 @@ const SelectedForm = ({ throw new Error('No connector selected'); }; -const GetWallet = () => { +export const GetWalletButton = ({ className }: { className?: string }) => { const { MOZILLA_EXTENSION_URL, CHROME_EXTENSION_URL } = useEnvironment(); const isItChrome = window.navigator.userAgent.includes('Chrome'); const isItMozilla = @@ -347,10 +349,13 @@ const GetWallet = () => { return !isItChrome && !isItMozilla ? (
{buttonContent} @@ -360,7 +365,7 @@ const GetWallet = () => { onClick={onClick} intent={Intent.Info} data-testid="get-wallet-button" - className="relative" + className={classNames('relative', className)} size="small" fill > @@ -409,6 +414,7 @@ const CustomUrlInput = ({ isDesktopWalletRunning: boolean | null; onSelect: (type: WalletType) => void; }) => { + const { pubKey } = useVegaWallet(); const [urlInputExpanded, setUrlInputExpanded] = useState(false); return urlInputExpanded ? ( <> @@ -433,7 +439,7 @@ const CustomUrlInput = ({ /> onSelect('jsonRpc')} @@ -442,7 +448,7 @@ const CustomUrlInput = ({ ) : ( <> onSelect('jsonRpc')} @@ -453,6 +459,7 @@ const CustomUrlInput = ({ diff --git a/libs/wallet/src/use-is-wallet-service-running.tsx b/libs/wallet/src/use-is-wallet-service-running.tsx index 4dd5ca50e..404f79272 100644 --- a/libs/wallet/src/use-is-wallet-service-running.tsx +++ b/libs/wallet/src/use-is-wallet-service-running.tsx @@ -12,7 +12,9 @@ export const useIsWalletServiceRunning = ( const checkState = useCallback(async () => { const connector = connectors['jsonRpc'] as JsonRpcConnector; - connector.url = url; + if (url && url !== connector.url) { + connector.url = url; + } try { await connector.checkCompat(); const chainIdResult = await connector.getChainId(); diff --git a/nx.json b/nx.json index 0cc81acee..d9f27667e 100644 --- a/nx.json +++ b/nx.json @@ -21,8 +21,7 @@ "echo $NX_TENDERMINT_URL", "echo $NX_TENDERMINT_WEBSOCKET_URL", "echo $NX_ETHEREUM_PROVIDER_URL" - ], - "url": "https://cloud.nx.app" + ] } } }, diff --git a/specs/0007-FUGS-first-use-get-started.md b/specs/0007-FUGS-first-use-get-started.md index 434fe17d0..10c87a581 100644 --- a/specs/0007-FUGS-first-use-get-started.md +++ b/specs/0007-FUGS-first-use-get-started.md @@ -1,22 +1,34 @@ # First use & get started steps -## When first enter the app +## "Onboarding" state is gradable and has following steps: (0007-FUGS-003) + +- New visitor - has no wallet nor any dapps running. + - I **must** see CTA button "Get started", which clicking launches the get wallet flow (wallet connection window with links to the Chrome and FF stores) +- Has wallet - Once wallet detected set to this. + - I **must** see CTA button "Connect", which clicking launches the wallet connection +- Has connected - Once user has connected set to this. + - I **must** see CTA button "Deposit", which clicking launches the deposit ticket. +- Has deposited - Once user has made AT LEAST one deposit of ANY settlement asset set to this. + - I **must** see CTA button "Dismiss", which clicking updates the state to Ready to trade - Get started box should now disappear forever. +- Ready to trade - Once user has made at least one deposit AND has dismissed the "Get Started" box in the ticket. + - Onboarding window nor contextual "Get started" banner should be not displayed anymore. + +## When first enter the app or next times, but I didn't accomplish all onboarding steps. - **Must** When I open Console for the first time I can see what it is i.e. a short description and key features in auto opened dialog window (first use popup) (0007-FUGS-001) -- **Must** If my wallet is already connected I don't see the first use popup (0007-FUGS-002) -- - **Must** If window.vega is detected (browser wallet is installed), don't open first use popup (0007-FUGS-003) -- - **Must** If we detect previous connection using localStorage for desktop/cli wallet, don't open first use popup (0007-FUGS-004) +- If full "onboarding" hasn't been accomplished yet, I **must** see the popup with my progress marked. (0007-FUGS-002) - **Must** There is a call to action to browse markets, linking to the market view market/all (0007-FUGS-005) - **Must** I can see the steps I need to take to get started trading (0007-FUGS-006) - **Must** There is a call to action to get started, triggering the connect modal (0007-FUGS-007) - **Must** There is a link to try out trading on Fairground when I'm on Mainnet (0007-FUGS-008) - **Must** There is a link to trade with real funds on Mainnet when I am on Fairground (0007-FUGS-010) - **Must** When I am on the Fairground version, I can see a warning / call out that this is Fairground meaning I can try out with virtual assets at no risk (0007-FUGS-011) +- If I dismiss the popup, I **must** not see it unless I NOT accomplish full "onboarding" - If I dismiss the popup, I land on the default market (0007-FUGS-012) -## When first use popup has been seen, but no browser wallet is installed +## When the popup has been dismissed: -- **Must** I can see the steps to get started with a visible call to action to "get started" in the context of the deal ticket, deposit, withdraw, transfer components in the sidebar (0007-FUGS-013) +- **Must** I can see the steps to get started with a visible call to action (according to my progress) in the context of the deal ticket, deposit, withdraw, transfer components in the sidebar (0007-FUGS-013) - **Must** Remove buttons from pane containers that prompt to connect wallet (0007-FUGS-014) - **Must** We've replaced "connect wallet" in the top right with "get started" (0007-FUGS-015) - **Must** When I press the get started CTA, I see the wallet connect popup (0007-FUGS-016)