Compare commits

..
Author SHA1 Message Date
Bartłomiej Głownia cea19a1197 chore: remove build and publish targets from libs 2023-09-05 08:47:10 +02:00
Bartłomiej Głownia c7e4b24c9c chore: convert libs to swc 2023-09-04 13:27:32 +02:00
Sam Keen b5ba4f99d9 fix(governance,utils,react-helpers): token locale formatting issue (#4678) 2023-09-04 12:09:38 +01:00
Joe Tsang 66f25603d3 test(explorer): add e2e test for explorer oracles (#4657) 2023-09-04 09:41:04 +00:00
Edd 4afd469404 chore(explorer,trading,governance): reconfigure hooks (#4655) 2023-09-04 09:36:13 +00:00
Maciek 9e5bc9c8d1 chore(trading): handle negative decimals (#4659) 2023-09-04 09:46:02 +02:00
Matthew Russell e41aff88b1 chore(trading): make top traded default sort for market selector (#4637) 2023-09-03 11:15:41 -07:00
Matthew Russell 9209074332 chore(trading): change pane context buttons color (#4680) 2023-09-01 17:00:11 -07:00
Art 39e5836edb fix(wallet): check if snaps are supported (#4671) 2023-09-01 11:22:13 +00:00
Art 85a4981700 fix(proposals): protocol upgrade notification block querying (#4665) 2023-09-01 12:30:01 +02:00
Ben 247927e939 chore(trading): get started specs update (#4681) 2023-09-01 10:55:56 +01:00
Maciek 6523490d96 chore(trading): 4349 delayed telemetry opt in (#4642) 2023-09-01 09:00:20 +00:00
daro-maj 105a758e8d test(trading): add stop order oco spec (#4669) 2023-09-01 10:48:38 +02:00
Matthew Russell 559ef48d6d feat(trading): orderbook changes (#4652) 2023-08-31 13:34:13 -07:00
Bartłomiej Głownia 255c3752f2 feat(deal-ticket): fix flaky tests (#4667) 2023-08-31 10:41:58 -07:00
Joe Tsang 2bbf1e2b81 chore(ci): update config.hcl file (#4677) 2023-08-31 10:35:46 -07:00
Maciek 06d3ef8d73 fix: de-polish and fix links to mozilla (#4670) 2023-08-31 14:09:41 +00:00
ArtandDariusz Majcherczyk de4c7926c2 chore(deposits): formatting tweaks (#4648)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
2023-08-31 15:30:03 +02:00
179 changed files with 2372 additions and 1555 deletions
-3
View File
@@ -3,6 +3,3 @@
# Lint commit messages to ensure they follow conventional commit standards
yarn commitlint --edit "${1}"
# Lint all staged files
yarn lint-staged
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Lint all staged files
yarn lint-staged
+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Lint all staged files
yarn nx format:check
# Test all projects with changes
yarn nx affected -t test --exclude trading
@@ -0,0 +1,68 @@
context('Oracle page', { tags: '@smoke' }, () => {
describe('Verify elements on page', () => {
before('create market and navigate to oracle page', () => {
cy.createMarket();
cy.visit('/oracles');
});
it('should see oracle data', () => {
cy.getByTestId('oracle-details').should('have.length.at.least', 2);
cy.getByTestId('oracle-details')
.should('exist')
.eq(0)
.within(() => {
cy.get('tr')
.eq(0)
.within(() => {
cy.get('th').should('have.text', 'ID');
cy.get('a').invoke('text').should('have.length', 64);
cy.get('a')
.should('have.attr', 'href')
.and('contain', '/oracles/');
});
cy.get('tr')
.eq(1)
.within(() => {
cy.get('th').should('have.text', 'Type');
cy.get('td').should('have.text', 'External data');
});
cy.get('tr')
.eq(2)
.within(() => {
cy.get('th').should('have.text', 'Signer');
cy.getByTestId('keytype').should('have.text', 'Vega');
cy.get('a').invoke('text').should('have.length', 64);
cy.get('a')
.should('have.attr', 'href')
.and('contain', '/parties/');
});
cy.get('tr')
.eq(3)
.within(() => {
cy.get('th').should('have.text', 'Settlement for');
cy.get('a').invoke('text').should('have.length', 64);
cy.get('a')
.should('have.attr', 'href')
.and('contain', '/markets/');
});
cy.get('tr')
.eq(4)
.within(() => {
cy.get('th').should('have.text', 'Matched data');
cy.get('td').should('have.text', '❌');
});
cy.get('details')
.eq(0)
.within(() => {
cy.contains('Filter').click();
cy.get('.language-json').should('exist');
});
cy.get('details')
.eq(1)
.within(() => {
cy.contains('JSON').click();
cy.get('.language-json').should('exist');
});
});
});
});
});
@@ -38,7 +38,12 @@ const Oracles = () => {
const dataConnection = o?.node.dataConnection;
return (
<div id={id} key={id} className="mb-10">
<div
id={id}
key={id}
className="mb-10"
data-testid="oracle-details"
>
<OracleDetails
id={id}
dataSource={o?.node}
+2 -2
View File
@@ -23,7 +23,7 @@ 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
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
#Test configuration variables
CYPRESS_FAIRGROUND=false
@@ -31,4 +31,4 @@ LC_ALL="en_US.UTF-8"
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=true
NX_METAMASK_SNAPS=true
+2 -2
View File
@@ -20,7 +20,7 @@ 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_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
@@ -30,4 +30,4 @@ CYPRESS_FAIRGROUND=false
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false
NX_METAMASK_SNAPS=false
NX_METAMASK_SNAPS=false
+2 -2
View File
@@ -15,11 +15,11 @@ 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_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
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_METAMASK_SNAPS=true
NX_METAMASK_SNAPS=true
+1 -1
View File
@@ -15,7 +15,7 @@ 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_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
+1 -1
View File
@@ -14,7 +14,7 @@ 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_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
+1 -1
View File
@@ -11,7 +11,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
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_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
+1 -1
View File
@@ -16,7 +16,7 @@ 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_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
+1 -1
View File
@@ -13,7 +13,7 @@ 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_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
@@ -54,7 +54,7 @@ export const WalletCardRow = ({
}) => {
const ref = React.useRef<HTMLDivElement | null>(null);
useAnimateValue(ref, value);
const [integers, decimalsPlaces] = useNumberParts(value, decimals);
const [integers, decimalsPlaces, separator] = useNumberParts(value, decimals);
return (
<div
@@ -75,7 +75,10 @@ export const WalletCardRow = ({
className="font-mono flex-1 text-right"
data-testid="associated-amount"
>
<span>{integers}.</span>
<span>
{integers}
{separator}
</span>
<span>{decimalsPlaces}</span>
</span>
)}
@@ -110,7 +113,10 @@ export const WalletCardAsset = ({
border,
subheading,
}: WalletCardAssetProps) => {
const [integers, decimalsPlaces] = useNumberParts(balance, decimals);
const [integers, decimalsPlaces, separator] = useNumberParts(
balance,
decimals
);
return (
<div className="flex flex-nowrap mt-2 mb-4">
@@ -132,7 +138,10 @@ export const WalletCardAsset = ({
</div>
</div>
<div className="px-2 basis-full font-mono" data-testid="currency-value">
<span>{integers}.</span>
<span>
{integers}
{separator}
</span>
<span className="text-neutral-400">{decimalsPlaces}</span>
</div>
</div>
@@ -133,11 +133,7 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
validateMarketDataRow(4, 'Decimals', '5');
validateMarketDataRow(5, 'Quantum', '1');
validateMarketDataRow(6, 'Status', 'Enabled');
validateMarketDataRow(
7,
'Contract address',
'0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4'
);
validateMarketDataRow(7, 'Contract address', '0x0158…78a4');
validateMarketDataRow(8, 'Withdrawal threshold', '0.0005');
validateMarketDataRow(9, 'Lifetime limit', '1,230');
validateMarketDataRow(10, 'Infrastructure fee account balance', '0.00001');
@@ -6,7 +6,7 @@ const askVolume = 'ask-vol-9894185';
const bidVolume = 'bid-vol-9889001';
const askCumulative = 'cumulative-vol-9894185';
const bidCumulative = 'cumulative-vol-9889001';
const midPrice = 'middle-mark-price-4612690000';
const midPrice = 'last-traded-4612690000';
const priceResolution = 'resolution';
const dealTicketPrice = 'order-price';
const dealTicketSize = 'order-size';
@@ -43,11 +43,10 @@ describe('ethereum wallet', { tags: '@smoke', testIsolation: true }, () => {
// 0004-EWAL-005
// 0004-EWAL-006
const ethWalletAddress = Cypress.env('ETHEREUM_WALLET_ADDRESS');
cy.getByTestId('Deposits').click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('MetaMask');
cy.getByTestId('ethereum-address').should('have.text', ethWalletAddress);
cy.getByTestId('ethereum-address').should('have.text', '0xEe7D…d94F');
cy.getByTestId('disconnect-ethereum-wallet')
.should('have.text', 'Disconnect')
.click();
+1 -1
View File
@@ -13,7 +13,7 @@ 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
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
# Cosmic elevator flags
+1 -1
View File
@@ -13,7 +13,7 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/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_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
+1 -1
View File
@@ -14,7 +14,7 @@ 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
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+1 -1
View File
@@ -14,7 +14,7 @@ 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://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
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/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
+1 -1
View File
@@ -14,7 +14,7 @@ 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://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
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/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 -1
View File
@@ -14,7 +14,7 @@ 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
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+1 -1
View File
@@ -15,7 +15,7 @@ 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://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
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+1 -1
View File
@@ -16,7 +16,7 @@ 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
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false
@@ -1,5 +1,5 @@
import { t } from '@vegaprotocol/i18n';
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
import { TradingButton } from '@vegaprotocol/ui-toolkit';
import { ViewType, useSidebar } from '../sidebar';
export const AccountsMenu = () => {
@@ -8,7 +8,6 @@ export const AccountsMenu = () => {
return (
<>
<TradingButton
intent={Intent.Primary}
size="extra-small"
data-testid="open-transfer"
onClick={() => setView({ type: ViewType.Transfer })}
@@ -16,7 +15,6 @@ export const AccountsMenu = () => {
{t('Transfer')}
</TradingButton>
<TradingButton
intent={Intent.Primary}
size="extra-small"
onClick={() => setView({ type: ViewType.Deposit })}
>
@@ -1,5 +1,5 @@
import { t } from '@vegaprotocol/i18n';
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
import { TradingButton } from '@vegaprotocol/ui-toolkit';
import { ViewType, useSidebar } from '../sidebar';
export const DepositsMenu = () => {
@@ -7,7 +7,6 @@ export const DepositsMenu = () => {
return (
<TradingButton
intent={Intent.Primary}
size="extra-small"
onClick={() => setView({ type: ViewType.Deposit })}
data-testid="deposit-button"
@@ -69,6 +69,7 @@ describe('MarketSelectorItem', () => {
targetStake: '1000000',
trigger: AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
priceMonitoringBounds: null,
lastTradedPrice: '100',
};
const candles = [
@@ -262,9 +262,7 @@ describe('MarketSelector', () => {
await userEvent.click(screen.getByTestId('sort-trigger'));
const options = screen.getAllByTestId(/sort-item/);
expect(options.map((o) => o.textContent?.trim())).toEqual(
Object.entries(Sort)
.filter(([key]) => key !== Sort.None)
.map(([key]) => SortTypeMapping[key as SortType])
Object.entries(Sort).map(([key]) => SortTypeMapping[key as SortType])
);
await userEvent.click(screen.getByTestId('sort-item-Gained'));
expect(
@@ -40,7 +40,7 @@ export const MarketSelector = ({
const [filter, setFilter] = useState<Filter>({
searchTerm: '',
product: Product.All,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
const allProducts = filter.product === Product.All;
@@ -53,7 +53,7 @@ export const MarketSelector = ({
return (
<div data-testid="market-selector">
<div className="pt-2 px-2 mb-2">
<div className="px-2 pt-2 mb-2">
<ProductSelector
product={filter.product}
onSelect={(product) => {
@@ -106,9 +106,6 @@ export const MarketSelector = ({
currentSort={filter.sort}
onSelect={(sort) => {
setFilter((curr) => {
if (curr.sort === sort) {
return { ...curr, sort: Sort.None };
}
return {
...curr,
sort,
@@ -294,9 +291,9 @@ const List = ({
const Skeleton = () => {
return (
<div className="mb-2 px-2">
<div className="bg-vega-light-100 dark:bg-vega-dark-100 rounded-lg p-4">
<div className="w-full h-3 bg-vega-light-200 dark:bg-vega-dark-200 mb-2" />
<div className="px-2 mb-2">
<div className="p-4 rounded-lg bg-vega-light-100 dark:bg-vega-dark-100">
<div className="w-full h-3 mb-2 bg-vega-light-200 dark:bg-vega-dark-200" />
<div className="w-2/3 h-3 bg-vega-light-200 dark:bg-vega-dark-200" />
</div>
</div>
@@ -1,4 +1,3 @@
import { t } from '@vegaprotocol/i18n';
import {
DropdownMenu,
DropdownMenuContent,
@@ -11,7 +10,6 @@ import {
} from '@vegaprotocol/ui-toolkit';
export const Sort = {
None: 'None',
Gained: 'Gained',
Lost: 'Lost',
New: 'New',
@@ -23,17 +21,15 @@ export type SortType = keyof typeof Sort;
export const SortTypeMapping: {
[key in SortType]: string;
} = {
[Sort.None]: 'None',
[Sort.TopTraded]: 'Top traded',
[Sort.Gained]: 'Top gaining',
[Sort.Lost]: 'Top losing',
[Sort.New]: 'New markets',
[Sort.TopTraded]: 'Top traded',
};
const SortIconMapping: {
[key in SortType]: VegaIconNames;
} = {
[Sort.None]: null as unknown as VegaIconNames, // not shown in list
[Sort.Gained]: VegaIconNames.TREND_UP,
[Sort.Lost]: VegaIconNames.TREND_DOWN,
[Sort.New]: VegaIconNames.STAR,
@@ -51,10 +47,8 @@ export const SortDropdown = ({
<DropdownMenu
trigger={
<DropdownMenuTrigger data-testid="sort-trigger">
<span className="flex justify-between items-center">
{currentSort === SortTypeMapping.None
? t('Sort')
: SortTypeMapping[currentSort]}{' '}
<span className="flex items-center justify-between gap-1">
{SortTypeMapping[currentSort]}
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} />
</span>
</DropdownMenuTrigger>
@@ -65,24 +59,22 @@ export const SortDropdown = ({
value={currentSort}
onValueChange={(value) => onSelect(value as SortType)}
>
{Object.keys(Sort)
.filter((s) => s !== Sort.None)
.map((key) => {
return (
<DropdownMenuRadioItem
inset
key={key}
value={key}
data-testid={`sort-item-${key}`}
>
<span className="flex gap-2">
<VegaIcon name={SortIconMapping[key as SortType]} />{' '}
{SortTypeMapping[key as SortType]}
</span>
<DropdownMenuItemIndicator />
</DropdownMenuRadioItem>
);
})}
{Object.keys(Sort).map((key) => {
return (
<DropdownMenuRadioItem
inset
key={key}
value={key}
data-testid={`sort-item-${key}`}
>
<span className="flex gap-2">
<VegaIcon name={SortIconMapping[key as SortType]} />{' '}
{SortTypeMapping[key as SortType]}
</span>
<DropdownMenuItemIndicator />
</DropdownMenuRadioItem>
);
})}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
@@ -12,7 +12,10 @@ import { useMarketList } from '@vegaprotocol/markets';
import type { Filter } from '../../components/market-selector';
import { subDays } from 'date-fns';
jest.mock('@vegaprotocol/markets');
jest.mock('@vegaprotocol/markets', () => ({
...jest.requireActual('@vegaprotocol/markets'),
useMarketList: jest.fn(),
}));
const mockUseMarketList = useMarketList as jest.Mock;
describe('useMarketSelectorList', () => {
@@ -20,7 +23,7 @@ describe('useMarketSelectorList', () => {
const defaultArgs: Filter = {
searchTerm: '',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
};
return renderHook((args) => useMarketSelectorList(args), {
@@ -109,21 +112,21 @@ describe('useMarketSelectorList', () => {
rerender({
searchTerm: '',
product: Product.Spot as 'Future',
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([markets[1]]);
rerender({
searchTerm: '',
product: Product.Perpetual as 'Future',
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([markets[2]]);
rerender({
searchTerm: '',
product: Product.All,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual(markets);
@@ -189,7 +192,7 @@ describe('useMarketSelectorList', () => {
const { result, rerender } = setup({
searchTerm: '',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: ['asset-0'],
});
expect(result.current.markets).toEqual([markets[0], markets[1]]);
@@ -197,7 +200,7 @@ describe('useMarketSelectorList', () => {
rerender({
searchTerm: '',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: ['asset-0', 'asset-1'],
});
@@ -210,7 +213,7 @@ describe('useMarketSelectorList', () => {
rerender({
searchTerm: '',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: ['asset-0', 'asset-1', 'asset-2'],
});
@@ -220,7 +223,7 @@ describe('useMarketSelectorList', () => {
rerender({
searchTerm: '',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: ['asset-invalid'],
});
@@ -275,28 +278,28 @@ describe('useMarketSelectorList', () => {
const { result, rerender } = setup({
searchTerm: 'abc',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([markets[0]]);
rerender({
searchTerm: 'def',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([markets[1], markets[2]]);
rerender({
searchTerm: 'defg',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([markets[2]]);
rerender({
searchTerm: 'zzz',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([]);
@@ -305,14 +308,14 @@ describe('useMarketSelectorList', () => {
rerender({
searchTerm: 'aaa',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([markets[0]]);
rerender({
searchTerm: 'ggg',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([
@@ -322,11 +325,15 @@ describe('useMarketSelectorList', () => {
]);
});
it('sorts by state and volume by default', () => {
it('sorts by top traded by default', () => {
const markets = [
createMarketFragment({
id: 'market-0',
state: MarketState.STATE_PENDING,
state: MarketState.STATE_ACTIVE,
// @ts-ignore data not on fragment
data: {
markPrice: '1',
},
// @ts-ignore candles not on fragment
candles: [
{
@@ -337,30 +344,42 @@ describe('useMarketSelectorList', () => {
createMarketFragment({
id: 'market-1',
state: MarketState.STATE_ACTIVE,
// @ts-ignore data not on fragment
data: {
markPrice: '1',
},
// @ts-ignore candles not on fragment
candles: [
{
volume: '200',
volume: '100',
},
],
}),
createMarketFragment({
id: 'market-2',
state: MarketState.STATE_ACTIVE,
// @ts-ignore data not on fragment
data: {
markPrice: '1',
},
// @ts-ignore candles not on fragment
candles: [
{
volume: '100',
volume: '300',
},
],
}),
createMarketFragment({
state: MarketState.STATE_PENDING,
id: 'market-3',
state: MarketState.STATE_ACTIVE,
// @ts-ignore data not on fragment
data: {
markPrice: '1',
},
// @ts-ignore candles not on fragment
candles: [
{
volume: '100',
volume: '400',
},
],
}),
@@ -375,14 +394,15 @@ describe('useMarketSelectorList', () => {
const { result } = setup({
searchTerm: '',
product: Product.Future,
sort: Sort.None,
sort: Sort.TopTraded,
assets: [],
});
expect(result.current.markets).toEqual([
markets[1],
markets[3],
markets[2],
markets[0],
markets[3],
markets[1],
]);
});
@@ -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 { calcTradedFactor, useMarketList } from '@vegaprotocol/markets';
import { priceChangePercentage } from '@vegaprotocol/utils';
import type { Filter } from '../../components/market-selector/market-selector';
import { Sort } from './sort-dropdown';
@@ -60,22 +56,6 @@ export const useMarketSelectorList = ({
return false;
});
if (sort === Sort.None) {
// Sort by market state primarily and AtoZ secondarily
return orderBy(
markets,
[
(m) => MARKET_TEMPLATE.indexOf(m.state),
(m) => {
if (!m.candles?.length) return 0;
const vol = calcCandleVolume(m.candles);
return Number(vol || 0);
},
],
['asc', 'desc']
);
}
if (sort === Sort.Gained || sort === Sort.Lost) {
const dir = sort === Sort.Gained ? 'desc' : 'asc';
return orderBy(
@@ -1,5 +1,5 @@
import { t } from '@vegaprotocol/i18n';
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
import { TradingButton } from '@vegaprotocol/ui-toolkit';
import { usePositionsStore } from '../positions-container';
export const PositionsMenu = () => {
@@ -7,7 +7,6 @@ export const PositionsMenu = () => {
const toggle = usePositionsStore((store) => store.toggleClosedMarkets);
return (
<TradingButton
intent={Intent.Primary}
size="extra-small"
data-testid="open-transfer"
onClick={toggle}
@@ -24,8 +24,8 @@ export const Settings = () => {
>
<Switch
name="settings-telemetry-switch"
onCheckedChange={(isOn) => setIsApproved(isOn)}
checked={isApproved}
onCheckedChange={(isOn) => setIsApproved(isOn ? 'true' : 'false')}
checked={isApproved === 'true'}
/>
</SettingsGroup>
<SettingsGroup label={t('Toast location')}>
@@ -23,6 +23,7 @@ import { Links, Routes } from '../../pages/client-router';
import { useGlobalStore } from '../../stores';
import { useSidebar, ViewType } from '../sidebar';
import * as constants from '../constants';
import { useOnboardingStore } from './welcome-dialog';
interface Props {
lead?: string;
@@ -35,7 +36,7 @@ const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
constants.ONBOARDING_VIEWED_KEY
);
const update = useGlobalStore((store) => store.update);
const dismiss = useOnboardingStore((store) => store.dismiss);
const marketId = useGlobalStore((store) => store.marketId);
const link = marketId ? Links[Routes.MARKET](marketId) : Links[Routes.HOME]();
const openVegaWalletDialog = useVegaWalletDialogStore(
@@ -61,7 +62,7 @@ const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
onClickHandle = () => {
navigate(link);
setView({ type: ViewType.Deposit });
update({ onBoardingDismissed: true });
dismiss();
};
} else if (step === OnboardingStep.ONBOARDING_ORDER_STEP) {
buttonText = t('Dismiss');
@@ -2,29 +2,35 @@ import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TelemetryApproval } from './telemetry-approval';
jest.mock('@vegaprotocol/logger', () => ({
SentryInit: () => undefined,
SentryClose: () => undefined,
}));
jest.mock('@vegaprotocol/environment', () => ({
useEnvironment: () => ({ VEGA_ENV: 'test', SENTRY_DSN: 'sentry-dsn' }),
}));
describe('TelemetryApproval', () => {
it('click on checkbox should be properly handled', async () => {
const helpText = 'My help text';
render(<TelemetryApproval helpText={helpText} />);
expect(screen.getByRole('checkbox')).toHaveAttribute(
'data-state',
'unchecked'
it('click on buttons should be properly handled', async () => {
const mockSetTelemetryValue = jest.fn();
render(
<TelemetryApproval
telemetryValue="false"
setTelemetryValue={mockSetTelemetryValue}
/>
);
await userEvent.click(screen.getByRole('checkbox'));
expect(screen.getByRole('checkbox')).toHaveAttribute(
'data-state',
'checked'
expect(
screen.getByRole('button', { name: 'No thanks' })
).toBeInTheDocument();
await userEvent.click(screen.getByRole('button', { name: 'No thanks' }));
expect(mockSetTelemetryValue).toHaveBeenCalledWith('false');
expect(screen.getByText('Share data')).toBeInTheDocument();
await userEvent.click(screen.getByText('Share data'));
expect(mockSetTelemetryValue).toHaveBeenCalledWith('true');
});
it('confirm button should have proper text', async () => {
const mockSetTelemetryValue = jest.fn();
render(
<TelemetryApproval
telemetryValue="true"
setTelemetryValue={mockSetTelemetryValue}
/>
);
expect(screen.getByText('Share usage data')).toBeInTheDocument();
expect(screen.getByText(helpText)).toBeInTheDocument();
expect(screen.getByText('Continue sharing data')).toBeInTheDocument();
await userEvent.click(screen.getByText('Continue sharing data'));
expect(mockSetTelemetryValue).toHaveBeenCalledWith('true');
});
});
@@ -1,21 +1,66 @@
import { TradingCheckbox } from '@vegaprotocol/ui-toolkit';
import {
Intent,
TradingButton,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { useTelemetryApproval } from '../../lib/hooks/use-telemetry-approval';
export const TelemetryApproval = ({ helpText }: { helpText: string }) => {
const [isApproved, setIsApproved] = useTelemetryApproval();
interface Props {
telemetryValue: string;
setTelemetryValue: (value: string) => void;
}
export const TelemetryApproval = ({
telemetryValue,
setTelemetryValue,
}: Props) => {
return (
<div className="flex flex-col py-3">
<div className="mr-4" role="form">
<TradingCheckbox
label={<span className="text-lg pl-1">{t('Share usage data')}</span>}
checked={isApproved}
name="telemetry-approval"
onCheckedChange={() => setIsApproved(!isApproved)}
/>
</div>
<div className="text-sm text-vega-light-300 dark:text-vega-dark-300 ml-6">
<span>{helpText}</span>
<div className="mt-2">
{t(
'Help us identify bugs and improve Vega Governance by sharing anonymous usage data.'
)}
</div>
<div className="flex items-center mt-2">
<VegaIcon name={VegaIconNames.EYE_OFF} size={24} />
<div className="flex flex-col gap-1 ml-6">
<div className="font-semibold">{t('Anonymous')}</div>
<div>{t('Your identity is always anonymous on Vega')}</div>
</div>
</div>
<div className="flex items-center mt-2">
<VegaIcon name={VegaIconNames.COG} size={24} />
<div className="flex flex-col gap-1 ml-6">
<div className="font-semibold">{t('Optional')}</div>
<div>{t('You can opt out any time via settings')}</div>
</div>
</div>
<div className="flex flex-col justify-around items-center mt-10 gap-4 w-full px-4">
<TradingButton
onClick={() => setTelemetryValue('false')}
size="small"
intent={Intent.None}
data-testid="do-not-share-data-button"
fill
>
{t('No thanks')}
</TradingButton>
<TradingButton
onClick={() => setTelemetryValue('true')}
intent={Intent.Info}
data-testid="share-data-button"
size="small"
fill
>
{telemetryValue === 'true'
? t('Continue sharing data')
: t('Share data')}
</TradingButton>
</div>
</div>
</div>
);
@@ -5,17 +5,17 @@ import { useNavigate } from 'react-router-dom';
import { Links, Routes } from '../../pages/client-router';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
import type { ReactNode } from 'react';
import { useGlobalStore } from '../../stores';
import { useOnboardingStore } from './welcome-dialog';
export const WelcomeDialogContent = () => {
const { VEGA_ENV } = useEnvironment();
const update = useGlobalStore((store) => store.update);
const dismiss = useOnboardingStore((store) => store.dismiss);
const navigate = useNavigate();
const browseMarkets = () => {
const link = Links[Routes.MARKETS]();
navigate(link);
update({ onBoardingDismissed: true });
dismiss();
};
const lead =
VEGA_ENV === Networks.MAINNET
@@ -1,7 +1,9 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
import type { Toast } from '@vegaprotocol/ui-toolkit';
import { Dialog, Intent, useToasts } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { useEnvironment } from '@vegaprotocol/environment';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { WelcomeDialogContent } from './welcome-dialog-content';
@@ -12,15 +14,41 @@ import {
OnboardingStep,
} from './use-get-onboarding-step';
import * as constants from '../constants';
import { TelemetryApproval } from './telemetry-approval';
import { useTelemetryApproval } from '../../lib/hooks/use-telemetry-approval';
import { useCallback } from 'react';
const ONBOARDING_STORAGE_KEY = 'vega_onboarding_dismiss_store';
export const useOnboardingStore = create<{
dismissed: boolean;
dismiss: () => void;
}>()(
persist(
(set) => ({
dismissed: false,
dismiss: () => set(() => ({ dismissed: true })),
}),
{
name: ONBOARDING_STORAGE_KEY,
}
)
);
const TELEMETRY_APPROVAL_TOAST_ID = 'telemetry_tost_id';
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 navigate = useNavigate();
const [telemetryValue, setTelemetryValue, isTelemetryNeeded, closeTelemetry] =
useTelemetryApproval();
const [onBoardingViewed] = useLocalStorage(constants.ONBOARDING_VIEWED_KEY);
const dismiss = useOnboardingStore((store) => store.dismiss);
const dismissed = useOnboardingStore((store) => store.dismissed);
const currentStep = useGetOnboardingStep();
const isTelemetryPopupNeeded =
isTelemetryNeeded &&
(onBoardingViewed === 'true' ||
currentStep > OnboardingStep.ONBOARDING_ORDER_STEP);
const isOnboardingDialogNeeded =
onBoardingViewed !== 'true' &&
currentStep &&
@@ -29,12 +57,58 @@ export const WelcomeDialog = () => {
const marketId = useGlobalStore((store) => store.marketId);
const onClose = () => {
const link = marketId
? Links[Routes.MARKET](marketId)
: Links[Routes.HOME]();
navigate(link);
update({ onBoardingDismissed: true });
if (isTelemetryPopupNeeded) {
closeTelemetry();
} else {
const link = marketId
? Links[Routes.MARKET](marketId)
: Links[Routes.HOME]();
navigate(link);
dismiss();
}
};
const [setToast, hasToast, removeToast] = useToasts((store) => [
store.setToast,
store.hasToast,
store.remove,
]);
const onApprovalClose = useCallback(() => {
closeTelemetry();
removeToast(TELEMETRY_APPROVAL_TOAST_ID);
}, [removeToast, closeTelemetry]);
const setTelemetryApprovalAndClose = useCallback(
(value: string) => {
setTelemetryValue(value);
onApprovalClose();
},
[setTelemetryValue, onApprovalClose]
);
if (isTelemetryPopupNeeded) {
const toast: Toast = {
id: TELEMETRY_APPROVAL_TOAST_ID,
intent: Intent.Primary,
content: (
<>
<h3 className="text-sm uppercase mb-1">
{t('Improve vega console')}
</h3>
<TelemetryApproval
telemetryValue={telemetryValue}
setTelemetryValue={setTelemetryApprovalAndClose}
/>
</>
),
onClose: onApprovalClose,
};
if (!hasToast(TELEMETRY_APPROVAL_TOAST_ID)) {
setToast(toast);
}
return;
}
const title = (
<span className="font-alpha calt" data-testid="welcome-title">
{t('Console')}{' '}
@@ -1,5 +1,5 @@
import { t } from '@vegaprotocol/i18n';
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
import { TradingButton } from '@vegaprotocol/ui-toolkit';
import { ViewType, useSidebar } from '../sidebar';
export const WithdrawalsMenu = () => {
@@ -7,7 +7,6 @@ export const WithdrawalsMenu = () => {
return (
<TradingButton
intent={Intent.Primary}
size="extra-small"
onClick={() => setView({ type: ViewType.Withdraw })}
data-testid="withdraw-dialog-button"
@@ -1,19 +1,40 @@
import { renderHook, act, waitFor } from '@testing-library/react';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { SentryInit, SentryClose } from '@vegaprotocol/logger';
import { STORAGE_KEY, useTelemetryApproval } from './use-telemetry-approval';
import {
STORAGE_KEY,
STORAGE_SECOND_KEY,
useTelemetryApproval,
} from './use-telemetry-approval';
import { Networks } from '@vegaprotocol/environment';
const mockSetValue = jest.fn();
const mockRemoveValue = jest.fn();
let mockStorageHookApprovalResult: [string | null, jest.Mock] = [
null,
mockSetValue,
];
const mockSetSecondValue = jest.fn();
let mockStorageHookViewedResult: [string | null, jest.Mock] = [
null,
mockSetSecondValue,
];
jest.mock('@vegaprotocol/logger');
jest.mock('@vegaprotocol/react-helpers', () => ({
...jest.requireActual('@vegaprotocol/react-helpers'),
useLocalStorage: jest
.fn()
.mockImplementation(() => [false, mockSetValue, mockRemoveValue]),
useLocalStorage: jest.fn((key: string) => {
if (key === 'vega_telemetry_approval') {
return mockStorageHookApprovalResult;
}
return mockStorageHookViewedResult;
}),
}));
let mockVegaEnv = 'test';
jest.mock('@vegaprotocol/environment', () => ({
useEnvironment: () => ({ VEGA_ENV: 'test', SENTRY_DSN: 'sentry-dsn' }),
...jest.requireActual('@vegaprotocol/environment'),
useEnvironment: jest.fn(() => ({
VEGA_ENV: mockVegaEnv,
SENTRY_DSN: 'sentry-dsn',
})),
}));
describe('useTelemetryApproval', () => {
@@ -21,32 +42,71 @@ describe('useTelemetryApproval', () => {
jest.clearAllMocks();
});
it('hook should return proper array', () => {
it('when empty hook should return proper array', () => {
const { result } = renderHook(() => useTelemetryApproval());
expect(result.current[0]).toEqual(false);
expect(result.current[0]).toEqual('');
expect(result.current[1]).toEqual(expect.any(Function));
expect(result.current[2]).toEqual(true);
expect(result.current[3]).toEqual(expect.any(Function));
expect(useLocalStorage).toHaveBeenCalledWith(STORAGE_KEY);
expect(useLocalStorage).toHaveBeenCalledWith(STORAGE_SECOND_KEY);
expect(mockSetValue).toHaveBeenCalledWith('true');
expect(mockSetSecondValue).not.toHaveBeenCalledWith('true');
});
it('when approval not empty but viewed is empty should return proper array', () => {
mockStorageHookApprovalResult = ['false', mockSetValue];
const { result } = renderHook(() => useTelemetryApproval());
expect(result.current[0]).toEqual('false');
expect(result.current[1]).toEqual(expect.any(Function));
expect(result.current[2]).toEqual(true);
expect(result.current[3]).toEqual(expect.any(Function));
expect(useLocalStorage).toHaveBeenCalledWith(STORAGE_KEY);
expect(useLocalStorage).toHaveBeenCalledWith(STORAGE_SECOND_KEY);
expect(mockSetValue).not.toHaveBeenCalled();
expect(mockSetSecondValue).not.toHaveBeenCalled();
});
it('when NOT empty hook should return proper array', () => {
mockStorageHookApprovalResult = ['false', mockSetValue];
mockStorageHookViewedResult = ['true', mockSetSecondValue];
const { result } = renderHook(() => useTelemetryApproval());
expect(result.current[0]).toEqual('false');
expect(result.current[1]).toEqual(expect.any(Function));
expect(result.current[2]).toEqual(false);
expect(result.current[3]).toEqual(expect.any(Function));
expect(useLocalStorage).toHaveBeenCalledWith(STORAGE_KEY);
expect(mockSetValue).not.toHaveBeenCalled();
});
it('on mainnet hook should init properly', () => {
mockStorageHookApprovalResult = [null, mockSetValue];
mockVegaEnv = Networks.MAINNET;
renderHook(() => useTelemetryApproval());
expect(mockSetValue).toHaveBeenCalledWith('false');
});
it('hook should init stuff properly', async () => {
const { result } = renderHook(() => useTelemetryApproval());
await act(() => {
result.current[1](true);
result.current[1]('true');
});
await waitFor(() => {
expect(SentryInit).toHaveBeenCalled();
expect(mockSetValue).toHaveBeenCalledWith('1');
expect(mockSetValue).toHaveBeenCalledWith('true');
expect(mockSetSecondValue).toHaveBeenCalledWith('true');
});
});
it('hook should close stuff properly', async () => {
const { result } = renderHook(() => useTelemetryApproval());
await act(() => {
result.current[1](false);
result.current[1]('false');
});
await waitFor(() => {
expect(SentryClose).toHaveBeenCalled();
expect(mockRemoveValue).toHaveBeenCalledWith();
expect(mockSetValue).toHaveBeenCalledWith('false');
expect(mockSetSecondValue).toHaveBeenCalledWith('true');
});
});
});
@@ -1,25 +1,51 @@
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { useCallback } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { SentryInit, SentryClose } from '@vegaprotocol/logger';
import { useEnvironment } from '@vegaprotocol/environment';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
export const STORAGE_KEY = 'vega_telemetry_approval';
export const STORAGE_SECOND_KEY = 'vega_telemetry_viewed';
export const useTelemetryApproval = (): [
value: boolean,
setValue: (value: boolean) => void
value: string,
setValue: (value: string) => void,
shouldOpen: boolean,
close: () => void
] => {
const { VEGA_ENV, SENTRY_DSN } = useEnvironment();
const [value, setValue, removeValue] = useLocalStorage(STORAGE_KEY);
const setApprove = useCallback(
(value: boolean) => {
if (value && SENTRY_DSN) {
const defaultTelemetryValue =
VEGA_ENV === Networks.MAINNET ? 'false' : 'true';
const [value, setValue] = useLocalStorage(STORAGE_KEY);
const [viewedValue, setViewedValue] = useLocalStorage(STORAGE_SECOND_KEY);
const [shouldOpen, setShouldOpen] = useState(!value || !viewedValue);
const close = useCallback(() => {
setShouldOpen(false);
setViewedValue('true');
}, [setViewedValue]);
const manageValue = useCallback(
(value: string) => {
if (value === 'true' && SENTRY_DSN) {
SentryInit(SENTRY_DSN, VEGA_ENV);
return setValue('1');
return setValue('true');
}
SentryClose();
removeValue();
setValue('false');
},
[setValue, removeValue, SENTRY_DSN, VEGA_ENV]
[setValue, SENTRY_DSN, VEGA_ENV]
);
return [Boolean(value), setApprove];
const setTelemetryValue = useCallback(
(value: string) => {
setShouldOpen(false);
setViewedValue('true');
manageValue(value);
},
[manageValue, setViewedValue]
);
useEffect(() => {
if (!value) {
manageValue(defaultTelemetryValue);
}
}, [value, manageValue, defaultTelemetryValue]);
return [value || '', setTelemetryValue, shouldOpen, close];
};
-2
View File
@@ -4,7 +4,6 @@ import produce from 'immer';
interface GlobalStore {
marketId: string | null;
onBoardingDismissed: boolean;
eagerConnecting: boolean;
update: (store: Partial<Omit<GlobalStore, 'update'>>) => void;
}
@@ -16,7 +15,6 @@ interface PageTitleStore {
export const useGlobalStore = create<GlobalStore>()((set) => ({
marketId: LocalStorage.getItem('marketId') || null,
onBoardingDismissed: false,
eagerConnecting: false,
update: (newState) => {
set(
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/accounts",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/accounts",
"tsConfig": "libs/accounts/tsconfig.lib.json",
"project": "libs/accounts/package.json",
"entryFile": "libs/accounts/src/index.ts",
"external": ["react", "react-dom", "react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/accounts/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-8
View File
@@ -1,8 +0,0 @@
{
"name": "@vegaprotocol/announcements",
"version": "0.0.2",
"peerDependencies": {
"react": "18.2.0",
"react-dom": "18.2.0"
}
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/announcements",
"tsConfig": "libs/announcements/tsconfig.lib.json",
"project": "libs/announcements/package.json",
"entryFile": "libs/announcements/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/announcements/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/apollo-client",
"version": "0.0.1"
}
-10
View File
@@ -4,16 +4,6 @@
"sourceRoot": "libs/apollo-client/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/apollo-client",
"main": "libs/apollo-client/src/index.ts",
"tsConfig": "libs/apollo-client/tsconfig.lib.json",
"assets": ["libs/apollo-client/*.md"]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/assets",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/assets",
"tsConfig": "libs/assets/tsconfig.lib.json",
"project": "libs/assets/package.json",
"entryFile": "libs/assets/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/assets/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+1 -1
View File
@@ -97,7 +97,7 @@ export const AssetDetailsDialog = ({
}}
>
{content}
<p className="text-sm my-4">
<p className="text-xs my-4">
{t(
'There is 1 unit of the settlement asset (%s) to every 1 quote unit.',
[assetSymbol]
+9 -3
View File
@@ -3,7 +3,11 @@ import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import type * as Schema from '@vegaprotocol/types';
import type { KeyValueTableRowProps } from '@vegaprotocol/ui-toolkit';
import { CopyWithTooltip, Icon } from '@vegaprotocol/ui-toolkit';
import {
CopyWithTooltip,
Icon,
truncateMiddle,
} from '@vegaprotocol/ui-toolkit';
import {
KeyValueTable,
KeyValueTableRow,
@@ -56,7 +60,7 @@ export const rows: Rows = [
key: AssetDetail.ID,
label: t('ID'),
tooltip: '',
value: (asset) => asset.id,
value: (asset) => truncateMiddle(asset.id),
},
{
key: AssetDetail.TYPE,
@@ -109,7 +113,9 @@ export const rows: Rows = [
return (
<>
<EtherscanLink address={asset.source.contractAddress} />{' '}
<EtherscanLink address={asset.source.contractAddress}>
{truncateMiddle(asset.source.contractAddress)}
</EtherscanLink>{' '}
<CopyWithTooltip text={asset.source.contractAddress}>
<button title={t('Copy address to clipboard')}>
<Icon size={3} name="duplicate" />
+2 -2
View File
@@ -1,4 +1,4 @@
import { TradingOption } from '@vegaprotocol/ui-toolkit';
import { TradingOption, truncateMiddle } from '@vegaprotocol/ui-toolkit';
import type { AssetFieldsFragment } from './__generated__/Asset';
import classNames from 'classnames';
import { t } from '@vegaprotocol/i18n';
@@ -45,7 +45,7 @@ export const AssetOption = ({ asset, balance }: AssetOptionProps) => {
{balance}
<div className="text-[12px] font-mono w-full text-left break-all">
<span className="text-vega-light-300 dark:text-vega-dark-300">
{asset.id}
{truncateMiddle(asset.id)}
</span>
</div>
</div>
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/candles-chart",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/candles-chart",
"tsConfig": "libs/candles-chart/tsconfig.lib.json",
"project": "libs/candles-chart/package.json",
"entryFile": "libs/candles-chart/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/candles-chart/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
@@ -7,8 +7,8 @@ describe('CandlesMenu', () => {
render(<CandlesMenu />);
await userEvent.click(
screen.getByText('Studies', {
selector: '[type="button"]',
screen.getByRole('button', {
name: 'Studies',
})
);
expect(await screen.findByRole('menu')).toBeInTheDocument();
+61 -51
View File
@@ -10,13 +10,14 @@ import {
studyLabels,
} from 'pennant';
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuItemIndicator,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuTrigger,
TradingButton,
TradingDropdown,
TradingDropdownCheckboxItem,
TradingDropdownContent,
TradingDropdownItemIndicator,
TradingDropdownRadioGroup,
TradingDropdownRadioItem,
TradingDropdownTrigger,
Icon,
} from '@vegaprotocol/ui-toolkit';
import type { IconName } from '@blueprintjs/icons';
@@ -44,69 +45,76 @@ export const CandlesMenu = () => {
} = useCandlesChartSettings();
const triggerClasses = 'text-xs';
const contentAlign = 'end';
const triggerButtonProps = { size: 'extra-small' } as const;
return (
<>
<DropdownMenu
<TradingDropdown
trigger={
<DropdownMenuTrigger className={triggerClasses}>
{t(`Interval: ${intervalLabels[interval]}`)}
</DropdownMenuTrigger>
<TradingDropdownTrigger className={triggerClasses}>
<TradingButton {...triggerButtonProps}>
{t(`Interval: ${intervalLabels[interval]}`)}
</TradingButton>
</TradingDropdownTrigger>
}
>
<DropdownMenuContent align={contentAlign}>
<DropdownMenuRadioGroup
<TradingDropdownContent align={contentAlign}>
<TradingDropdownRadioGroup
value={interval}
onValueChange={(value) => {
setInterval(value as Interval);
}}
>
{Object.values(Interval).map((timeInterval) => (
<DropdownMenuRadioItem
<TradingDropdownRadioItem
key={timeInterval}
inset
value={timeInterval}
>
{intervalLabels[timeInterval]}
<DropdownMenuItemIndicator />
</DropdownMenuRadioItem>
<TradingDropdownItemIndicator />
</TradingDropdownRadioItem>
))}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu
</TradingDropdownRadioGroup>
</TradingDropdownContent>
</TradingDropdown>
<TradingDropdown
trigger={
<DropdownMenuTrigger className={triggerClasses}>
<Icon name={chartTypeIcon.get(chartType) as IconName} />
</DropdownMenuTrigger>
<TradingDropdownTrigger className={triggerClasses}>
<TradingButton {...triggerButtonProps}>
<Icon name={chartTypeIcon.get(chartType) as IconName} />
</TradingButton>
</TradingDropdownTrigger>
}
>
<DropdownMenuContent align={contentAlign}>
<DropdownMenuRadioGroup
<TradingDropdownContent align={contentAlign}>
<TradingDropdownRadioGroup
value={chartType}
onValueChange={(value) => {
setType(value as ChartType);
}}
>
{Object.values(ChartType).map((type) => (
<DropdownMenuRadioItem key={type} inset value={type}>
<TradingDropdownRadioItem key={type} inset value={type}>
{chartTypeLabels[type]}
<DropdownMenuItemIndicator />
</DropdownMenuRadioItem>
<TradingDropdownItemIndicator />
</TradingDropdownRadioItem>
))}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu
</TradingDropdownRadioGroup>
</TradingDropdownContent>
</TradingDropdown>
<TradingDropdown
trigger={
<DropdownMenuTrigger className={triggerClasses}>
{t('Overlays')}
</DropdownMenuTrigger>
<TradingDropdownTrigger className={triggerClasses}>
<TradingButton {...triggerButtonProps}>
{t('Overlays')}
</TradingButton>
</TradingDropdownTrigger>
}
>
<DropdownMenuContent align={contentAlign}>
<TradingDropdownContent align={contentAlign}>
{Object.values(Overlay).map((overlay) => (
<DropdownMenuCheckboxItem
<TradingDropdownCheckboxItem
key={overlay}
checked={overlays.includes(overlay)}
onCheckedChange={() => {
@@ -121,21 +129,23 @@ export const CandlesMenu = () => {
}}
>
{overlayLabels[overlay]}
<DropdownMenuItemIndicator />
</DropdownMenuCheckboxItem>
<TradingDropdownItemIndicator />
</TradingDropdownCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu
</TradingDropdownContent>
</TradingDropdown>
<TradingDropdown
trigger={
<DropdownMenuTrigger className={triggerClasses}>
{t('Studies')}
</DropdownMenuTrigger>
<TradingDropdownTrigger className={triggerClasses}>
<TradingButton {...triggerButtonProps}>
{t('Studies')}
</TradingButton>
</TradingDropdownTrigger>
}
>
<DropdownMenuContent align={contentAlign}>
<TradingDropdownContent align={contentAlign}>
{Object.values(Study).map((study) => (
<DropdownMenuCheckboxItem
<TradingDropdownCheckboxItem
key={study}
checked={studies.includes(study)}
onCheckedChange={() => {
@@ -150,11 +160,11 @@ export const CandlesMenu = () => {
}}
>
{studyLabels[study]}
<DropdownMenuItemIndicator />
</DropdownMenuCheckboxItem>
<TradingDropdownItemIndicator />
</TradingDropdownCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</TradingDropdownContent>
</TradingDropdown>
</>
);
};
@@ -65,6 +65,8 @@ export function addSetVegaWallet() {
Cypress.Commands.add('setVegaWallet', () => {
cy.window().then((win) => {
win.localStorage.setItem('vega_onboarding_viewed', 'true');
win.localStorage.setItem('vega_telemetry_approval', 'false');
win.localStorage.setItem('vega_telemetry_viewed', 'true');
win.localStorage.setItem(
'vega_wallet_config',
JSON.stringify({
@@ -81,6 +83,8 @@ export function addSetOnBoardingViewed() {
Cypress.Commands.add('setOnBoardingViewed', () => {
cy.window().then((win) => {
win.localStorage.setItem('vega_onboarding_viewed', 'true');
win.localStorage.setItem('vega_telemetry_approval', 'false');
win.localStorage.setItem('vega_telemetry_viewed', 'true');
});
});
}
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/data-provider",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/data-provider",
"tsConfig": "libs/data-provider/tsconfig.lib.json",
"project": "libs/data-provider/package.json",
"entryFile": "libs/data-provider/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/data-provider/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/datagrid",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/datagrid",
"tsConfig": "libs/datagrid/tsconfig.lib.json",
"project": "libs/datagrid/package.json",
"entryFile": "libs/datagrid/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/datagrid/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/deal-ticket",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/deal-ticket",
"tsConfig": "libs/deal-ticket/tsconfig.lib.json",
"project": "libs/deal-ticket/package.json",
"entryFile": "libs/deal-ticket/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/deal-ticket/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
@@ -432,9 +432,9 @@ describe('StopOrder', () => {
});
it('sets expiry time/date to now if expiry is changed to checked', async () => {
const now = Math.round(Date.now() / 1000) * 1000;
const now = 24 * 60 * 60 * 1000;
render(generateJsx());
jest.spyOn(global.Date, 'now').mockImplementationOnce(() => now);
jest.spyOn(global.Date, 'now').mockImplementation(() => now);
await userEvent.click(screen.getByTestId(expire));
// expiry time/date was empty it should be set to now
@@ -21,6 +21,8 @@ import {
import * as positionsTools from '@vegaprotocol/positions';
import { OrdersDocument } from '@vegaprotocol/orders';
import { formatForInput } from '@vegaprotocol/utils';
import type { PartialDeep } from 'type-fest';
import type { Market } from '@vegaprotocol/markets';
jest.mock('zustand');
jest.mock('./deal-ticket-fee-details', () => ({
@@ -36,12 +38,19 @@ const market = generateMarket();
const marketData = generateMarketData();
const submit = jest.fn();
function generateJsx(mocks: MockedResponse[] = []) {
function generateJsx(
mocks: MockedResponse[] = [],
marketOverrides: PartialDeep<Market> = {}
) {
const joinedMarket: Market = {
...market,
...marketOverrides,
} as Market;
return (
<MockedProvider mocks={[...mocks]}>
<VegaWalletContext.Provider value={{ pubKey, isReadOnly: false } as any}>
<DealTicket
market={market}
market={joinedMarket}
marketData={marketData}
marketPrice={marketPrice}
submit={submit}
@@ -367,7 +376,6 @@ describe('DealTicket', () => {
expect(screen.getByTestId('iceberg')).toBeDisabled();
});
// eslint-disable-next-line jest/no-disabled-tests
it('handles TIF select box dependent on order type', async () => {
render(generateJsx());
@@ -533,6 +541,25 @@ describe('DealTicket', () => {
expect(screen.queryByTestId(priceErrorMessage)).toBeNull();
});
it('validates size when positionDecimalPlaces is negative', async () => {
render(generateJsx([], { positionDecimalPlaces: -4 }));
const sizeErrorMessage = 'deal-ticket-error-message-size';
const sizeInput = 'order-size';
await userEvent.click(screen.getByTestId('place-order'));
// default value should be invalid
expect(screen.getByTestId(sizeErrorMessage)).toBeInTheDocument();
expect(screen.getByTestId(sizeErrorMessage)).toHaveTextContent(
'Size cannot be lower than 10000'
);
await userEvent.type(screen.getByTestId(sizeInput), '10001');
expect(screen.getByTestId(sizeErrorMessage)).toHaveTextContent(
'Size must be a multiple of 10000 for this market'
);
await userEvent.clear(screen.getByTestId(sizeInput));
await userEvent.type(screen.getByTestId(sizeInput), '10000');
expect(screen.queryByTestId(sizeErrorMessage)).toBeNull();
});
it('validates iceberg field', async () => {
const peakSizeErrorMessage = 'deal-ticket-peak-error-message';
const minimumSizeErrorMessage = 'deal-ticket-minimum-error-message';
@@ -590,9 +617,9 @@ describe('DealTicket', () => {
it('sets expiry time/date to now if expiry is changed to checked', async () => {
const datePicker = 'date-picker-field';
const now = Math.round(Date.now() / 1000) * 1000;
const now = 24 * 60 * 60 * 1000;
render(generateJsx());
jest.spyOn(global.Date, 'now').mockImplementationOnce(() => now);
jest.spyOn(global.Date, 'now').mockImplementation(() => now);
await userEvent.selectOptions(
screen.getByTestId('order-tif'),
Schema.OrderTimeInForce.TIME_IN_FORCE_GTT
@@ -496,11 +496,12 @@ export const DealTicket = ({
onSelect={(value) => {
// If GTT is selected and no expiresAt time is set, or its
// behind current time then reset the value to current time
const now = Date.now();
if (
value === Schema.OrderTimeInForce.TIME_IN_FORCE_GTT &&
(!expiresAt || new Date(expiresAt).getTime() < Date.now())
(!expiresAt || new Date(expiresAt).getTime() < now)
) {
setValue('expiresAt', formatForInput(new Date()), {
setValue('expiresAt', formatForInput(new Date(now)), {
shouldValidate: true,
});
}
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/deposits",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/deposits",
"tsConfig": "libs/deposits/tsconfig.lib.json",
"project": "libs/deposits/package.json",
"entryFile": "libs/deposits/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/deposits/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+15 -2
View File
@@ -2,7 +2,11 @@ import type { Asset } from '@vegaprotocol/assets';
import { EtherscanLink } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
import { formatNumber } from '@vegaprotocol/utils';
import {
formatNumber,
getUnlimitedThreshold,
quantumDecimalPlaces,
} from '@vegaprotocol/utils';
import type { EthStoredTxState } from '@vegaprotocol/web3';
import { EthTxStatus, useEthTransactionStore } from '@vegaprotocol/web3';
import BigNumber from 'bignumber.js';
@@ -188,6 +192,15 @@ const ApprovalTxFeedback = ({
}
if (tx.status === EthTxStatus.Confirmed) {
const approvedAllowanceValue = (
allowance || new BigNumber(0)
).isGreaterThan(getUnlimitedThreshold(selectedAsset.decimals))
? '∞'
: formatNumber(
allowance?.toString() || 0,
quantumDecimalPlaces(selectedAsset.quantum, selectedAsset.decimals)
);
return (
<div className="mb-4">
<Notification
@@ -198,7 +211,7 @@ const ApprovalTxFeedback = ({
<p>
{t('You approved deposits of up to %s %s.', [
selectedAsset?.symbol,
formatNumber(allowance?.toString() || 0),
approvedAllowanceValue,
])}
</p>
{txLink && <p>{txLink}</p>}
+3 -2
View File
@@ -15,6 +15,7 @@ import { useWeb3ConnectStore } from '@vegaprotocol/web3';
import { useWeb3React } from '@web3-react/core';
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
import type { DepositBalances } from './use-deposit-balances';
import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
jest.mock('@vegaprotocol/wallet');
jest.mock('@vegaprotocol/web3');
@@ -90,7 +91,7 @@ describe('Deposit form', () => {
// Assert default values (including) from/to provided by useVegaWallet and useWeb3React
expect(screen.getByText('From (Ethereum address)')).toBeInTheDocument();
expect(screen.getByTestId('ethereum-address')).toHaveTextContent(
MOCK_ETH_ADDRESS
truncateMiddle(MOCK_ETH_ADDRESS)
);
expect(screen.getByLabelText('Asset')).toHaveValue('');
expect(screen.getByLabelText('To (Vega key)')).toHaveValue('');
@@ -353,7 +354,7 @@ describe('Deposit form', () => {
).not.toBeInTheDocument();
expect(screen.getByText('From (Ethereum address)')).toBeInTheDocument();
expect(screen.getByTestId('ethereum-address')).toHaveTextContent(
MOCK_ETH_ADDRESS
truncateMiddle(MOCK_ETH_ADDRESS)
);
});
+2 -1
View File
@@ -22,6 +22,7 @@ import {
Intent,
ButtonLink,
TradingSelect,
truncateMiddle,
} from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useWeb3React } from '@web3-react/core';
@@ -173,7 +174,7 @@ export const DepositForm = ({
return (
<div className="text-sm" aria-describedby="ethereum-address">
<p className="mb-1 break-all" data-testid="ethereum-address">
{account}
{truncateMiddle(account)}
</p>
<DisconnectEthereumButton
onDisconnect={() => {
+10 -4
View File
@@ -7,7 +7,7 @@ import {
Tooltip,
} from '@vegaprotocol/ui-toolkit';
import type BigNumber from 'bignumber.js';
import { formatNumber } from '@vegaprotocol/utils';
import { formatNumber, quantumDecimalPlaces } from '@vegaprotocol/utils';
// Note: all of the values here are with correct asset's decimals
// See `libs/deposits/src/lib/use-deposit-balances.ts`
@@ -35,7 +35,10 @@ export const DepositLimits = ({
label: t('Balance available'),
rawValue: balance,
value: balance ? (
<CompactNumber number={balance} decimals={asset.decimals} />
<CompactNumber
number={balance}
decimals={quantumDecimalPlaces(asset.quantum, asset.decimals)}
/>
) : (
'-'
),
@@ -73,7 +76,7 @@ export const DepositLimits = ({
value: !exempt ? (
<CompactNumber
number={max.minus(deposited)}
decimals={asset.decimals}
decimals={quantumDecimalPlaces(asset.quantum, asset.decimals)}
/>
) : (
<div data-testid="exempt">{t('Exempt')}</div>
@@ -97,7 +100,10 @@ export const DepositLimits = ({
),
rawValue: allowance,
value: allowance ? (
<CompactNumber number={allowance} decimals={asset.decimals} />
<CompactNumber
number={allowance}
decimals={quantumDecimalPlaces(asset.quantum, asset.decimals)}
/>
) : (
'-'
),
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/environment",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/environment",
"tsConfig": "libs/environment/tsconfig.lib.json",
"project": "libs/environment/package.json",
"entryFile": "libs/environment/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/environment/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/fills",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/fills",
"tsConfig": "libs/fills/tsconfig.lib.json",
"project": "libs/fills/package.json",
"entryFile": "libs/fills/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/fills/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+21 -1
View File
@@ -4,7 +4,6 @@ import { getDateTimeFormat } from '@vegaprotocol/utils';
import * as Schema from '@vegaprotocol/types';
import type { PartialDeep } from 'type-fest';
import type { Trade } from './fills-data-provider';
import { FillsTable, getFeesBreakdown } from './fills-table';
import { generateFill } from './test-helpers';
@@ -215,6 +214,27 @@ describe('FillsTable', () => {
).toBeInTheDocument();
});
it('negative positionDecimalPoints should be properly rendered in size column', async () => {
const partyId = 'party-id';
const negativeDecimalPositionFill = generateFill({
...defaultFill,
market: {
...defaultFill.market,
positionDecimalPlaces: -4,
},
});
await act(async () => {
render(
<FillsTable partyId={partyId} rowData={[negativeDecimalPositionFill]} />
);
});
const sizeCell = screen
.getAllByRole('gridcell')
.find((c) => c.getAttribute('col-id') === 'size');
expect(sizeCell).toHaveTextContent('3,000,000,000');
});
describe('getFeesBreakdown', () => {
it('should return correct fees breakdown for a taker', () => {
const fees = {
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-5
View File
@@ -1,5 +0,0 @@
{
"name": "@vegaprotocol/i18n",
"version": "0.0.4",
"type": "commonjs"
}
-21
View File
@@ -4,27 +4,6 @@
"sourceRoot": "libs/i18n/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/i18n",
"main": "libs/i18n/src/index.ts",
"tsConfig": "libs/i18n/tsconfig.lib.json",
"assets": ["libs/i18n/*.md"]
}
},
"publish": {
"executor": "nx:run-commands",
"options": {
"command": "node tools/scripts/publish.mjs i18n {args.ver} {args.tag}"
},
"dependsOn": [
{
"target": "build"
}
]
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/ledger",
"version": "0.0.1"
}
-20
View File
@@ -4,26 +4,6 @@
"sourceRoot": "libs/ledger/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/ledger",
"tsConfig": "libs/ledger/tsconfig.lib.json",
"project": "libs/ledger/package.json",
"entryFile": "libs/ledger/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/ledger/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
+24
View File
@@ -0,0 +1,24 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "commonjs",
"strict": true,
"noInterop": true
},
"sourceMaps": true,
"exclude": ["jest.config.ts",".*\\.spec.tsx?$",".*\\.test.tsx?$","./src/jest-setup.ts$","./**/jest-setup.ts$",".*.js$"]
}
-4
View File
@@ -1,4 +0,0 @@
{
"name": "@vegaprotocol/liquidity",
"version": "0.0.1"
}
-20
View File
@@ -5,26 +5,6 @@
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/liquidity",
"tsConfig": "libs/liquidity/tsconfig.lib.json",
"project": "libs/liquidity/package.json",
"entryFile": "libs/liquidity/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nx/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/liquidity/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],

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