Compare commits

..
80 changed files with 536 additions and 1090 deletions
+1 -1
View File
@@ -125,7 +125,7 @@ jobs:
#----------------------------------------------
- name: Run tests
working-directory: ./console-test
run: poetry run pytest -s --numprocesses auto --dist loadfile
run: poetry run pytest -s --numprocesses auto
- name: Check files
run: |
ls -al .
@@ -29,6 +29,37 @@ fragment ExplorerPartyAssetsAccounts on AccountBalance {
}
}
fragment ExplorerPartyLinks on AccountBalance {
asset {
name
id
decimals
symbol
source {
__typename
... on ERC20 {
contractAddress
}
}
}
type
balance
market {
id
decimalPlaces
tradableInstrument {
instrument {
name
product {
... on Future {
quoteName
}
}
}
}
}
}
query ExplorerPartyAssets($partyId: ID!) {
partiesConnection(id: $partyId) {
edges {
@@ -64,7 +64,7 @@ export const ExplorerPartyAssetsDocument = gql`
}
stakingSummary {
currentStakeAvailable
linkings(pagination: {last: 100}) {
linkings(pagination: {first: 100}) {
edges {
node {
type
@@ -113,4 +113,4 @@ export function useExplorerPartyAssetsLazyQuery(baseOptions?: Apollo.LazyQueryHo
}
export type ExplorerPartyAssetsQueryHookResult = ReturnType<typeof useExplorerPartyAssetsQuery>;
export type ExplorerPartyAssetsLazyQueryHookResult = ReturnType<typeof useExplorerPartyAssetsLazyQuery>;
export type ExplorerPartyAssetsQueryResult = Apollo.QueryResult<ExplorerPartyAssetsQuery, ExplorerPartyAssetsQueryVariables>;
export type ExplorerPartyAssetsQueryResult = Apollo.QueryResult<ExplorerPartyAssetsQuery, ExplorerPartyAssetsQueryVariables>;
@@ -42,14 +42,14 @@ export const PartyBlockStake = ({
linkedLength && linkedLength > 0
? p?.stakingSummary?.linkings?.edges
?.reduce((total, e) => {
const accumulator = new BigNumber(total);
const diff = new BigNumber(e?.node.amount || 0);
const accumulator = new BigNumber(total)
const diff = new BigNumber(e?.node.amount || 0)
if (e?.node.type === 'TYPE_LINK') {
return accumulator.plus(diff);
} else if (e?.node.type === 'TYPE_UNLINK') {
return accumulator.minus(diff);
} else {
return accumulator;
return accumulator
}
}, new BigNumber(0))
.toString()
@@ -361,34 +361,6 @@ describe(
stakingPageDisassociateAllTokens();
});
it('Error message should be displayed if error returned from wallet when voting', function () {
const errorMsg =
'Application error: party has already submitted the maximum number of transactions of this type per epoch (3)';
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getProposalFromTitle(rawProposal.rationale.title).within(() =>
cy.getByTestId(viewProposalButton).click()
);
cy.intercept('POST', '/api/v2/requests', {
jsonrpc: '2.0',
error: {
code: 2001,
message: 'Application error',
data: 'party has already submitted the maximum number of transactions of this type per epoch (3)',
},
id: '-PK5EGmErnjLhAmzMeclC',
});
cy.contains('Vote breakdown').should('be.visible', { timeout: 10000 });
cy.getByTestId('vote-buttons').contains('for').click();
cy.getByTestId('dialog-title').should(
'have.text',
'Transaction failed'
);
cy.getByTestId('Error').should('have.text', errorMsg);
});
});
it('Able to see successor market details with new and updated values', function () {
cy.createMarket();
cy.reload();
@@ -119,7 +119,6 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
});
});
// 0006-NETW-001 0006-NETW-002
it('should display network data', function () {
cy.getByTestId('git-network-data')
.should('contain.text', 'Reading network data from')
@@ -131,37 +130,6 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
});
});
// 0006-NETW-003 0006-NETW-008 0006-NETW-009 0006-NETW-010 0006-NETW-012 0006-NETW-013 0006-NETW-017 0006-NETW-018 0006-NETW-019 0006-NETW-020
it('should have option to switch to different network node', function () {
cy.getByTestId('git-network-data').within(() => {
cy.getByTestId('link').click();
});
cy.getByTestId('node-row').within(() => {
cy.getByTestId('node-url-0')
.parent()
.should('have.text', 'http://localhost:3008/graphql');
cy.getByTestId('response-time-cell')
.invoke('text')
.should('not.be.empty')
.and('not.eq', 'Checking');
cy.getByTestId('block-height-cell')
.invoke('text')
.should('not.be.empty')
.then((currentBlockHeight) => {
// Check that block height updates automatically
cy.getByTestId('block-height-cell')
.invoke('text')
.should('not.eq', currentBlockHeight);
});
cy.getByTestId('subscription-cell').should('have.text', 'Yes');
});
cy.getByTestId('connect').should('be.disabled');
cy.getByTestId('node-url-custom').click();
cy.get('input').should('exist');
cy.getByTestId('connect').should('be.disabled');
cy.getByTestId('icon-cross').click();
});
it('should display eth data', function () {
cy.getByTestId('git-eth-data')
.should('contain.text', 'Reading Ethereum data from')
@@ -170,7 +138,6 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
});
});
// 0006-NETW-011
it('should contain link for known issues on Github', function () {
cy.getByTestId('git-info').within(() => {
cy.contains('Known issues and feedback on')
@@ -183,8 +183,9 @@ export function clickOnValidatorFromList(
cy.get(`[row-id="${validatorNumber}"]`)
.should('be.visible')
.first()
.as('validatorOnList');
cy.get('@validatorOnList').click();
.within(() => {
cy.get(stakeValidatorListName).click();
});
}
}
+2
View File
@@ -22,6 +22,8 @@ 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
+1 -4
View File
@@ -19,9 +19,6 @@ 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
@@ -29,4 +26,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
CYPRESS_FAIRGROUND=false
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false
NX_SUCCESSOR_MARKETS=false
+1 -4
View File
@@ -14,11 +14,8 @@ 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
NX_SUCCESSOR_MARKETS=true
+1 -3
View File
@@ -14,11 +14,9 @@ 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
NX_SUCCESSOR_MARKETS=false
+1 -3
View File
@@ -13,11 +13,9 @@ 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
NX_SUCCESSOR_MARKETS=false
+1 -4
View File
@@ -10,11 +10,8 @@ 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
NX_SUCCESSOR_MARKETS=true
+1 -4
View File
@@ -15,11 +15,8 @@ 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
NX_SUCCESSOR_MARKETS=true
+1 -4
View File
@@ -12,11 +12,8 @@ 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
NX_SUCCESSOR_MARKETS=false
+1 -1
View File
@@ -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
CYPRESS_NX_SUCCESSOR_MARKETS=true
@@ -259,12 +259,6 @@ describe('Closed markets', { tags: '@smoke' }, () => {
.find('[data-testid="market-code"]')
.should('have.text', settledMarket.tradableInstrument.instrument.code);
// 6001-MARK-071
cy.get(rowSelector)
.first()
.find('[title="Future"]')
.should('have.text', 'Futr');
// 6001-MARK-002
cy.get(rowSelector)
.first()
@@ -69,12 +69,6 @@ describe('markets all table', { tags: '@smoke' }, () => {
.find(colInstrumentCode)
.should('have.text', 'SOLUSD');
// 6001-MARK-073
cy.get(rowSelector)
.first()
.find('[title="Future"]')
.should('have.text', 'Futr');
// 6001-MARK-036
cy.get(rowSelector)
.first()
@@ -0,0 +1,233 @@
import { aliasGQLQuery, checkSorting } from '@vegaprotocol/cypress';
import type { ProposalsListQuery } from '@vegaprotocol/proposals';
const rowSelector =
'[data-testid="tab-proposed-markets"] .ag-center-cols-container .ag-row';
const colMarketId = '[col-id="market"] [data-testid="market-code"]';
describe('markets proposed table', { tags: '@smoke' }, () => {
before(() => {
cy.mockTradingPage();
cy.mockSubscription();
cy.setOnBoardingViewed();
cy.visit('/#/markets/all');
cy.get('[data-testid="Proposed markets"]').click();
});
it('can see table headers', () => {
const headers = [
'Market',
'Description',
'Settlement asset',
'State',
'Parent market',
'Voting',
'Closing date',
'Enactment date',
'',
];
cy.getByTestId('tab-proposed-markets').within(($headers) => {
cy.wrap($headers)
.get('.ag-header-cell-text')
.each(($header, i) => {
cy.wrap($header).should('have.text', headers[i]);
});
});
});
it('renders markets correctly', () => {
// 6001-MARK-049
cy.get(rowSelector).first().find(colMarketId).should('have.text', 'ETHUSD');
// 6001-MARK-050
cy.get(rowSelector)
.first()
.find('[col-id="description"]')
.should('have.text', 'ETHUSD');
// 6001-MARK-051
cy.get(rowSelector)
.first()
.find('[col-id="asset"]')
.should('have.text', 'tDAI TEST');
// 6001-MARK-052
// 6001-MARK-053
cy.get(rowSelector)
.first()
.find('[col-id="state"]')
.should('have.text', 'Open');
// 6001-MARK-054
cy.get(rowSelector)
.first()
.find('[col-id="voting"]')
.should('have.text', '');
// 6001-MARK-056
cy.get(rowSelector)
.first()
.find('[col-id="closing-date"]')
.should('not.be.empty');
// 6001-MARK-057
cy.get(rowSelector)
.first()
.find('[col-id="enactment-date"]')
.should('not.be.empty');
});
it('can open row actions', () => {
// 6001-MARK-058
cy.get('.ag-pinned-right-cols-container')
.find('[col-id="proposal-actions"]')
.first()
.find('button')
.click();
const dropdownContent = '[data-testid="proposal-actions-content"]';
const dropdownContentItem = '[role="menuitem"]';
// 6001-MARK-059
cy.get(dropdownContent)
.find(dropdownContentItem)
.eq(0)
.find('a')
.should('have.text', 'View proposal')
.and(
'have.attr',
'href',
`${Cypress.env(
'VEGA_TOKEN_URL'
)}/proposals/e9ec6d5c46a7e7bcabf9ba7a893fa5a5eeeec08b731f06f7a6eb7bf0e605b829`
);
});
// 6001-MARK-060
it('can see proposed market link', () => {
cy.getByTestId('tab-proposed-markets')
.find('[data-testid="external-link"]')
.should('have.length', 11)
.last()
.should('have.text', 'Propose a new market')
.and(
'have.attr',
'href',
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market`
);
});
it('proposed markets tab should be sorted properly', () => {
// 6001-MARK-062
cy.get('[data-testid="Proposed markets"]').click({ force: true });
const marketColDefault = [
'ETHUSD',
'LINKUSD',
'ETHUSD',
'ETHDAI.MF21',
'AAPL.MF21',
'BTCUSD.MF21',
'TSLA.QM21',
'AAVEDAI.MF21',
'ETHBTC.QM21',
'UNIDAI.MF21',
];
const marketColAsc = [
'AAPL.MF21',
'AAVEDAI.MF21',
'BTCUSD.MF21',
'ETHBTC.QM21',
'ETHDAI.MF21',
'ETHUSD',
'ETHUSD',
'LINKUSD',
'TSLA.QM21',
'UNIDAI.MF21',
];
const marketColDesc = [
'UNIDAI.MF21',
'TSLA.QM21',
'LINKUSD',
'ETHUSD',
'ETHUSD',
'ETHDAI.MF21',
'ETHBTC.QM21',
'BTCUSD.MF21',
'AAVEDAI.MF21',
'AAPL.MF21',
];
checkSorting(
'market',
marketColDefault,
marketColAsc,
marketColDesc,
' [data-testid="market-code"]'
);
const stateColDefault = [
'Open',
'Passed',
'Waiting for Node Vote',
'Open',
'Passed',
'Open',
'Passed',
'Open',
'Waiting for Node Vote',
'Open',
];
const stateColAsc = [
'Open',
'Open',
'Open',
'Open',
'Open',
'Passed',
'Passed',
'Passed',
'Waiting for Node Vote',
'Waiting for Node Vote',
];
const stateColDesc = [
'Waiting for Node Vote',
'Waiting for Node Vote',
'Passed',
'Passed',
'Passed',
'Open',
'Open',
'Open',
'Open',
'Open',
];
checkSorting('state', stateColDefault, stateColAsc, stateColDesc);
});
it('can drag and drop columns', () => {
// 6001-MARK-063
cy.get(colMarketId).realMouseDown().realMouseMove(700, 15).realMouseUp();
cy.get(colMarketId).should(($element) => {
const attributeValue = $element.attr('aria-colindex');
expect(attributeValue).not.to.equal('1');
});
});
});
describe('no markets proposed', { tags: '@smoke', testIsolation: true }, () => {
before(() => {
cy.mockTradingPage();
const proposal: ProposalsListQuery = {};
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ProposalsList', proposal);
});
cy.mockSubscription();
cy.setOnBoardingViewed();
});
it.skip('can see no markets message', () => {
cy.visit('/#/markets/all');
cy.get('[data-testid="Proposed markets"]').click();
// 6001-MARK-061
cy.getByTestId('tab-proposed-markets').should('contain.text', 'No markets');
});
});
@@ -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('order-connect-wallet').should('exist');
cy.getByTestId('get-started-button').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('order-connect-wallet').click();
cy.getByTestId('get-started-button').click();
cy.getByTestId('dialog-content').should('be.visible');
cy.getByTestId('connectors-list')
.find('[data-testid="connector-jsonRpc"]')
@@ -54,15 +54,6 @@ describe('deal ticket basics', { tags: '@smoke' }, () => {
cy.getByTestId(toggleLimit).next('input').should('be.checked');
cy.getByTestId(orderPriceField).should('have.value', '101');
});
it('sidebar should be open after reload', () => {
cy.mockTradingPage();
cy.getByTestId('deal-ticket-form').should('be.visible');
cy.getByTestId('Order').click();
cy.getByTestId('deal-ticket-form').should('not.exist');
cy.reload();
cy.getByTestId('deal-ticket-form').should('be.visible');
});
});
describe(
@@ -222,17 +222,12 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
it('must see a filled order', () => {
// 7002-SORD-046
// 7003-MORD-020
// NOT COVERED: Must be able to see/link to all trades that were created from this order
updateOrder({
id: orderId,
status: Schema.OrderStatus.STATUS_FILLED,
});
cy.getByTestId(`order-status-${orderId}`).should('have.text', 'Filled');
cy.get('[col-id="market.tradableInstrument.instrument.code"]').contains(
'[title="Future"]',
'Futr'
);
});
it('must see a rejected order', () => {
+2 -1
View File
@@ -12,7 +12,8 @@ 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
-2
View File
@@ -12,8 +12,6 @@ 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"
-2
View File
@@ -13,8 +13,6 @@ 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
-2
View File
@@ -13,8 +13,6 @@ 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
-2
View File
@@ -13,8 +13,6 @@ 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
+1 -3
View File
@@ -13,11 +13,9 @@ 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
# NX_PRODUCT_PERPETUALS
+1 -3
View File
@@ -14,8 +14,6 @@ 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
@@ -24,4 +22,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
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
-3
View File
@@ -15,9 +15,6 @@ 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
@@ -94,11 +94,7 @@ const MainGrid = memo(
>
<TradeGridChild>
<Tabs storageKey="console-trade-grid-bottom">
<Tab
id="positions"
name={t('Positions')}
menu={<TradingViews.positions.menu />}
>
<Tab id="positions" name={t('Positions')}>
<TradingViews.positions.component />
</Tab>
<Tab
@@ -17,7 +17,6 @@ import type { OrderContainerProps } from '../../components/orders-container';
import { OrdersContainer } from '../../components/orders-container';
import { StopOrdersContainer } from '../../components/stop-orders-container';
import { AccountsMenu } from '../../components/accounts-menu';
import { PositionsMenu } from '../../components/positions-menu';
type MarketDependantView =
| typeof CandlesChartContainer
@@ -58,11 +57,7 @@ export const TradingViews = {
label: 'Trades',
component: requiresMarket(TradesContainer),
},
positions: {
label: 'Positions',
component: PositionsContainer,
menu: PositionsMenu,
},
positions: { label: 'Positions', component: PositionsContainer },
activeOrders: {
label: 'Active',
component: (props: OrderContainerProps) => (
+8
View File
@@ -1,2 +1,10 @@
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).'
);
@@ -1,4 +1,4 @@
import { Fragment, useState } from 'react';
import { useState } from 'react';
import type {
SuccessorProposalListFieldsFragment,
NewMarketSuccessorFieldsFragment,
@@ -52,7 +52,7 @@ export const MarketSuccessorProposalBanner = ({
TOKEN_PROPOSAL.replace(':id', item.id || '')
);
return (
<Fragment key={i}>
<>
<ExternalLink href={externalLink} key={i}>
{
(item.terms?.change as NewMarketSuccessorFieldsFragment)
@@ -60,7 +60,7 @@ export const MarketSuccessorProposalBanner = ({
}
</ExternalLink>
{i < successors.length - 1 && ', '}
</Fragment>
</>
);
})}
</div>
@@ -3,7 +3,7 @@ import { Header, HeaderTitle } from '../header';
import { useParams } from 'react-router-dom';
import { MarketSelector } from '../../components/market-selector/market-selector';
import { MarketHeaderStats } from '../../client-pages/market/market-header-stats';
import { useMarket, useMarketList } from '@vegaprotocol/markets';
import { useMarket } from '@vegaprotocol/markets';
import { useState } from 'react';
export const MarketHeader = () => {
@@ -11,10 +11,6 @@ export const MarketHeader = () => {
const { data } = useMarket(marketId);
const [open, setOpen] = useState(false);
// Ensure that markets are kept cached so opening the list
// shows all markets instantly
useMarketList();
if (!data) return null;
return (
@@ -132,7 +132,6 @@ describe('MarketSelector', () => {
data: markets,
loading: false,
error: undefined,
reload: jest.fn(),
});
it('Button "All" should be selected by default', () => {
@@ -1,6 +1,6 @@
import { t } from '@vegaprotocol/i18n';
import uniqBy from 'lodash/uniqBy';
import { type MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
import {
TradingInput,
TinyScroll,
@@ -8,7 +8,7 @@ import {
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import type { CSSProperties } from 'react';
import { useCallback, useState, useMemo, useRef, useEffect } from 'react';
import { useCallback, useState, useMemo, useRef } from 'react';
import { FixedSizeList } from 'react-window';
import { useMarketSelectorList } from './use-market-selector-list';
import type { ProductType } from './product-selector';
@@ -44,12 +44,7 @@ export const MarketSelector = ({
assets: [],
});
const allProducts = filter.product === Product.All;
const { markets, data, loading, error, reload } =
useMarketSelectorList(filter);
useEffect(() => {
reload();
}, [reload]);
const { markets, data, loading, error } = useMarketSelectorList(filter);
return (
<div data-testid="market-selector">
@@ -15,7 +15,6 @@ export const Sort = {
Gained: 'Gained',
Lost: 'Lost',
New: 'New',
TopTraded: 'TopTraded',
} as const;
export type SortType = keyof typeof Sort;
@@ -27,7 +26,6 @@ export const SortTypeMapping: {
[Sort.Gained]: 'Top gaining',
[Sort.Lost]: 'Top losing',
[Sort.New]: 'New markets',
[Sort.TopTraded]: 'Top traded',
};
const SortIconMapping: {
@@ -37,7 +35,6 @@ const SortIconMapping: {
[Sort.Gained]: VegaIconNames.TREND_UP,
[Sort.Lost]: VegaIconNames.TREND_DOWN,
[Sort.New]: VegaIconNames.STAR,
[Sort.TopTraded]: VegaIconNames.ARROW_UP,
};
export const SortDropdown = ({
@@ -1,11 +1,7 @@
import { useMemo } from 'react';
import orderBy from 'lodash/orderBy';
import { MarketState } from '@vegaprotocol/types';
import {
calcCandleVolume,
calcTradedFactor,
useMarketList,
} from '@vegaprotocol/markets';
import { calcCandleVolume, useMarketList } from '@vegaprotocol/markets';
import { priceChangePercentage } from '@vegaprotocol/utils';
import type { Filter } from '../../components/market-selector/market-selector';
import { Sort } from './sort-dropdown';
@@ -24,7 +20,7 @@ export const useMarketSelectorList = ({
sort,
searchTerm,
}: Filter) => {
const { data, loading, error, reload } = useMarketList();
const { data, loading, error } = useMarketList();
const markets = useMemo(() => {
if (!data?.length) return [];
@@ -98,14 +94,10 @@ export const useMarketSelectorList = ({
);
}
if (sort === Sort.TopTraded) {
return orderBy(markets, [(m) => calcTradedFactor(m)], ['desc']);
}
return markets;
}, [data, product, searchTerm, assets, sort]);
return { markets, data, loading, error, reload };
return { markets, data, loading, error };
};
export const isMarketActive = (state: MarketState) => {
@@ -1,6 +1,6 @@
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
import { MarketSelector } from '../market-selector';
import { useMarket, useMarketList } from '@vegaprotocol/markets';
import { useMarket } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n';
import { useParams } from 'react-router-dom';
import * as PopoverPrimitive from '@radix-ui/react-popover';
@@ -14,10 +14,6 @@ export const NavHeader = () => {
const { data } = useMarket(marketId);
const [open, setOpen] = useState(false);
// Ensure that markets are kept cached so opening the list
// shows all markets instantly
useMarketList();
if (!marketId) return null;
return (
@@ -5,7 +5,6 @@ import { Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import type { DataGridSlice } from '../../stores/datagrid-store-slice';
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
import type { StateCreator } from 'zustand';
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
@@ -14,7 +13,6 @@ export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
const onMarketClick = useMarketClickHandler(true);
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
const showClosed = usePositionsStore((store) => store.showClosedMarkets);
const gridStore = usePositionsStore((store) => store.gridStore);
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore);
@@ -42,35 +40,12 @@ export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
onMarketClick={onMarketClick}
isReadOnly={isReadOnly}
gridProps={gridStoreCallbacks}
showClosed={showClosed}
/>
);
};
type PositionsStoreSlice = {
showClosedMarkets: boolean;
toggleClosedMarkets: () => void;
};
const createPositionStoreSlice: StateCreator<PositionsStoreSlice> = (set) => ({
showClosedMarkets: false,
toggleClosedMarkets: () => {
set((curr) => {
return {
showClosedMarkets: !curr.showClosedMarkets,
};
});
},
});
export const usePositionsStore = create<PositionsStoreSlice & DataGridSlice>()(
persist(
(...args) => ({
...createPositionStoreSlice(...args),
...createDataGridSlice(...args),
}),
{
name: 'vega_positions_store',
}
)
const usePositionsStore = create<DataGridSlice>()(
persist(createDataGridSlice, {
name: 'vega_positions_store',
})
);
@@ -1 +0,0 @@
export * from './positions-menu';
@@ -1,18 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
import { usePositionsStore } from '../positions-container';
export const PositionsMenu = () => {
const showClosed = usePositionsStore((store) => store.showClosedMarkets);
const toggle = usePositionsStore((store) => store.toggleClosedMarkets);
return (
<TradingButton
intent={Intent.Primary}
size="extra-small"
data-testid="open-transfer"
onClick={toggle}
>
{showClosed ? t('Hide closed markets') : t('Show closed markets')}
</TradingButton>
);
};
+21 -10
View File
@@ -14,9 +14,12 @@ import { Settings } from '../settings';
import { Tooltip } from '../../components/tooltip';
import { WithdrawContainer } from '../withdraw-container';
import { Routes as AppRoutes } from '../../pages/client-router';
import { persist } from 'zustand/middleware';
import { GetStarted } from '../welcome-dialog';
import { useVegaWallet, useViewAsDialog } from '@vegaprotocol/wallet';
const STORAGE_KEY = 'vega_sidebar_store';
export enum ViewType {
Order = 'Order',
Info = 'Info',
@@ -299,14 +302,22 @@ export const useSidebar = create<{
init: boolean;
view: SidebarView | null;
setView: (view: SidebarView | null) => void;
}>()((set) => ({
init: true,
view: null,
setView: (x) =>
set(() => {
if (x == null) {
return { view: null, init: false };
}
return { view: x, init: false };
}>()(
persist(
(set) => ({
init: true,
view: null,
setView: (x) =>
set(() => {
if (x == null) {
return { view: null, init: false };
}
return { view: x, init: false };
}),
}),
}));
{
name: STORAGE_KEY,
}
)
);
@@ -1,36 +1,16 @@
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<VegaWalletContextShape> = {}) => {
return render(
<MemoryRouter>
<VegaWalletContext.Provider value={context as VegaWalletContextShape}>
<GetStarted />
</VegaWalletContext.Provider>
</MemoryRouter>
<VegaWalletContext.Provider value={context as VegaWalletContextShape}>
<GetStarted />
</VegaWalletContext.Provider>
);
};
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();
@@ -40,71 +20,12 @@ describe('GetStarted', () => {
it('renders connect prompt if no pubKey but wallet installed', () => {
globalThis.window.vega = {} as Vega;
renderComponent();
expect(screen.getByTestId('get-started-banner')).toBeInTheDocument();
expect(screen.getByTestId('order-connect-wallet')).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(
<MemoryRouter>
<VegaWalletContext.Provider value={{} as VegaWalletContextShape}>
<GetStarted />
</VegaWalletContext.Provider>
</MemoryRouter>
);
checkTicks(screen.getAllByRole('listitem'));
expect(screen.getByRole('button', { name: 'Connect' })).toBeInTheDocument();
mockStep = 3;
rerender(
<MemoryRouter>
<VegaWalletContext.Provider value={{} as VegaWalletContextShape}>
<GetStarted />
</VegaWalletContext.Provider>
</MemoryRouter>
);
checkTicks(screen.getAllByRole('listitem'));
expect(screen.getByRole('button', { name: 'Deposit' })).toBeInTheDocument();
mockStep = 4;
rerender(
<MemoryRouter>
<VegaWalletContext.Provider value={{} as VegaWalletContextShape}>
<GetStarted />
</VegaWalletContext.Provider>
</MemoryRouter>
);
checkTicks(screen.getAllByRole('listitem'));
expect(screen.getByRole('button', { name: 'Dismiss' })).toBeInTheDocument();
mockStep = 5;
rerender(
<MemoryRouter>
<VegaWalletContext.Provider
value={{ pubKey: 'my-pubkey' } as VegaWalletContextShape}
>
<GetStarted />
</VegaWalletContext.Provider>
</MemoryRouter>
);
expect(container).toBeEmptyDOMElement();
});
});
@@ -1,96 +1,36 @@
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;
}
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 <GetWalletButton className="justify-between" />;
} 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 (
<TradingButton
onClick={onClickHandle}
size="small"
data-testid="get-started-button"
intent={Intent.Info}
>
{buttonText}
</TradingButton>
);
};
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 [, setOnboardingViewed] = useLocalStorage(
constants.ONBOARDING_VIEWED_KEY
);
const openVegaWalletDialog = useVegaWalletDialogStore(
(store) => store.openVegaWalletDialog
);
const getStartedNeeded =
onBoardingViewed !== 'true' &&
currentStep &&
currentStep < OnboardingStep.ONBOARDING_COMPLETE_STEP;
const onButtonClick = () => {
openVegaWalletDialog();
setOnboardingViewed('true');
};
const wrapperClasses = classNames(
'flex flex-col py-4 px-6 gap-4 rounded',
@@ -99,48 +39,27 @@ export const GetStarted = ({ lead }: Props) => {
{ 'mt-8': !lead }
);
if (getStartedNeeded) {
if (!pubKey && !isBrowserWalletInstalled()) {
return (
<div className={wrapperClasses} data-testid="get-started-banner">
{lead && <h2>{lead}</h2>}
<h3 className="text-lg">{t('Get started')}</h3>
<div>
<ul className="list-inside -ml-5" role="list">
<li className="flex">
<div className="w-5">
{currentStep > OnboardingStep.ONBOARDING_WALLET_STEP && (
<VegaIcon name={VegaIconNames.TICK} size={20} />
)}
</div>
<div className="ml-1">1. {t('Get a Vega wallet')}</div>
</li>
<li className="flex">
<div className="w-5">
{(currentStep > OnboardingStep.ONBOARDING_CONNECT_STEP ||
pubKey) && <VegaIcon name={VegaIconNames.TICK} size={20} />}
</div>
<div className="ml-1">2. {t('Connect')}</div>
</li>
<li className="flex">
<div className="w-5">
{currentStep > OnboardingStep.ONBOARDING_DEPOSIT_STEP && (
<VegaIcon name={VegaIconNames.TICK} size={20} />
)}
</div>
<div className="ml-1">3. {t('Deposit funds')}</div>
</li>
<li className="flex">
<div className="w-5">
{currentStep > OnboardingStep.ONBOARDING_ORDER_STEP && (
<VegaIcon name={VegaIconNames.TICK} size={20} />
)}
</div>
<div className="ml-1">4. {t('Open a position')}</div>
</li>
<ul className="list-decimal list-inside">
<li>{t('Get a Vega wallet')}</li>
<li>{t('Connect')}</li>
<li>{t('Deposit funds')}</li>
<li>{t('Open a position')}</li>
</ul>
</div>
<div>
<GetStartedButton step={currentStep} />
<TradingButton
intent={Intent.Info}
onClick={onButtonClick}
data-testid="get-started-button"
>
{t('Get started')}
</TradingButton>
</div>
{VEGA_ENV === Networks.MAINNET && (
<p className="text-sm">
@@ -1,97 +0,0 @@
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<VegaWalletContextShape> = { 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 }) => (
<VegaWalletContext.Provider
value={mockContext as unknown as VegaWalletContextShape}
>
{children}
</VegaWalletContext.Provider>
);
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
);
});
});
@@ -1,82 +0,0 @@
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;
};
@@ -3,19 +3,21 @@ 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 update = useGlobalStore((store) => store.update);
const [, setOnboardingViewed] = useLocalStorage(
constants.ONBOARDING_VIEWED_KEY
);
const navigate = useNavigate();
const browseMarkets = () => {
const link = Links[Routes.MARKETS]();
navigate(link);
update({ onBoardingDismissed: true });
setOnboardingViewed('true');
};
const lead =
VEGA_ENV === Networks.MAINNET
@@ -55,7 +57,7 @@ export const WelcomeDialogContent = () => {
{t('Browse the markets')}
</TradingButton>
</div>
<div className="sm:w-1/2 flex grow">
<div className="sm:w-1/2">
<GetStarted lead={lead} />
</div>
</div>
@@ -2,38 +2,31 @@ import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { useEnvironment } from '@vegaprotocol/environment';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { useEnvironment } from '@vegaprotocol/environment';
import { isBrowserWalletInstalled } from '@vegaprotocol/wallet';
import * as constants from '../constants';
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] = useLocalStorage(constants.ONBOARDING_VIEWED_KEY);
const update = useGlobalStore((store) => store.update);
const dismissed = useGlobalStore((store) => store.onBoardingDismissed);
const currentStep = useGetOnboardingStep();
const [onBoardingViewed, setOnboardingViewed] = useLocalStorage(
constants.ONBOARDING_VIEWED_KEY
);
const navigate = useNavigate();
const isOnboardingDialogNeeded =
onBoardingViewed !== 'true' &&
currentStep &&
currentStep < OnboardingStep.ONBOARDING_COMPLETE_STEP &&
!dismissed;
onBoardingViewed !== 'true' && !isBrowserWalletInstalled() && !getConfig();
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 = (
<span className="font-alpha calt" data-testid="welcome-title">
+3 -7
View File
@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from 'react';
import { 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 { useGlobalStore, usePageTitleStore } from '../stores';
import { usePageTitleStore } from '../stores';
import DialogsContainer from './dialogs-container';
import ToastsManager from './toasts-manager';
import {
@@ -170,8 +170,7 @@ const PartyData = () => {
const MaybeConnectEagerly = () => {
const { VEGA_ENV, SENTRY_DSN } = useEnvironment();
const update = useGlobalStore((store) => store.update);
const eagerConnecting = useVegaEagerConnect(Connectors);
useVegaEagerConnect(Connectors);
const [isTelemetryApproved] = useTelemetryApproval();
useEthereumEagerConnect(
isTelemetryApproved ? { dsn: SENTRY_DSN, env: VEGA_ENV } : {}
@@ -183,8 +182,5 @@ const MaybeConnectEagerly = () => {
if (query && !pubKey) {
connect(Connectors['view']);
}
useEffect(() => {
update({ eagerConnecting });
}, [update, eagerConnecting]);
return null;
};
+39 -9
View File
@@ -1,10 +1,40 @@
import { Head, Html, Main, NextScript } from 'next/document';
import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
return (
<>
<Html>
<Head>
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charSet="utf-8" />
<link
rel="icon"
type="image/x-icon"
href="https://static.vega.xyz/favicon.ico"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Vega Protocol - VEGA Console" />
<meta name="og:type" content="website" />
<meta name="og:url" content="https://console.vega.xyz/" />
<meta name="og:title" content="Vega Protocol - Console" />
<meta name="og:site_name" content="Vega Protocol - Console" />
<meta name="og:image" content="https://static.vega.xyz/favicon.ico" />
<meta
name="twitter:card"
content="https://static.vega.xyz/favicon.ico"
/>
<meta name="twitter:title" content="Vega Protocol - Console" />
<meta name="twitter:description" content="Vega Protocol - Console" />
<meta
name="twitter:image"
content="https://static.vega.xyz/favicon.ico"
/>
<meta name="twitter:image:alt" content="VEGA logo" />
<meta name="twitter:site" content="@vegaprotocol" />
<meta name="description" content="Vega Protocol - Console" />
<link
rel="apple-touch-icon"
content="https://static.vega.xyz/favicon.ico"
@@ -15,6 +45,8 @@ export default function Document() {
as="font"
type="font/woff2"
/>
{/* eslint-disable-next-line @next/next/no-css-tags */}
<link rel="stylesheet" href="/preloader.css" media="all" />
<link
rel="icon"
type="image/x-icon"
@@ -22,12 +54,10 @@ export default function Document() {
/>
<script src="/theme-setter.js" type="text/javascript" async />
</Head>
<Html>
<body className="bg-white dark:bg-vega-cdark-900 text-default font-alpha">
<Main />
<NextScript />
</body>
</Html>
</>
<body className="bg-white dark:bg-vega-cdark-900 text-default font-alpha">
<Main />
<NextScript />
</body>
</Html>
);
}
+1 -57
View File
@@ -1,4 +1,3 @@
import Head from 'next/head';
import { ClientRouter } from './client-router';
/**
@@ -7,60 +6,5 @@ import { ClientRouter } from './client-router';
* have to serve a static site via next export
*/
export default function Index() {
return (
<>
<Head>
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charSet="utf-8" />
<link
rel="icon"
type="image/x-icon"
href="https://static.vega.xyz/favicon.ico"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Vega Protocol - VEGA Console" />
<meta name="og:type" content="website" />
<meta name="og:url" content="https://console.vega.xyz/" />
<meta name="og:title" content="Vega Protocol - Console" />
<meta name="og:site_name" content="Vega Protocol - Console" />
<meta name="og:image" content="https://static.vega.xyz/favicon.ico" />
<meta
name="twitter:card"
content="https://static.vega.xyz/favicon.ico"
/>
<meta name="twitter:title" content="Vega Protocol - Console" />
<meta name="twitter:description" content="Vega Protocol - Console" />
<meta
name="twitter:image"
content="https://static.vega.xyz/favicon.ico"
/>
<meta name="twitter:image:alt" content="VEGA logo" />
<meta name="twitter:site" content="@vegaprotocol" />
<meta name="description" content="Vega Protocol - Console" />
<link
rel="apple-touch-icon"
content="https://static.vega.xyz/favicon.ico"
/>
<link
rel="preload"
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
as="font"
type="font/woff2"
/>
{/* eslint-disable-next-line @next/next/no-css-tags */}
<link rel="stylesheet" href="/preloader.css" media="all" />
<link
rel="icon"
type="image/x-icon"
href="https://static.vega.xyz/favicon.ico"
/>
<script src="/theme-setter.js" type="text/javascript" async />
</Head>
<ClientRouter />
</>
);
return <ClientRouter />;
}
-4
View File
@@ -4,8 +4,6 @@ import produce from 'immer';
interface GlobalStore {
marketId: string | null;
onBoardingDismissed: boolean;
eagerConnecting: boolean;
update: (store: Partial<Omit<GlobalStore, 'update'>>) => void;
}
@@ -16,8 +14,6 @@ interface PageTitleStore {
export const useGlobalStore = create<GlobalStore>()((set) => ({
marketId: LocalStorage.getItem('marketId') || null,
onBoardingDismissed: false,
eagerConnecting: false,
update: (newState) => {
set(
produce((state: GlobalStore) => {
+1 -5
View File
@@ -1,8 +1,4 @@
{
"name": "@vegaprotocol/announcements",
"version": "0.0.2",
"peerDependencies": {
"react": "18.2.0",
"react-dom": "18.2.0"
}
"version": "0.0.2"
}
+2 -55
View File
@@ -1,10 +1,6 @@
import * as Schema from '@vegaprotocol/types';
import type { Market, MarketMaybeWithDataAndCandles } from './markets-provider';
import {
calcTradedFactor,
filterAndSortMarkets,
totalFeesPercentage,
} from './market-utils';
import type { Market } from './markets-provider';
import { filterAndSortMarkets, totalFeesPercentage } from './market-utils';
const { MarketState, MarketTradingMode } = Schema;
const MARKET_A: Partial<Market> = {
@@ -81,52 +77,3 @@ describe('totalFees', () => {
expect(totalFeesPercentage(i)).toEqual(o);
});
});
describe('calcTradedFactor', () => {
const marketA = {
data: {
markPrice: '10',
},
candles: [
{
volume: '1000',
},
],
tradableInstrument: {
instrument: {
product: {
settlementAsset: {
decimals: 18,
quantum: '1000000000000000000', // 1
},
},
},
},
};
const marketB = {
data: {
markPrice: '10',
},
candles: [
{
volume: '1000',
},
],
tradableInstrument: {
instrument: {
product: {
settlementAsset: {
decimals: 18,
quantum: '1', // 0.0000000000000000001
},
},
},
},
};
it('a is "traded" more than b', () => {
const fa = calcTradedFactor(marketA as MarketMaybeWithDataAndCandles);
const fb = calcTradedFactor(marketB as MarketMaybeWithDataAndCandles);
// it should be true because market a's asset is "more valuable" than b's
expect(fa > fb).toBeTruthy();
});
});
+2 -22
View File
@@ -1,13 +1,8 @@
import { formatNumberPercentage, toBigNum } from '@vegaprotocol/utils';
import { formatNumberPercentage } from '@vegaprotocol/utils';
import * as Schema from '@vegaprotocol/types';
import BigNumber from 'bignumber.js';
import orderBy from 'lodash/orderBy';
import type {
Market,
Candle,
MarketMaybeWithData,
MarketMaybeWithDataAndCandles,
} from '../';
import type { Market, Candle, MarketMaybeWithData } from '../';
const { MarketState, MarketTradingMode } = Schema;
export const totalFees = (fees: Market['fees']['factors']) => {
@@ -91,18 +86,3 @@ export const calcCandleHigh = (candles: Candle[]): string | undefined => {
export const calcCandleVolume = (candles: Candle[]): string | undefined =>
candles &&
candles.reduce((acc, c) => new BigNumber(acc).plus(c.volume).toString(), '0');
export const calcTradedFactor = (m: MarketMaybeWithDataAndCandles) => {
const volume = Number(calcCandleVolume(m.candles || []) || 0);
const price = m.data?.markPrice ? Number(m.data.markPrice) : 0;
const quantum = Number(
m.tradableInstrument.instrument.product.settlementAsset.quantum
);
const decimals = Number(
m.tradableInstrument.instrument.product.settlementAsset.decimals
);
const fp = toBigNum(price, decimals);
const fq = toBigNum(quantum, decimals);
const factor = fq.multipliedBy(fp).multipliedBy(volume);
return factor.toNumber();
};
@@ -128,9 +128,6 @@ fragment StopOrderFields on StopOrder {
updatedAt
partyId
marketId
order {
...OrderFields
}
trigger {
... on StopOrderPrice {
price
@@ -34,51 +34,22 @@ export type OrdersUpdateSubscription = { __typename?: 'Subscription', orders?: A
export type OrderSubmissionFieldsFragment = { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null };
export type StopOrderFieldsFragment = { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, order?: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, icebergOrder?: { __typename: 'IcebergOrder', peakSize: string, minimumVisibleSize: string, reservedRemaining: string } | null } | null, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } };
export type StopOrderFieldsFragment = { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } };
export type StopOrdersQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type StopOrdersQuery = { __typename?: 'Query', stopOrders?: { __typename?: 'StopOrderConnection', edges?: Array<{ __typename?: 'StopOrderEdge', node?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, order?: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, icebergOrder?: { __typename: 'IcebergOrder', peakSize: string, minimumVisibleSize: string, reservedRemaining: string } | null } | null, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null }> | null } | null };
export type StopOrdersQuery = { __typename?: 'Query', stopOrders?: { __typename?: 'StopOrderConnection', edges?: Array<{ __typename?: 'StopOrderEdge', node?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null }> | null } | null };
export type StopOrderByIdQueryVariables = Types.Exact<{
stopOrderId: Types.Scalars['ID'];
}>;
export type StopOrderByIdQuery = { __typename?: 'Query', stopOrder?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, order?: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, icebergOrder?: { __typename: 'IcebergOrder', peakSize: string, minimumVisibleSize: string, reservedRemaining: string } | null } | null, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null };
export type StopOrderByIdQuery = { __typename?: 'Query', stopOrder?: { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } } | null };
export const OrderUpdateFieldsFragmentDoc = gql`
fragment OrderUpdateFields on OrderUpdate {
id
marketId
type
side
size
status
rejectionReason
price
timeInForce
remaining
expiresAt
createdAt
updatedAt
liquidityProvisionId
peggedOrder {
__typename
reference
offset
}
icebergOrder {
__typename
peakSize
minimumVisibleSize
reservedRemaining
}
}
`;
export const OrderFieldsFragmentDoc = gql`
fragment OrderFields on Order {
id
@@ -114,6 +85,35 @@ export const OrderFieldsFragmentDoc = gql`
}
}
`;
export const OrderUpdateFieldsFragmentDoc = gql`
fragment OrderUpdateFields on OrderUpdate {
id
marketId
type
side
size
status
rejectionReason
price
timeInForce
remaining
expiresAt
createdAt
updatedAt
liquidityProvisionId
peggedOrder {
__typename
reference
offset
}
icebergOrder {
__typename
peakSize
minimumVisibleSize
reservedRemaining
}
}
`;
export const OrderSubmissionFieldsFragmentDoc = gql`
fragment OrderSubmissionFields on OrderSubmission {
marketId
@@ -144,9 +144,6 @@ export const StopOrderFieldsFragmentDoc = gql`
updatedAt
partyId
marketId
order {
...OrderFields
}
trigger {
... on StopOrderPrice {
price
@@ -159,8 +156,7 @@ export const StopOrderFieldsFragmentDoc = gql`
...OrderSubmissionFields
}
}
${OrderFieldsFragmentDoc}
${OrderSubmissionFieldsFragmentDoc}`;
${OrderSubmissionFieldsFragmentDoc}`;
export const OrderByIdDocument = gql`
query OrderById($orderId: ID!) {
orderByID(id: $orderId) {
@@ -296,7 +296,7 @@ export const OrderListTable = memo<
</ButtonLink>
</>
)}
<ActionsDropdown data-testid="order-actions-content">
<ActionsDropdown data-testid="market-actions-content">
<TradingDropdownCopyItem
value={data.id}
text={t('Copy order ID')}
@@ -1,13 +1,11 @@
import { t } from '@vegaprotocol/i18n';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect } from 'react';
import { StopOrdersTable } from '../stop-orders-table/stop-orders-table';
import type { useDataGridEvents } from '@vegaprotocol/datagrid';
import { useVegaTransactionStore } from '@vegaprotocol/wallet';
import type { StopOrder } from '../order-data-provider/stop-orders-data-provider';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { stopOrdersWithMarketProvider } from '../order-data-provider/stop-orders-data-provider';
import { OrderViewDialog } from '../order-list/order-view-dialog';
import type { Order } from '../order-data-provider';
export interface StopOrdersManagerProps {
partyId: string;
@@ -25,7 +23,6 @@ export const StopOrdersManager = ({
gridProps,
}: StopOrdersManagerProps) => {
const create = useVegaTransactionStore((state) => state.create);
const [viewOrder, setViewOrder] = useState<Order | null>(null);
const variables = { partyId };
const { data, error, reload } = useDataProvider({
@@ -56,25 +53,14 @@ export const StopOrdersManager = ({
);
return (
<>
<StopOrdersTable
rowData={data}
onCancel={cancel}
onView={setViewOrder}
onMarketClick={onMarketClick}
isReadOnly={isReadOnly}
suppressAutoSize
overlayNoRowsTemplate={error ? error.message : t('No stop orders')}
{...gridProps}
/>
{viewOrder && (
<OrderViewDialog
isOpen={Boolean(viewOrder)}
order={viewOrder}
onChange={() => setViewOrder(null)}
onMarketClick={onMarketClick}
/>
)}
</>
<StopOrdersTable
rowData={data}
onCancel={cancel}
onMarketClick={onMarketClick}
isReadOnly={isReadOnly}
suppressAutoSize
overlayNoRowsTemplate={error ? error.message : t('No stop orders')}
{...gridProps}
/>
);
};
@@ -4,7 +4,6 @@ import type { PartialDeep } from 'type-fest';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import { MockedProvider } from '@apollo/client/testing';
import userEvent from '@testing-library/user-event';
import {
StopOrdersTable,
type StopOrdersTableProps,
@@ -28,7 +27,6 @@ jest.mock('@vegaprotocol/utils', () => ({
}));
const defaultProps: StopOrdersTableProps = {
onView: jest.fn(),
rowData: [],
onCancel: jest.fn(),
isReadOnly: false,
@@ -106,7 +104,6 @@ const rowData = [
generateStopOrder({
id: 'stop-order-6',
status: Schema.StopOrderStatus.STATUS_TRIGGERED,
order: { id: 'order-id' },
}),
];
@@ -237,37 +234,4 @@ describe('StopOrdersTable', () => {
);
});
});
it('shows actions dropdown only for triggered stop orders', async () => {
await act(async () => {
render(generateJsx({ rowData }));
});
const dropdownMenuButtons = screen.getAllByTestId('dropdown-menu');
expect(dropdownMenuButtons).toHaveLength(1);
dropdownMenuButtons.forEach((dropdownMenuButton) => {
const id = dropdownMenuButton
.closest('[role="row"]')
?.getAttribute('row-id');
expect(rowData.find((row) => row.id === id)?.status).toEqual(
Schema.StopOrderStatus.STATUS_TRIGGERED
);
});
});
it('action dropdown has copy and view order actions', async () => {
const onView = jest.fn();
const user = userEvent.setup();
await act(async () => {
render(generateJsx({ rowData, onView }));
});
const dropdownMenuButtons = screen.getByTestId('dropdown-menu');
dropdownMenuButtons.click();
await user.click(dropdownMenuButtons as HTMLButtonElement);
const menuItems = screen.getAllByRole('menuitem');
expect(menuItems).toHaveLength(2);
expect(menuItems[0]).toHaveTextContent('Copy order ID');
expect(menuItems[1]).toHaveTextContent('View order details');
menuItems[1].click();
expect(onView).toBeCalled();
});
});
@@ -7,14 +7,7 @@ import {
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import * as Schema from '@vegaprotocol/types';
import {
ActionsDropdown,
ButtonLink,
VegaIcon,
VegaIconNames,
DropdownMenuItem,
TradingDropdownCopyItem,
} from '@vegaprotocol/ui-toolkit';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { ForwardedRef } from 'react';
import { memo, useMemo } from 'react';
import {
@@ -35,7 +28,6 @@ import type {
import type { AgGridReact } from 'ag-grid-react';
import type { StopOrder } from '../order-data-provider/stop-orders-data-provider';
import type { ColDef } from 'ag-grid-community';
import type { Order } from '../order-data-provider';
const defaultColDef = {
resizable: true,
@@ -46,13 +38,12 @@ const defaultColDef = {
export type StopOrdersTableProps = TypedDataAgGrid<StopOrder> & {
onCancel: (order: StopOrder) => void;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
onView: (order: Order) => void;
isReadOnly: boolean;
};
export const StopOrdersTable = memo<
StopOrdersTableProps & { ref?: ForwardedRef<AgGridReact> }
>(({ onCancel, onView, onMarketClick, ...props }: StopOrdersTableProps) => {
>(({ onCancel, onMarketClick, ...props }: StopOrdersTableProps) => {
const showAllActions = !props.isReadOnly;
const columnDefs: ColDef[] = useMemo(
() => [
@@ -245,32 +236,12 @@ export const StopOrdersTable = memo<
{t('Cancel')}
</ButtonLink>
)}
{data.status === Schema.StopOrderStatus.STATUS_TRIGGERED &&
data.order && (
<ActionsDropdown data-testid="stop-order-actions-content">
<TradingDropdownCopyItem
value={data.order.id}
text={t('Copy order ID')}
/>
<DropdownMenuItem
key={'view-order'}
data-testid="view-order"
onClick={() =>
data.order &&
onView({ ...data.order, market: data.market })
}
>
<VegaIcon name={VegaIconNames.INFO} size={16} />
{t('View order details')}
</DropdownMenuItem>
</ActionsDropdown>
)}
</div>
);
},
},
],
[onCancel, onMarketClick, onView, props.isReadOnly, showAllActions]
[onCancel, onMarketClick, props.isReadOnly, showAllActions]
);
return (
@@ -2,12 +2,7 @@ import * as Schema from '@vegaprotocol/types';
import type { Account } from '@vegaprotocol/accounts';
import type { MarketWithData } from '@vegaprotocol/markets';
import type { PositionFieldsFragment } from './__generated__/Positions';
import type { Position } from './positions-data-providers';
import {
getMetrics,
preparePositions,
rejoinPositionData,
} from './positions-data-providers';
import { getMetrics, rejoinPositionData } from './positions-data-providers';
import { PositionStatus } from '@vegaprotocol/types';
const accounts = [
@@ -228,29 +223,4 @@ describe('getMetrics && rejoinPositionData', () => {
);
expect(metrics[1].status).toEqual(positions[1].positionStatus);
});
it('sorts and filters positions', () => {
const createPosition = (override?: Partial<Position>) =>
({
marketState: Schema.MarketState.STATE_ACTIVE,
marketCode: 'a',
...override,
} as Position);
const data = [
createPosition(),
createPosition({
marketCode: 'c',
marketState: Schema.MarketState.STATE_CANCELLED,
}),
createPosition({ marketCode: 'd' }),
createPosition({ marketCode: 'b' }),
];
const withoutClosed = preparePositions(data, false);
expect(withoutClosed.map((p) => p.marketCode)).toEqual(['a', 'b', 'd']);
const withClosed = preparePositions(data, true);
expect(withClosed.map((p) => p.marketCode)).toEqual(['a', 'b', 'c', 'd']);
});
});
@@ -41,7 +41,6 @@ export interface Position {
marketId: string;
marketCode: string;
marketTradingMode: Schema.MarketTradingMode;
marketState: Schema.MarketState;
markPrice: string | undefined;
notional: string | undefined;
openVolume: string;
@@ -120,7 +119,6 @@ export const getMetrics = (
marketId: market.id,
marketCode: market.tradableInstrument.instrument.code,
marketTradingMode: market.tradingMode,
marketState: market.state,
markPrice: marketData ? marketData.markPrice : undefined,
notional: notional
? notional.multipliedBy(10 ** marketDecimalPlaces).toFixed(0)
@@ -181,7 +179,7 @@ const getSubscriptionVariables = (
): PositionsSubscriptionSubscriptionVariables[] =>
([] as string[]).concat(variables.partyIds).map((partyId) => ({ partyId }));
export const positionsDataProvider = makeDataProvider<
const positionsDataProvider = makeDataProvider<
PositionsQuery,
PositionFieldsFragment[],
PositionsSubscriptionSubscription,
@@ -250,26 +248,6 @@ export const rejoinPositionData = (
return null;
};
export const preparePositions = (metrics: Position[], showClosed: boolean) => {
return sortBy(metrics, 'marketCode').filter((p) => {
if (showClosed) {
return true;
}
if (
[
Schema.MarketState.STATE_ACTIVE,
Schema.MarketState.STATE_PENDING,
Schema.MarketState.STATE_SUSPENDED,
].includes(p.marketState)
) {
return true;
}
return false;
});
};
export const positionsMarketsProvider = makeDerivedDataProvider<
string[],
never,
@@ -287,7 +265,7 @@ export const positionsMarketsProvider = makeDerivedDataProvider<
export const positionsMetricsProvider = makeDerivedDataProvider<
Position[],
Position[],
PositionsQueryVariables & { marketIds: string[]; showClosed: boolean }
PositionsQueryVariables & { marketIds: string[] }
>(
[
(callback, client, variables) =>
@@ -303,10 +281,10 @@ export const positionsMetricsProvider = makeDerivedDataProvider<
marketIds: variables.marketIds,
}),
],
([positions, accounts, marketsData], variables) => {
([positions, accounts, marketsData]) => {
const positionsData = rejoinPositionData(positions, marketsData);
const metrics = getMetrics(positionsData, accounts as Account[] | null);
return preparePositions(metrics, variables.showClosed);
return sortBy(metrics, 'marketCode');
},
(data, delta, previousData) =>
data.filter((row) => {
+2 -4
View File
@@ -16,7 +16,6 @@ interface PositionsManagerProps {
onMarketClick?: (marketId: string) => void;
isReadOnly: boolean;
gridProps?: ReturnType<typeof useDataGridEvents>;
showClosed?: boolean;
}
export const PositionsManager = ({
@@ -24,7 +23,6 @@ export const PositionsManager = ({
onMarketClick,
isReadOnly,
gridProps,
showClosed = false,
}: PositionsManagerProps) => {
const { pubKeys, pubKey } = useVegaWallet();
const create = useVegaTransactionStore((store) => store.create);
@@ -62,7 +60,7 @@ export const PositionsManager = ({
const { data, error } = useDataProvider({
dataProvider: positionsMetricsProvider,
variables: { partyIds, marketIds: marketIds || [], showClosed },
variables: { partyIds, marketIds: marketIds || [] },
skip: !marketIds,
});
@@ -70,7 +68,7 @@ export const PositionsManager = ({
<PositionsTable
pubKey={pubKey}
pubKeys={pubKeys}
rowData={data}
rowData={error ? [] : data}
onMarketClick={onMarketClick}
onClose={onClose}
isReadOnly={isReadOnly}
@@ -27,7 +27,6 @@ const singleRow: Position = {
marketId: 'string',
marketCode: 'ETHBTC.QM21',
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketState: Schema.MarketState.STATE_ACTIVE,
markPrice: '123',
notional: '12300',
openVolume: '100',
+2 -2
View File
@@ -473,8 +473,8 @@ export const PositionsTable = ({
</div>
);
},
minWidth: 55,
maxWidth: 55,
minWidth: 75,
maxWidth: 75,
}
: null,
];
@@ -17,17 +17,4 @@ export const proposalsDataProvider = makeDataProvider<
never,
never,
ProposalsListQueryVariables
>({
query: ProposalsListDocument,
getData,
/**
* Ignores errors for not found settlement asset for NewMarket proposals.
*
* It can happen that a NewMarket proposal is incomplete and does not contain
* `futureProduct` details. This guard protects against that.
*
* GQL Path: `terms.change.instrument.futureProduct.settlementAsset`
*/
errorPolicyGuard: (errors) =>
errors.every((e) => e.message.match(/failed to get asset for ID/)),
});
>({ query: ProposalsListDocument, getData });
+1 -5
View File
@@ -1,8 +1,4 @@
{
"name": "@vegaprotocol/react-helpers",
"version": "0.2.5",
"peerDependencies": {
"react": "18.2.0",
"react-dom": "18.2.0"
}
"version": "0.2.5"
}
+1 -1
View File
@@ -1,4 +1,4 @@
{
"name": "@vegaprotocol/types",
"version": "0.0.5"
"version": "0.0.4"
}
+1 -5
View File
@@ -1,8 +1,4 @@
{
"name": "@vegaprotocol/ui-toolkit",
"version": "0.12.8",
"peerDependencies": {
"react": "18.2.0",
"react-dom": "18.2.0"
}
"version": "0.12.7"
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "@vegaprotocol/utils",
"version": "0.0.8",
"version": "0.0.7",
"type": "commonjs"
}
@@ -204,7 +204,6 @@ const ConnectorList = ({
setWalletUrl: (value: string) => void;
isDesktopWalletRunning: boolean | null;
}) => {
const { pubKey } = useVegaWallet();
const title = isBrowserWalletInstalled()
? t('Connect Vega wallet')
: t('Get a Vega wallet');
@@ -235,7 +234,7 @@ const ConnectorList = ({
onClick={() => onSelect('injected')}
/>
) : (
<GetWalletButton />
<GetWallet />
)}
</div>
<div>
@@ -243,7 +242,6 @@ const ConnectorList = ({
type="view"
text={t('View as party')}
onClick={() => onSelect('view')}
disabled={Boolean(pubKey)}
/>
</div>
<div className="last:mb-0">
@@ -320,7 +318,7 @@ const SelectedForm = ({
throw new Error('No connector selected');
};
export const GetWalletButton = ({ className }: { className?: string }) => {
const GetWallet = () => {
const { MOZILLA_EXTENSION_URL, CHROME_EXTENSION_URL } = useEnvironment();
const isItChrome = window.navigator.userAgent.includes('Chrome');
const isItMozilla =
@@ -349,13 +347,10 @@ export const GetWalletButton = ({ className }: { className?: string }) => {
return !isItChrome && !isItMozilla ? (
<div
className={classNames(
[
'bg-vega-blue-350 hover:bg-vega-blue-400 dark:bg-vega-blue-650 dark:hover:bg-vega-blue-600',
'flex gap-2 items-center justify-center rounded h-8 px-3 relative',
],
className
)}
className={classNames([
'bg-vega-blue-350 hover:bg-vega-blue-400 dark:bg-vega-blue-650 dark:hover:bg-vega-blue-600',
'flex gap-2 items-center justify-center rounded h-8 px-3 relative',
])}
data-testid="get-wallet-button"
>
{buttonContent}
@@ -365,7 +360,7 @@ export const GetWalletButton = ({ className }: { className?: string }) => {
onClick={onClick}
intent={Intent.Info}
data-testid="get-wallet-button"
className={classNames('relative', className)}
className="relative"
size="small"
fill
>
@@ -414,7 +409,6 @@ const CustomUrlInput = ({
isDesktopWalletRunning: boolean | null;
onSelect: (type: WalletType) => void;
}) => {
const { pubKey } = useVegaWallet();
const [urlInputExpanded, setUrlInputExpanded] = useState(false);
return urlInputExpanded ? (
<>
@@ -439,7 +433,7 @@ const CustomUrlInput = ({
/>
</TradingFormGroup>
<ConnectionOption
disabled={!isDesktopWalletRunning || Boolean(pubKey)}
disabled={!isDesktopWalletRunning}
type="jsonRpc"
text={t('Connect the App/CLI')}
onClick={() => onSelect('jsonRpc')}
@@ -448,7 +442,7 @@ const CustomUrlInput = ({
) : (
<>
<ConnectionOption
disabled={!isDesktopWalletRunning || Boolean(pubKey)}
disabled={!isDesktopWalletRunning}
type="jsonRpc"
text={t('Use the Desktop App/CLI')}
onClick={() => onSelect('jsonRpc')}
@@ -459,7 +453,6 @@ const CustomUrlInput = ({
<button
className="underline text-default"
onClick={() => setUrlInputExpanded(true)}
disabled={Boolean(pubKey)}
>
{t('Enter a custom wallet location')}{' '}
<VegaIcon name={VegaIconNames.ARROW_RIGHT} />
@@ -474,7 +467,6 @@ const CustomUrlInput = ({
<button
className="underline"
onClick={() => setUrlInputExpanded(true)}
disabled={Boolean(pubKey)}
>
{t('custom wallet location')}
</button>
@@ -12,9 +12,7 @@ export const useIsWalletServiceRunning = (
const checkState = useCallback(async () => {
const connector = connectors['jsonRpc'] as JsonRpcConnector;
if (url && url !== connector.url) {
connector.url = url;
}
connector.url = url;
try {
await connector.checkCompat();
const chainIdResult = await connector.getChainId();
+2 -1
View File
@@ -21,7 +21,8 @@
"echo $NX_TENDERMINT_URL",
"echo $NX_TENDERMINT_WEBSOCKET_URL",
"echo $NX_ETHEREUM_PROVIDER_URL"
]
],
"url": "https://cloud.nx.app"
}
}
},
+1 -1
View File
@@ -166,7 +166,7 @@
"babel-jest": "29.4.3",
"babel-loader": "8.1.0",
"css-loader": "^6.4.0",
"cypress": "12.17.0",
"cypress": "^12.2.0",
"cypress-mochawesome-reporter": "^3.3.0",
"cypress-real-events": "^1.8.1",
"dotenv": "^16.0.1",
+6 -18
View File
@@ -1,34 +1,22 @@
# First use & get started steps
## "Onboarding" state is gradable and has following steps: (<a name="0007-FUGS-002" href="#0007-FUGS-002">0007-FUGS-003</a>)
- 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.
## When first enter the app
- **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) (<a name="0007-FUGS-001" href="#0007-FUGS-001">0007-FUGS-001</a>)
- If full "onboarding" hasn't been accomplished yet, I **must** see the popup with my progress marked. (<a name="0007-FUGS-002" href="#0007-FUGS-002">0007-FUGS-002</a>)
- **Must** If my wallet is already connected I don't see the first use popup (<a name="0007-FUGS-002" href="#0007-FUGS-002">0007-FUGS-002</a>)
- - **Must** If window.vega is detected (browser wallet is installed), don't open first use popup (<a name="0007-FUGS-003" href="#0007-FUGS-003">0007-FUGS-003</a>)
- - **Must** If we detect previous connection using localStorage for desktop/cli wallet, don't open first use popup (<a name="0007-FUGS-004" href="#0007-FUGS-004">0007-FUGS-004</a>)
- **Must** There is a call to action to browse markets, linking to the market view market/all (<a name="0007-FUGS-005" href="#0007-FUGS-005">0007-FUGS-005</a>)
- **Must** I can see the steps I need to take to get started trading (<a name="0007-FUGS-007" href="#0007-FUGS-006">0007-FUGS-006</a>)
- **Must** There is a call to action to get started, triggering the connect modal (<a name="0007-FUGS-007" href="#0007-FUGS-007">0007-FUGS-007</a>)
- **Must** There is a link to try out trading on Fairground when I'm on Mainnet (<a name="0007-FUGS-008" href="#0007-FUGS-008">0007-FUGS-008</a>)
- **Must** There is a link to trade with real funds on Mainnet when I am on Fairground (<a name="0007-FUGS-010" href="#0007-FUGS-010">0007-FUGS-010</a>)
- **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 (<a name="0007-FUGS-011" href="#0007-FUGS-011">0007-FUGS-011</a>)
- 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 (<a name="0007-FUGS-012" href="#0007-FUGS-012">0007-FUGS-012</a>)
## When the popup has been dismissed:
## When first use popup has been seen, but no browser wallet is installed
- **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 (<a name="0007-FUGS-013" href="#0007-FUGS-013">0007-FUGS-013</a>)
- **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 (<a name="0007-FUGS-013" href="#0007-FUGS-013">0007-FUGS-013</a>)
- **Must** Remove buttons from pane containers that prompt to connect wallet (<a name="0007-FUGS-014" href="#0007-FUGS-014">0007-FUGS-014</a>)
- **Must** We've replaced "connect wallet" in the top right with "get started" (<a name="0007-FUGS-015" href="#0007-FUGS-015">0007-FUGS-015</a>)
- **Must** When I press the get started CTA, I see the wallet connect popup (<a name="0007-FUGS-016" href="#0007-FUGS-016">0007-FUGS-016</a>)
+1
View File
@@ -53,6 +53,7 @@ for the a given Ethereum wallet/address/key:
- **must** see how many tokens in each tranche are locked <a name="1005-VEST-025" href="#1005-VEST-025">1005-VEST-025</a>
- **must** see how many tokens in each tranche are redeemable <a name="1005-VEST-026" href="#1005-VEST-026">1005-VEST-026</a>
- **must** see an option to redeem from tranche <a name="1005-VEST-027" href="#1005-VEST-027">1005-VEST-027</a>
- **must** be warned if amount that can be redeemed from that tranche is greater than the un-associated balance for that Eth key (because this will cause the redeem function to fail) <a name="1005-VEST-028" href="#1005-VEST-028">1005-VEST-028</a>
- **should** see how many tokens I'd need to disassociate to be able to run the redeem function (this should be rounded up to avoid the transaction failing due to more tokens having unlocked since the user looked at the form)
- **should** see link to [disassociate](1004-ASSO-associate.md)
+1 -5
View File
@@ -51,8 +51,4 @@
- **Must** be able to see if your realised PnL was affected by loss socialisation (<a name="7004-POSI-018" href="#7004-POSI-018">7004-POSI-018</a>)
- **Must** be able to see what type of product the position was opened on (<a name="7004-POSI-019" href="#7004-POSI-019">7004-POSI-019</a>)
- **Must** not see positions on markets which are closed (<a name="7004-POSI-020" href="#7004-POSI-020">7004-POSI-020</a>)
- **Must** be able to show closed markets (<a name="7004-POSI-021" href="#7004-POSI-021">7004-POSI-021</a>)
- **Must** Must be able to see what type of product the position was opened on (<a name="7004-POSI-019" href="#7004-POSI-019">7004-POSI-019</a>)
+27 -28
View File
@@ -2881,9 +2881,9 @@
globby "^11.0.4"
"@cypress/request@^2.88.10":
version "2.88.12"
resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.12.tgz#ba4911431738494a85e93fb04498cb38bc55d590"
integrity sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA==
version "2.88.10"
resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce"
integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
@@ -2898,9 +2898,9 @@
json-stringify-safe "~5.0.1"
mime-types "~2.1.19"
performance-now "^2.1.0"
qs "~6.10.3"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "^4.1.3"
tough-cookie "~2.5.0"
tunnel-agent "^0.6.0"
uuid "^8.3.2"
@@ -8247,9 +8247,9 @@
integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
"@types/node@^14.14.31":
version "14.18.55"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.55.tgz#c60ad83c7d87c2d933cc4c1cb7d54d98ae50e460"
integrity sha512-PiNZnJDie6lgSWfjWYcQ8KWrEHp0bGv1WgnQAUuaao/HpUBKNX+HXubScoMRdLXBuovbte0djGtsxiWScvlQUQ==
version "14.18.32"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.32.tgz#8074f7106731f1a12ba993fe8bad86ee73905014"
integrity sha512-Y6S38pFr04yb13qqHf8uk1nHE3lXgQ30WZbv1mLliV9pt0NjvqdWttLcrOYLnXbOafknVYRHZGoMSpR9UwfYow==
"@types/node@^16.0.0":
version "16.18.37"
@@ -12337,10 +12337,10 @@ cypress-real-events@^1.8.1:
resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.8.1.tgz#d00c7fe93124bbe7c0f27296684838614d24a840"
integrity sha512-8fFnA8EzS3EVbAmpSEUf3A8yZCmfU3IPOSGUDVFCdE1ke1gYL1A+gvXXV6HKUbTPRuvKKt2vpaMbUwYLpDRswQ==
cypress@12.17.0:
version "12.17.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.17.0.tgz#3a907a41c4afbb44be7b84e822e4914d734a6bb0"
integrity sha512-nq0ug8Zrjq/2khHU1PTNxg+3/n1oqtmAFCxwQhS6QzkQ4mR6RLitX+cGIOuIMfnEbDAtVub0hZh661FOA16JxA==
cypress@^12.2.0:
version "12.16.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.16.0.tgz#d0dcd0725a96497f4c60cf54742242259847924c"
integrity sha512-mwv1YNe48hm0LVaPgofEhGCtLwNIQEjmj2dJXnAkY1b4n/NE9OtgPph4TyS+tOtYp5CKtRmDvBzWseUXQTjbTg==
dependencies:
"@cypress/request" "^2.88.10"
"@cypress/xvfb" "^1.2.4"
@@ -12379,7 +12379,7 @@ cypress@12.17.0:
pretty-bytes "^5.6.0"
proxy-from-env "1.0.0"
request-progress "^3.0.0"
semver "^7.5.3"
semver "^7.3.2"
supports-color "^8.1.1"
tmp "~0.2.1"
untildify "^4.0.0"
@@ -20881,7 +20881,7 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==
psl@^1.1.33:
psl@^1.1.28, psl@^1.1.33:
version "1.9.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
@@ -20998,12 +20998,10 @@ qs@^6.10.3:
dependencies:
side-channel "^1.0.4"
qs@~6.10.3:
version "6.10.5"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.5.tgz#974715920a80ff6a262264acd2c7e6c2a53282b4"
integrity sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ==
dependencies:
side-channel "^1.0.4"
qs@~6.5.2:
version "6.5.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
query-string@6.13.5:
version "6.13.5"
@@ -22271,13 +22269,6 @@ semver@^7.5.1:
dependencies:
lru-cache "^6.0.0"
semver@^7.5.3:
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
semver@~7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
@@ -23531,7 +23522,7 @@ toml@^3.0.0:
resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==
tough-cookie@^4.1.2, tough-cookie@^4.1.3:
tough-cookie@^4.1.2:
version "4.1.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
@@ -23541,6 +23532,14 @@ tough-cookie@^4.1.2, tough-cookie@^4.1.3:
universalify "^0.2.0"
url-parse "^1.5.3"
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
psl "^1.1.28"
punycode "^2.1.1"
tr46@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"