Compare commits
9 Commits
chore/remo
...
develop
Author | SHA1 | Date | |
---|---|---|---|
88264d890d | |||
|
26b78f878b | ||
|
054c0377b4 | ||
|
29bcbd06fb | ||
|
1d721dc748 | ||
|
1d71a839b3 | ||
|
4b917926c5 | ||
|
3a56678403 | ||
|
bcb5351dfc |
@ -4,6 +4,5 @@ tmp/*
|
|||||||
.dockerignore
|
.dockerignore
|
||||||
dockerfiles
|
dockerfiles
|
||||||
node_modules
|
node_modules
|
||||||
.git
|
|
||||||
.github
|
.github
|
||||||
.vscode
|
.vscode
|
||||||
|
28
.verdaccio/config.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# path to a directory with all packages
|
||||||
|
storage: ../tmp/local-registry/storage
|
||||||
|
|
||||||
|
# a list of other known repositories we can talk to
|
||||||
|
uplinks:
|
||||||
|
npmjs:
|
||||||
|
url: https://registry.yarnpkg.com
|
||||||
|
maxage: 60m
|
||||||
|
|
||||||
|
packages:
|
||||||
|
'**':
|
||||||
|
# give all users (including non-authenticated users) full access
|
||||||
|
# because it is a local registry
|
||||||
|
access: $all
|
||||||
|
publish: $all
|
||||||
|
unpublish: $all
|
||||||
|
|
||||||
|
# if package is not available locally, proxy requests to npm registry
|
||||||
|
proxy: npmjs
|
||||||
|
|
||||||
|
# log settings
|
||||||
|
logs:
|
||||||
|
type: stdout
|
||||||
|
format: pretty
|
||||||
|
level: warn
|
||||||
|
|
||||||
|
publish:
|
||||||
|
allow_offline: true # set offline to true to allow publish offline
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../../libs/tailwindcss-config/src/theme');
|
const { theme } = require('../../libs/tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
@ -38,6 +38,7 @@ import { differenceInHours, format, formatDistanceToNowStrict } from 'date-fns';
|
|||||||
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
|
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
|
||||||
import { MarketName } from '../proposal/market-name';
|
import { MarketName } from '../proposal/market-name';
|
||||||
import { Indicator } from '../proposal/indicator';
|
import { Indicator } from '../proposal/indicator';
|
||||||
|
import { type ProposalNode } from '../proposal/proposal-utils';
|
||||||
|
|
||||||
const ProposalTypeTags = ({
|
const ProposalTypeTags = ({
|
||||||
proposal,
|
proposal,
|
||||||
@ -540,10 +541,12 @@ const BatchProposalStateText = ({
|
|||||||
|
|
||||||
export const ProposalHeader = ({
|
export const ProposalHeader = ({
|
||||||
proposal,
|
proposal,
|
||||||
|
restData,
|
||||||
isListItem = true,
|
isListItem = true,
|
||||||
voteState,
|
voteState,
|
||||||
}: {
|
}: {
|
||||||
proposal: Proposal | BatchProposal;
|
proposal: Proposal | BatchProposal;
|
||||||
|
restData?: ProposalNode | null;
|
||||||
isListItem?: boolean;
|
isListItem?: boolean;
|
||||||
voteState?: VoteState | null;
|
voteState?: VoteState | null;
|
||||||
}) => {
|
}) => {
|
||||||
@ -595,7 +598,7 @@ export const ProposalHeader = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ProposalDetails proposal={proposal} />
|
<ProposalDetails proposal={proposal} />
|
||||||
<VoteBreakdown proposal={proposal} />
|
<VoteBreakdown proposal={proposal} restData={restData} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -91,6 +91,28 @@ export type ProposalNode = {
|
|||||||
proposal: ProposalData;
|
proposal: ProposalData;
|
||||||
proposalType: ProposalNodeType;
|
proposalType: ProposalNodeType;
|
||||||
proposals: SubProposalData[];
|
proposals: SubProposalData[];
|
||||||
|
yes?: [
|
||||||
|
{
|
||||||
|
partyId: string;
|
||||||
|
elsPerMarket?: [
|
||||||
|
{
|
||||||
|
marketId: string;
|
||||||
|
els: string;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
no?: [
|
||||||
|
{
|
||||||
|
partyId: string;
|
||||||
|
elsPerMarket?: [
|
||||||
|
{
|
||||||
|
marketId: string;
|
||||||
|
els: string;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
type SingleProposalNode = ProposalNode & {
|
type SingleProposalNode = ProposalNode & {
|
||||||
|
@ -48,6 +48,7 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
|||||||
|
|
||||||
<ProposalHeader
|
<ProposalHeader
|
||||||
proposal={proposal}
|
proposal={proposal}
|
||||||
|
restData={restData}
|
||||||
isListItem={false}
|
isListItem={false}
|
||||||
voteState={voteState}
|
voteState={voteState}
|
||||||
/>
|
/>
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
import { useBatchVoteInformation } from '../../hooks/use-vote-information';
|
import { useBatchVoteInformation } from '../../hooks/use-vote-information';
|
||||||
import { MarketName } from '../proposal/market-name';
|
import { MarketName } from '../proposal/market-name';
|
||||||
import { Indicator } from '../proposal/indicator';
|
import { Indicator } from '../proposal/indicator';
|
||||||
|
import { type ProposalNode } from '../proposal/proposal-utils';
|
||||||
|
|
||||||
export const CompactVotes = ({ number }: { number: BigNumber }) => (
|
export const CompactVotes = ({ number }: { number: BigNumber }) => (
|
||||||
<CompactNumber
|
<CompactNumber
|
||||||
@ -110,24 +111,64 @@ const Status = ({ reached, threshold, text, testId }: StatusProps) => {
|
|||||||
|
|
||||||
export const VoteBreakdown = ({
|
export const VoteBreakdown = ({
|
||||||
proposal,
|
proposal,
|
||||||
|
restData,
|
||||||
}: {
|
}: {
|
||||||
proposal: Proposal | BatchProposal;
|
proposal: Proposal | BatchProposal;
|
||||||
|
restData?: ProposalNode | null;
|
||||||
}) => {
|
}) => {
|
||||||
if (proposal.__typename === 'Proposal') {
|
if (proposal.__typename === 'Proposal') {
|
||||||
return <VoteBreakdownNormal proposal={proposal} />;
|
return <VoteBreakdownNormal proposal={proposal} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proposal.__typename === 'BatchProposal') {
|
if (proposal.__typename === 'BatchProposal') {
|
||||||
return <VoteBreakdownBatch proposal={proposal} />;
|
return <VoteBreakdownBatch proposal={proposal} restData={restData} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
const VoteBreakdownBatch = ({
|
||||||
|
proposal,
|
||||||
|
restData,
|
||||||
|
}: {
|
||||||
|
proposal: BatchProposal;
|
||||||
|
restData?: ProposalNode | null;
|
||||||
|
}) => {
|
||||||
const [fullBreakdown, setFullBreakdown] = useState(false);
|
const [fullBreakdown, setFullBreakdown] = useState(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const yesELS =
|
||||||
|
restData?.yes?.reduce((all, y) => {
|
||||||
|
if (y.elsPerMarket) {
|
||||||
|
y.elsPerMarket.forEach((item) => {
|
||||||
|
const share = Number(item.els);
|
||||||
|
if (all[item.marketId]) {
|
||||||
|
all[item.marketId].push(share);
|
||||||
|
} else {
|
||||||
|
all[item.marketId] = [share];
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
}, {} as Record<string, number[]>) || {};
|
||||||
|
|
||||||
|
const noELS =
|
||||||
|
restData?.no?.reduce((all, y) => {
|
||||||
|
if (y.elsPerMarket) {
|
||||||
|
y.elsPerMarket.forEach((item) => {
|
||||||
|
const share = Number(item.els);
|
||||||
|
if (all[item.marketId]) {
|
||||||
|
all[item.marketId].push(share);
|
||||||
|
} else {
|
||||||
|
all[item.marketId] = [share];
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
}, {} as Record<string, number[]>) || {};
|
||||||
|
|
||||||
const voteInfo = useBatchVoteInformation({
|
const voteInfo = useBatchVoteInformation({
|
||||||
terms: compact(
|
terms: compact(
|
||||||
proposal.subProposals ? proposal.subProposals.map((p) => p?.terms) : []
|
proposal.subProposals ? proposal.subProposals.map((p) => p?.terms) : []
|
||||||
@ -194,6 +235,8 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
|||||||
proposal={proposal}
|
proposal={proposal}
|
||||||
votes={proposal.votes}
|
votes={proposal.votes}
|
||||||
terms={p.terms}
|
terms={p.terms}
|
||||||
|
yesELS={yesELS}
|
||||||
|
noELS={noELS}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -254,6 +297,8 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
|||||||
proposal={proposal}
|
proposal={proposal}
|
||||||
votes={proposal.votes}
|
votes={proposal.votes}
|
||||||
terms={p.terms}
|
terms={p.terms}
|
||||||
|
yesELS={yesELS}
|
||||||
|
noELS={noELS}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -271,17 +316,17 @@ const VoteBreakdownBatchSubProposal = ({
|
|||||||
votes,
|
votes,
|
||||||
terms,
|
terms,
|
||||||
indicator,
|
indicator,
|
||||||
|
yesELS,
|
||||||
|
noELS,
|
||||||
}: {
|
}: {
|
||||||
proposal: BatchProposal;
|
proposal: BatchProposal;
|
||||||
votes: VoteFieldsFragment;
|
votes: VoteFieldsFragment;
|
||||||
terms: ProposalTermsFieldsFragment;
|
terms: ProposalTermsFieldsFragment;
|
||||||
indicator?: number;
|
indicator?: number;
|
||||||
|
yesELS: Record<string, number[]>;
|
||||||
|
noELS: Record<string, number[]>;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const voteInfo = useVoteInformation({
|
|
||||||
votes,
|
|
||||||
terms,
|
|
||||||
});
|
|
||||||
|
|
||||||
const isProposalOpen = proposal?.state === ProposalState.STATE_OPEN;
|
const isProposalOpen = proposal?.state === ProposalState.STATE_OPEN;
|
||||||
const isUpdateMarket = terms?.change?.__typename === 'UpdateMarket';
|
const isUpdateMarket = terms?.change?.__typename === 'UpdateMarket';
|
||||||
@ -294,6 +339,15 @@ const VoteBreakdownBatchSubProposal = ({
|
|||||||
marketId = terms.change.market.id;
|
marketId = terms.change.market.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const voteInfo = useVoteInformation({
|
||||||
|
votes,
|
||||||
|
terms,
|
||||||
|
// yes votes ELS for this specific proposal (market)
|
||||||
|
yesELS: marketId ? yesELS[marketId] : undefined,
|
||||||
|
// no votes ELS for this specific proposal (market)
|
||||||
|
noELS: marketId ? noELS[marketId] : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
const marketName = marketId ? (
|
const marketName = marketId ? (
|
||||||
<>
|
<>
|
||||||
: <MarketName marketId={marketId} />
|
: <MarketName marketId={marketId} />
|
||||||
|
@ -8,13 +8,18 @@ import {
|
|||||||
type VoteFieldsFragment,
|
type VoteFieldsFragment,
|
||||||
} from '../__generated__/Proposals';
|
} from '../__generated__/Proposals';
|
||||||
import { type ProposalChangeType } from '../types';
|
import { type ProposalChangeType } from '../types';
|
||||||
|
import sum from 'lodash/sum';
|
||||||
|
|
||||||
export const useVoteInformation = ({
|
export const useVoteInformation = ({
|
||||||
votes,
|
votes,
|
||||||
terms,
|
terms,
|
||||||
|
yesELS,
|
||||||
|
noELS,
|
||||||
}: {
|
}: {
|
||||||
votes: VoteFieldsFragment;
|
votes: VoteFieldsFragment;
|
||||||
terms: ProposalTermsFieldsFragment;
|
terms: ProposalTermsFieldsFragment;
|
||||||
|
yesELS?: number[];
|
||||||
|
noELS?: number[];
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
appState: { totalSupply, decimals },
|
appState: { totalSupply, decimals },
|
||||||
@ -31,7 +36,9 @@ export const useVoteInformation = ({
|
|||||||
paramsForChange,
|
paramsForChange,
|
||||||
votes,
|
votes,
|
||||||
totalSupply,
|
totalSupply,
|
||||||
decimals
|
decimals,
|
||||||
|
yesELS,
|
||||||
|
noELS
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,7 +79,11 @@ const getVoteData = (
|
|||||||
},
|
},
|
||||||
votes: ProposalFieldsFragment['votes'],
|
votes: ProposalFieldsFragment['votes'],
|
||||||
totalSupply: BigNumber,
|
totalSupply: BigNumber,
|
||||||
decimals: number
|
decimals: number,
|
||||||
|
/** A list of ELS yes votes */
|
||||||
|
yesELS?: number[],
|
||||||
|
/** A list if ELS no votes */
|
||||||
|
noELS?: number[]
|
||||||
) => {
|
) => {
|
||||||
const requiredMajorityPercentage = params.requiredMajority
|
const requiredMajorityPercentage = params.requiredMajority
|
||||||
? new BigNumber(params.requiredMajority).times(100)
|
? new BigNumber(params.requiredMajority).times(100)
|
||||||
@ -86,17 +97,31 @@ const getVoteData = (
|
|||||||
addDecimal(votes.no.totalTokens ?? 0, decimals)
|
addDecimal(votes.no.totalTokens ?? 0, decimals)
|
||||||
);
|
);
|
||||||
|
|
||||||
const noEquityLikeShareWeight = !votes.no.totalEquityLikeShareWeight
|
let noEquityLikeShareWeight = !votes.no.totalEquityLikeShareWeight
|
||||||
? new BigNumber(0)
|
? new BigNumber(0)
|
||||||
: new BigNumber(votes.no.totalEquityLikeShareWeight).times(100);
|
: new BigNumber(votes.no.totalEquityLikeShareWeight).times(100);
|
||||||
|
// there's no meaningful `totalEquityLikeShareWeight` in batch proposals,
|
||||||
|
// it has to be deduced from `elsPerMarket` of `no` votes of given proposal
|
||||||
|
// data. (by REST DATA)
|
||||||
|
if (noELS != null) {
|
||||||
|
const noTotalELS = sum(noELS);
|
||||||
|
noEquityLikeShareWeight = new BigNumber(noTotalELS).times(100);
|
||||||
|
}
|
||||||
|
|
||||||
const yesTokens = new BigNumber(
|
const yesTokens = new BigNumber(
|
||||||
addDecimal(votes.yes.totalTokens ?? 0, decimals)
|
addDecimal(votes.yes.totalTokens ?? 0, decimals)
|
||||||
);
|
);
|
||||||
|
|
||||||
const yesEquityLikeShareWeight = !votes.yes.totalEquityLikeShareWeight
|
let yesEquityLikeShareWeight = !votes.yes.totalEquityLikeShareWeight
|
||||||
? new BigNumber(0)
|
? new BigNumber(0)
|
||||||
: new BigNumber(votes.yes.totalEquityLikeShareWeight).times(100);
|
: new BigNumber(votes.yes.totalEquityLikeShareWeight).times(100);
|
||||||
|
// there's no meaningful `totalEquityLikeShareWeight` in batch proposals,
|
||||||
|
// it has to be deduced from `elsPerMarket` of `yes` votes of given proposal
|
||||||
|
// data. (by REST DATA)
|
||||||
|
if (noELS != null) {
|
||||||
|
const yesTotalELS = sum(yesELS);
|
||||||
|
yesEquityLikeShareWeight = new BigNumber(yesTotalELS).times(100);
|
||||||
|
}
|
||||||
|
|
||||||
const totalTokensVoted = yesTokens.plus(noTokens);
|
const totalTokensVoted = yesTokens.plus(noTokens);
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../../libs/tailwindcss-config/src/theme');
|
const { theme } = require('../../libs/tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
content: [
|
content: [
|
||||||
join(__dirname, 'src/**/*.{js,ts,jsx,tsx}'),
|
join(__dirname, 'src/**/*.{js,ts,jsx,tsx}'),
|
||||||
'libs/ui-toolkit/src/utils/shared.ts',
|
'libs/ui-toolkit/src/utils/shared.ts',
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../../libs/tailwindcss-config/src/theme');
|
const { theme } = require('../../libs/tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 547 B |
Before Width: | Height: | Size: 1.5 KiB |
@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Vega Protocol - Trading",
|
|
||||||
"short_name": "Console",
|
|
||||||
"description": "Vega Protocol - Trading dApp",
|
|
||||||
"start_url": "/",
|
|
||||||
"display": "standalone",
|
|
||||||
"orientation": "portrait",
|
|
||||||
"theme_color": "#000000",
|
|
||||||
"background_color": "#ffffff",
|
|
||||||
"icons": [
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
|
||||||
"type": "image/x-icon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo192.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "192x192"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,63 +1,126 @@
|
|||||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||||
import {
|
import {
|
||||||
AppFailure,
|
|
||||||
AppLoader,
|
AppLoader,
|
||||||
NetworkLoader,
|
NetworkLoader,
|
||||||
NodeFailure,
|
|
||||||
NodeGuard,
|
|
||||||
useEnvironment,
|
useEnvironment,
|
||||||
|
useNodeSwitcherStore,
|
||||||
} from '@vegaprotocol/environment';
|
} from '@vegaprotocol/environment';
|
||||||
import { type ReactNode } from 'react';
|
import { useEffect, type ReactNode, useState } from 'react';
|
||||||
import { Web3Provider } from './web3-provider';
|
import { Web3Provider } from './web3-provider';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
import { DataLoader } from './data-loader';
|
import { DataLoader } from './data-loader';
|
||||||
import { WalletProvider } from '@vegaprotocol/wallet-react';
|
import { WalletProvider } from '@vegaprotocol/wallet-react';
|
||||||
import { useVegaWalletConfig } from '../../lib/hooks/use-vega-wallet-config';
|
import { useVegaWalletConfig } from '../../lib/hooks/use-vega-wallet-config';
|
||||||
|
import { Trans } from 'react-i18next';
|
||||||
|
import { Button, Loader, Splash, VLogo } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
|
const Failure = ({ reason }: { reason?: ReactNode }) => {
|
||||||
|
const t = useT();
|
||||||
|
const setNodeSwitcher = useNodeSwitcherStore((store) => store.setDialogOpen);
|
||||||
|
return (
|
||||||
|
<Splash>
|
||||||
|
<div className="border border-vega-red m-10 mx-auto w-4/5 max-w-3xl rounded-lg overflow-hidden animate-shake">
|
||||||
|
<div className="bg-vega-red text-white px-2 py-2 flex gap-1 items-center font-alpha calt uppercase">
|
||||||
|
<VLogo className="h-4" />
|
||||||
|
<span className="text-lg">{t('Failed to initialize the app')}</span>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 text-left text-sm">
|
||||||
|
<p className="mb-4">{reason}</p>
|
||||||
|
<div className="text-center">
|
||||||
|
<Button className="border-2" onClick={() => setNodeSwitcher(true)}>
|
||||||
|
{t('Change node')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Splash>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Loading = () => {
|
||||||
|
const [showSlowNotification, setShowSlowNotification] = useState(false);
|
||||||
|
const t = useT();
|
||||||
|
const setNodeSwitcher = useNodeSwitcherStore((store) => store.setDialogOpen);
|
||||||
|
useEffect(() => {
|
||||||
|
const to = setTimeout(() => {
|
||||||
|
if (!showSlowNotification) setShowSlowNotification(true);
|
||||||
|
}, 5000);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(to);
|
||||||
|
};
|
||||||
|
}, [showSlowNotification]);
|
||||||
|
return (
|
||||||
|
<Splash>
|
||||||
|
<div className="border border-transparent m-10 mx-auto w-4/5 max-w-3xl rounded-lg overflow-hidden">
|
||||||
|
<div className="mt-11 p-4 text-left text-sm">
|
||||||
|
<Loader />
|
||||||
|
{showSlowNotification && (
|
||||||
|
<>
|
||||||
|
<p className="mt-4 text-center">
|
||||||
|
{t(
|
||||||
|
"It looks like you're connection is slow, try switching to another node."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<div className="mt-4 text-center">
|
||||||
|
<Button
|
||||||
|
className="border-2"
|
||||||
|
onClick={() => setNodeSwitcher(true)}
|
||||||
|
>
|
||||||
|
{t('Change node')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Splash>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Bootstrapper = ({ children }: { children: ReactNode }) => {
|
export const Bootstrapper = ({ children }: { children: ReactNode }) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const { error, VEGA_URL } = useEnvironment();
|
|
||||||
|
const { error, VEGA_URL } = useEnvironment((state) => ({
|
||||||
|
error: state.error,
|
||||||
|
VEGA_URL: state.VEGA_URL,
|
||||||
|
}));
|
||||||
const config = useVegaWalletConfig();
|
const config = useVegaWalletConfig();
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return <AppLoader />;
|
return <AppLoader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ERR_DATA_LOADER = (
|
||||||
|
<Trans
|
||||||
|
i18nKey="It appears that the connection to the node <0>{{VEGA_URL}}</0> does not return necessary data, try switching to another node."
|
||||||
|
components={[
|
||||||
|
<span key="vega" className="text-muted">
|
||||||
|
{VEGA_URL}
|
||||||
|
</span>,
|
||||||
|
]}
|
||||||
|
values={{
|
||||||
|
VEGA_URL,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NetworkLoader
|
<NetworkLoader
|
||||||
cache={cacheConfig}
|
cache={cacheConfig}
|
||||||
skeleton={<AppLoader />}
|
skeleton={<Loading />}
|
||||||
failure={
|
failure={<Failure reason={error} />}
|
||||||
<AppFailure title={t('Could not initialize app')} error={error} />
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<NodeGuard
|
|
||||||
skeleton={<AppLoader />}
|
|
||||||
failure={
|
|
||||||
<NodeFailure
|
|
||||||
title={t('Node: {{VEGA_URL}} is unsuitable', { VEGA_URL })}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<DataLoader
|
<DataLoader
|
||||||
skeleton={<AppLoader />}
|
skeleton={<Loading />}
|
||||||
failure={
|
failure={<Failure reason={ERR_DATA_LOADER} />}
|
||||||
<AppFailure
|
|
||||||
title={t('Could not load market data or asset data')}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Web3Provider
|
<Web3Provider
|
||||||
skeleton={<AppLoader />}
|
skeleton={<Loading />}
|
||||||
failure={
|
failure={<Failure reason={t('Could not configure web3 provider')} />}
|
||||||
<AppFailure title={t('Could not configure web3 provider')} />
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<WalletProvider config={config}>{children}</WalletProvider>
|
<WalletProvider config={config}>{children}</WalletProvider>
|
||||||
</Web3Provider>
|
</Web3Provider>
|
||||||
</DataLoader>
|
</DataLoader>
|
||||||
</NodeGuard>
|
|
||||||
</NetworkLoader>
|
</NetworkLoader>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -107,6 +170,9 @@ const cacheConfig: InMemoryCacheConfig = {
|
|||||||
Fees: {
|
Fees: {
|
||||||
keyFields: false,
|
keyFields: false,
|
||||||
},
|
},
|
||||||
|
PartyProfile: {
|
||||||
|
keyFields: ['partyId'],
|
||||||
|
},
|
||||||
// The folling types are cached by the data provider and not by apollo
|
// The folling types are cached by the data provider and not by apollo
|
||||||
PositionUpdate: {
|
PositionUpdate: {
|
||||||
keyFields: false,
|
keyFields: false,
|
||||||
|
@ -8,6 +8,12 @@ import {
|
|||||||
mockConfig,
|
mockConfig,
|
||||||
MockedWalletProvider,
|
MockedWalletProvider,
|
||||||
} from '@vegaprotocol/wallet-react/testing';
|
} from '@vegaprotocol/wallet-react/testing';
|
||||||
|
import { MockedProvider, type MockedResponse } from '@apollo/react-testing';
|
||||||
|
import {
|
||||||
|
PartyProfilesDocument,
|
||||||
|
type PartyProfilesQuery,
|
||||||
|
type PartyProfilesQueryVariables,
|
||||||
|
} from '../vega-wallet-connect-button/__generated__/PartyProfiles';
|
||||||
|
|
||||||
jest.mock('@vegaprotocol/proposals', () => ({
|
jest.mock('@vegaprotocol/proposals', () => ({
|
||||||
ProtocolUpgradeCountdown: () => null,
|
ProtocolUpgradeCountdown: () => null,
|
||||||
@ -24,15 +30,45 @@ describe('Navbar', () => {
|
|||||||
publicKey: '2'.repeat(64),
|
publicKey: '2'.repeat(64),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const key1Alias = 'key 1 alias';
|
||||||
const marketId = 'abc';
|
const marketId = 'abc';
|
||||||
const navbarContent = 'navbar-menu-content';
|
const navbarContent = 'navbar-menu-content';
|
||||||
|
|
||||||
|
const partyProfilesMock: MockedResponse<
|
||||||
|
PartyProfilesQuery,
|
||||||
|
PartyProfilesQueryVariables
|
||||||
|
> = {
|
||||||
|
request: {
|
||||||
|
query: PartyProfilesDocument,
|
||||||
|
variables: {
|
||||||
|
partyIds: mockKeys.map((k) => k.publicKey),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
partiesProfilesConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
partyId: mockKeys[0].publicKey,
|
||||||
|
alias: key1Alias,
|
||||||
|
metadata: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const renderComponent = (initialEntries?: string[]) => {
|
const renderComponent = (initialEntries?: string[]) => {
|
||||||
return render(
|
return render(
|
||||||
<MemoryRouter initialEntries={initialEntries}>
|
<MemoryRouter initialEntries={initialEntries}>
|
||||||
|
<MockedProvider mocks={[partyProfilesMock]}>
|
||||||
<MockedWalletProvider>
|
<MockedWalletProvider>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
</MockedWalletProvider>
|
</MockedWalletProvider>
|
||||||
|
</MockedProvider>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -140,6 +176,7 @@ describe('Navbar', () => {
|
|||||||
const activeKey = within(menu.getByTestId(/key-1+-mobile/));
|
const activeKey = within(menu.getByTestId(/key-1+-mobile/));
|
||||||
expect(activeKey.getByText(mockKeys[0].name)).toBeInTheDocument();
|
expect(activeKey.getByText(mockKeys[0].name)).toBeInTheDocument();
|
||||||
expect(activeKey.getByTestId('icon-tick')).toBeInTheDocument();
|
expect(activeKey.getByTestId('icon-tick')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(key1Alias)).toBeInTheDocument();
|
||||||
|
|
||||||
const inactiveKey = within(menu.getByTestId(/key-2+-mobile/));
|
const inactiveKey = within(menu.getByTestId(/key-2+-mobile/));
|
||||||
await userEvent.click(inactiveKey.getByText(mockKeys[1].name));
|
await userEvent.click(inactiveKey.getByText(mockKeys[1].name));
|
||||||
|
@ -31,39 +31,27 @@ export const ProfileDialog = () => {
|
|||||||
const pubKey = useProfileDialogStore((store) => store.pubKey);
|
const pubKey = useProfileDialogStore((store) => store.pubKey);
|
||||||
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
||||||
|
|
||||||
const { send, status, error, reset } = useSimpleTransaction({
|
|
||||||
onSuccess: () => {
|
|
||||||
refetch();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const profileEdge = data?.partiesProfilesConnection?.edges.find(
|
const profileEdge = data?.partiesProfilesConnection?.edges.find(
|
||||||
(e) => e.node.partyId === pubKey
|
(e) => e.node.partyId === pubKey
|
||||||
);
|
);
|
||||||
|
|
||||||
const sendTx = (field: FormFields) => {
|
|
||||||
send({
|
|
||||||
updatePartyProfile: {
|
|
||||||
alias: field.alias,
|
|
||||||
metadata: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
setOpen(undefined);
|
setOpen(undefined);
|
||||||
reset();
|
|
||||||
}}
|
}}
|
||||||
title={t('Edit profile')}
|
title={t('Edit profile')}
|
||||||
>
|
>
|
||||||
<ProfileForm
|
<ProfileFormContainer
|
||||||
profile={profileEdge?.node}
|
profile={profileEdge?.node}
|
||||||
status={status}
|
onSuccess={() => {
|
||||||
error={error}
|
refetch();
|
||||||
onSubmit={sendTx}
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setOpen(undefined);
|
||||||
|
}, 1000);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
@ -77,6 +65,32 @@ type Profile = NonNullable<
|
|||||||
PartyProfilesQuery['partiesProfilesConnection']
|
PartyProfilesQuery['partiesProfilesConnection']
|
||||||
>['edges'][number]['node'];
|
>['edges'][number]['node'];
|
||||||
|
|
||||||
|
const ProfileFormContainer = ({
|
||||||
|
profile,
|
||||||
|
onSuccess,
|
||||||
|
}: {
|
||||||
|
profile: Profile | undefined;
|
||||||
|
onSuccess: () => void;
|
||||||
|
}) => {
|
||||||
|
const { send, status, error } = useSimpleTransaction({ onSuccess });
|
||||||
|
const sendTx = (field: FormFields) => {
|
||||||
|
send({
|
||||||
|
updatePartyProfile: {
|
||||||
|
alias: field.alias,
|
||||||
|
metadata: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ProfileForm
|
||||||
|
profile={profile}
|
||||||
|
status={status}
|
||||||
|
error={error}
|
||||||
|
onSubmit={sendTx}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const ProfileForm = ({
|
const ProfileForm = ({
|
||||||
profile,
|
profile,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
@ -114,6 +128,14 @@ const ProfileForm = ({
|
|||||||
|
|
||||||
const errorMessage = errors.alias?.message || error;
|
const errorMessage = errors.alias?.message || error;
|
||||||
|
|
||||||
|
if (status === 'confirmed') {
|
||||||
|
return (
|
||||||
|
<p className="mt-2 mb-4 text-sm text-vega-green-600 dark:text-vega-green">
|
||||||
|
{t('Profile updated')}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)} className="mt-3">
|
<form onSubmit={handleSubmit(onSubmit)} className="mt-3">
|
||||||
<FormGroup label="Alias" labelFor="alias">
|
<FormGroup label="Alias" labelFor="alias">
|
||||||
@ -131,12 +153,6 @@ const ProfileForm = ({
|
|||||||
</p>
|
</p>
|
||||||
</InputError>
|
</InputError>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{status === 'confirmed' && (
|
|
||||||
<p className="mt-2 mb-4 text-sm text-success">
|
|
||||||
{t('Profile updated')}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<TradingButton
|
<TradingButton
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -94,6 +94,7 @@ export const VegaWalletConnectButton = ({
|
|||||||
<KeypairRadioGroup
|
<KeypairRadioGroup
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
pubKeys={pubKeys}
|
pubKeys={pubKeys}
|
||||||
|
activeKey={activeKey?.publicKey}
|
||||||
onSelect={selectPubKey}
|
onSelect={selectPubKey}
|
||||||
/>
|
/>
|
||||||
<TradingDropdownSeparator />
|
<TradingDropdownSeparator />
|
||||||
@ -138,15 +139,18 @@ export const VegaWalletConnectButton = ({
|
|||||||
const KeypairRadioGroup = ({
|
const KeypairRadioGroup = ({
|
||||||
pubKey,
|
pubKey,
|
||||||
pubKeys,
|
pubKeys,
|
||||||
|
activeKey,
|
||||||
onSelect,
|
onSelect,
|
||||||
}: {
|
}: {
|
||||||
pubKey: string | undefined;
|
pubKey: string | undefined;
|
||||||
pubKeys: Key[];
|
pubKeys: Key[];
|
||||||
|
activeKey: string | undefined;
|
||||||
onSelect: (pubKey: string) => void;
|
onSelect: (pubKey: string) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { data } = usePartyProfilesQuery({
|
const { data } = usePartyProfilesQuery({
|
||||||
variables: { partyIds: pubKeys.map((pk) => pk.publicKey) },
|
variables: { partyIds: pubKeys.map((pk) => pk.publicKey) },
|
||||||
skip: pubKeys.length <= 0,
|
skip: pubKeys.length <= 0,
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -156,14 +160,27 @@ const KeypairRadioGroup = ({
|
|||||||
(e) => e.node.partyId === pk.publicKey
|
(e) => e.node.partyId === pk.publicKey
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<KeypairItem key={pk.publicKey} pk={pk} alias={profile?.node.alias} />
|
<KeypairItem
|
||||||
|
key={pk.publicKey}
|
||||||
|
pk={pk}
|
||||||
|
isActive={activeKey === pk.publicKey}
|
||||||
|
alias={profile?.node.alias}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</TradingDropdownRadioGroup>
|
</TradingDropdownRadioGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const KeypairItem = ({ pk, alias }: { pk: Key; alias: string | undefined }) => {
|
const KeypairItem = ({
|
||||||
|
pk,
|
||||||
|
isActive,
|
||||||
|
alias,
|
||||||
|
}: {
|
||||||
|
pk: Key;
|
||||||
|
alias: string | undefined;
|
||||||
|
isActive: boolean;
|
||||||
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const [copied, setCopied] = useCopyTimeout();
|
const [copied, setCopied] = useCopyTimeout();
|
||||||
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
||||||
@ -194,8 +211,13 @@ const KeypairItem = ({ pk, alias }: { pk: Key; alias: string | undefined }) => {
|
|||||||
data-testid={`key-${pk.publicKey}`}
|
data-testid={`key-${pk.publicKey}`}
|
||||||
>
|
>
|
||||||
<Tooltip description={t('Public facing key alias. Click to edit')}>
|
<Tooltip description={t('Public facing key alias. Click to edit')}>
|
||||||
<button data-testid="alias" onClick={() => setOpen(pk.publicKey)}>
|
<button
|
||||||
|
data-testid="alias"
|
||||||
|
onClick={() => setOpen(pk.publicKey)}
|
||||||
|
className="flex items-center gap-1"
|
||||||
|
>
|
||||||
{alias ? alias : t('No alias')}
|
{alias ? alias : t('No alias')}
|
||||||
|
{isActive && <VegaIcon name={VegaIconNames.EDIT} />}
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,6 +12,8 @@ import CopyToClipboard from 'react-copy-to-clipboard';
|
|||||||
import { ViewType, useSidebar } from '../sidebar';
|
import { ViewType, useSidebar } from '../sidebar';
|
||||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
|
import { usePartyProfilesQuery } from '../vega-wallet-connect-button/__generated__/PartyProfiles';
|
||||||
|
import { useProfileDialogStore } from '../../stores/profile-dialog-store';
|
||||||
|
|
||||||
export const VegaWalletMenu = ({
|
export const VegaWalletMenu = ({
|
||||||
setMenu,
|
setMenu,
|
||||||
@ -23,6 +25,12 @@ export const VegaWalletMenu = ({
|
|||||||
const currentRouteId = useGetCurrentRouteId();
|
const currentRouteId = useGetCurrentRouteId();
|
||||||
const setViews = useSidebar((store) => store.setViews);
|
const setViews = useSidebar((store) => store.setViews);
|
||||||
|
|
||||||
|
const { data } = usePartyProfilesQuery({
|
||||||
|
variables: { partyIds: pubKeys.map((pk) => pk.publicKey) },
|
||||||
|
skip: pubKeys.length <= 0,
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
|
});
|
||||||
|
|
||||||
const activeKey = useMemo(() => {
|
const activeKey = useMemo(() => {
|
||||||
return pubKeys?.find((pk) => pk.publicKey === pubKey);
|
return pubKeys?.find((pk) => pk.publicKey === pubKey);
|
||||||
}, [pubKey, pubKeys]);
|
}, [pubKey, pubKeys]);
|
||||||
@ -37,14 +45,21 @@ export const VegaWalletMenu = ({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="grow my-4" role="list">
|
<div className="grow my-4" role="list">
|
||||||
{(pubKeys || []).map((pk) => (
|
{(pubKeys || []).map((pk) => {
|
||||||
|
const profile = data?.partiesProfilesConnection?.edges.find(
|
||||||
|
(e) => e.node.partyId === pk.publicKey
|
||||||
|
);
|
||||||
|
return (
|
||||||
<KeypairListItem
|
<KeypairListItem
|
||||||
key={pk.publicKey}
|
key={pk.publicKey}
|
||||||
pk={pk}
|
pk={pk}
|
||||||
isActive={activeKey?.publicKey === pk.publicKey}
|
isActive={activeKey?.publicKey === pk.publicKey}
|
||||||
onSelectItem={onSelectItem}
|
onSelectItem={onSelectItem}
|
||||||
|
alias={profile?.node.alias}
|
||||||
|
setMenu={setMenu}
|
||||||
/>
|
/>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2 m-4">
|
<div className="flex flex-col gap-2 m-4">
|
||||||
@ -72,18 +87,23 @@ export const VegaWalletMenu = ({
|
|||||||
const KeypairListItem = ({
|
const KeypairListItem = ({
|
||||||
pk,
|
pk,
|
||||||
isActive,
|
isActive,
|
||||||
|
alias,
|
||||||
onSelectItem,
|
onSelectItem,
|
||||||
|
setMenu,
|
||||||
}: {
|
}: {
|
||||||
pk: Key;
|
pk: Key;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
|
alias: string | undefined;
|
||||||
onSelectItem: (pk: string) => void;
|
onSelectItem: (pk: string) => void;
|
||||||
|
setMenu: (open: 'nav' | 'wallet' | null) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const [copied, setCopied] = useCopyTimeout();
|
const [copied, setCopied] = useCopyTimeout();
|
||||||
|
const setOpen = useProfileDialogStore((store) => store.setOpen);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col w-full ml-4 mr-2 mb-4"
|
className="flex flex-col w-full px-4 mb-4"
|
||||||
data-testid={`key-${pk.publicKey}-mobile`}
|
data-testid={`key-${pk.publicKey}-mobile`}
|
||||||
>
|
>
|
||||||
<span className="flex gap-2 items-center mr-2">
|
<span className="flex gap-2 items-center mr-2">
|
||||||
@ -106,6 +126,24 @@ const KeypairListItem = ({
|
|||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
{copied && <span className="text-xs">{t('Copied')}</span>}
|
{copied && <span className="text-xs">{t('Copied')}</span>}
|
||||||
</span>
|
</span>
|
||||||
|
<span
|
||||||
|
className="flex gap-2 items-center"
|
||||||
|
data-testid={`key-${pk.publicKey}`}
|
||||||
|
>
|
||||||
|
<span className="truncate">{alias ? alias : t('No alias')}</span>
|
||||||
|
{isActive && (
|
||||||
|
<button
|
||||||
|
data-testid="alias"
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(pk.publicKey);
|
||||||
|
setMenu(null);
|
||||||
|
}}
|
||||||
|
className="flex items-center gap-1"
|
||||||
|
>
|
||||||
|
<VegaIcon name={VegaIconNames.EDIT} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -9,12 +9,14 @@ from actions.utils import next_epoch, change_keys
|
|||||||
from wallet_config import MM_WALLET
|
from wallet_config import MM_WALLET
|
||||||
from vega_sim.null_service import VegaServiceNull
|
from vega_sim.null_service import VegaServiceNull
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def setup_environment(request, browser) -> Generator[Tuple[Page, str, str], None, None]:
|
def setup_environment(request, browser) -> Generator[Tuple[Page, str, str], None, None]:
|
||||||
with init_vega(request) as vega_instance:
|
with init_vega(request) as vega_instance:
|
||||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||||
|
|
||||||
tDAI_market, tDAI_asset_id = setup_market_with_reward_program(vega_instance)
|
tDAI_market, tDAI_asset_id = setup_market_with_reward_program(
|
||||||
|
vega_instance)
|
||||||
|
|
||||||
with init_page(vega_instance, browser, request) as page:
|
with init_page(vega_instance, browser, request) as page:
|
||||||
risk_accepted_setup(page)
|
risk_accepted_setup(page)
|
||||||
@ -147,14 +149,12 @@ def setup_market_with_reward_program(vega: VegaServiceNull):
|
|||||||
return tDAI_market, tDAI_asset_id
|
return tDAI_market, tDAI_asset_id
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_network_reward_pot(setup_environment: Tuple[Page, str, str],
|
def test_network_reward_pot(setup_environment: Tuple[Page, str, str],
|
||||||
) -> None:
|
) -> None:
|
||||||
page, tDAI_market, tDAI_asset_id = setup_environment
|
page, tDAI_market, tDAI_asset_id = setup_environment
|
||||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("183.33333 tDAI")
|
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("183.33333 tDAI")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_reward_multiplier(
|
def test_reward_multiplier(
|
||||||
setup_environment: Tuple[Page, str, str],
|
setup_environment: Tuple[Page, str, str],
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -168,7 +168,6 @@ def test_reward_multiplier(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_reward_history(
|
def test_reward_history(
|
||||||
setup_environment: Tuple[Page, str, str],
|
setup_environment: Tuple[Page, str, str],
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -177,26 +176,37 @@ def test_reward_history(
|
|||||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||||
"299.99999100.00%"
|
"299.99999100.00%"
|
||||||
)
|
)
|
||||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("299.99999")
|
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(
|
||||||
|
1)).to_have_text("299.99999")
|
||||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||||
"183.33333"
|
"183.33333"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_staking_reward(
|
def test_staking_reward(
|
||||||
page: Page,
|
setup_environment: Tuple[Page, str, str],
|
||||||
):
|
):
|
||||||
|
page, tDAI_market, tDAI_asset_id = setup_environment
|
||||||
expect(page.get_by_test_id("active-rewards-card")).to_have_count(2)
|
expect(page.get_by_test_id("active-rewards-card")).to_have_count(2)
|
||||||
staking_reward_card = page.get_by_test_id("active-rewards-card").nth(1)
|
staking_reward_card = page.get_by_test_id("active-rewards-card").nth(1)
|
||||||
expect(staking_reward_card).to_be_visible()
|
expect(staking_reward_card).to_be_visible()
|
||||||
expect(staking_reward_card.get_by_test_id("entity-scope")).to_have_text("Individual")
|
expect(staking_reward_card.get_by_test_id(
|
||||||
expect(staking_reward_card.get_by_test_id("locked-for")).to_have_text("0 epochs")
|
"entity-scope")).to_have_text("Individual")
|
||||||
expect(staking_reward_card.get_by_test_id("reward-value")).to_have_text("100.00")
|
expect(staking_reward_card.get_by_test_id(
|
||||||
expect(staking_reward_card.get_by_test_id("distribution-strategy")).to_have_text("Pro rata")
|
"locked-for")).to_have_text("0 epochs")
|
||||||
|
expect(staking_reward_card.get_by_test_id(
|
||||||
|
"reward-value")).to_have_text("100.00")
|
||||||
|
expect(staking_reward_card.get_by_test_id(
|
||||||
|
"distribution-strategy")).to_have_text("Pro rata")
|
||||||
expect(staking_reward_card.get_by_test_id("dispatch-metric-info")).to_have_text(
|
expect(staking_reward_card.get_by_test_id("dispatch-metric-info")).to_have_text(
|
||||||
"Staking rewards"
|
"Staking rewards"
|
||||||
)
|
)
|
||||||
expect(staking_reward_card.get_by_test_id("assessed-over")).to_have_text("1 epoch")
|
expect(staking_reward_card.get_by_test_id(
|
||||||
expect(staking_reward_card.get_by_test_id("scope")).to_have_text("Individual")
|
"assessed-over")).to_have_text("1 epoch")
|
||||||
expect(staking_reward_card.get_by_test_id("staking-requirement")).to_have_text("1.00")
|
expect(staking_reward_card.get_by_test_id(
|
||||||
expect(staking_reward_card.get_by_test_id("average-position")).to_have_text("0.00")
|
"scope")).to_have_text("Individual")
|
||||||
|
expect(staking_reward_card.get_by_test_id(
|
||||||
|
"staking-requirement")).to_have_text("1.00")
|
||||||
|
expect(staking_reward_card.get_by_test_id(
|
||||||
|
"average-position")).to_have_text("0.00")
|
||||||
|
@ -39,6 +39,8 @@ const nextConfig = {
|
|||||||
GIT_COMMIT: commitHash,
|
GIT_COMMIT: commitHash,
|
||||||
GIT_TAG: tag,
|
GIT_TAG: tag,
|
||||||
},
|
},
|
||||||
|
basePath: '/apps/vegas', // Set the base path
|
||||||
|
assetPrefix: '/apps/vegas', // Set the asset prefix
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = SENTRY_AUTH_TOKEN
|
module.exports = SENTRY_AUTH_TOKEN
|
||||||
|
@ -4,11 +4,10 @@ export default function Document() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
{/*
|
<meta
|
||||||
meta tags
|
name="viewport"
|
||||||
- next advised against using _document for this, so they exist in our
|
content="width=device-width, initial-scale=1.0, user-scalable=no"
|
||||||
- single page index.page.tsx
|
/>
|
||||||
*/}
|
|
||||||
|
|
||||||
{/* preload fonts */}
|
{/* preload fonts */}
|
||||||
<link
|
<link
|
||||||
@ -18,15 +17,38 @@ export default function Document() {
|
|||||||
type="font/woff"
|
type="font/woff"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<link
|
||||||
|
rel="preload"
|
||||||
|
href="/AlphaLyrae.woff2"
|
||||||
|
as="font"
|
||||||
|
type="font/woff2"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* icons */}
|
{/* icons */}
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
<link rel="apple-touch-icon" content="/favicon.ico" />
|
<link
|
||||||
|
rel="apple-touch-icon"
|
||||||
|
sizes="180x180"
|
||||||
|
href="/apple-touch-icon.png"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="32x32"
|
||||||
|
href="/favicon-32x32.png"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="16x16"
|
||||||
|
href="/favicon-16x16.png"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* scripts */}
|
{/* scripts */}
|
||||||
<script src="/theme-setter.js" type="text/javascript" async />
|
<script src="/theme-setter.js" type="text/javascript" async />
|
||||||
|
|
||||||
{/* manifest */}
|
{/* manifest */}
|
||||||
<link rel="manifest" href="/apps/trading/public/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
</Head>
|
</Head>
|
||||||
<Html>
|
<Html>
|
||||||
<body
|
<body
|
||||||
|
BIN
apps/trading/public/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
apps/trading/public/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
apps/trading/public/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
apps/trading/public/favicon-16x16.png
Normal file
After Width: | Height: | Size: 265 B |
BIN
apps/trading/public/favicon-32x32.png
Normal file
After Width: | Height: | Size: 281 B |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 15 KiB |
@ -9,14 +9,14 @@
|
|||||||
"background_color": "#ffffff",
|
"background_color": "#ffffff",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "favicon.ico",
|
"src": "/android-chrome-192x192.png",
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
"sizes": "192x192",
|
||||||
"type": "image/x-icon"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "cover.png",
|
"src": "/android-chrome-512x512.png",
|
||||||
"type": "image/png",
|
"sizes": "512x512",
|
||||||
"sizes": "192x192"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/next/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/next/tailwind');
|
||||||
const theme = require('../../libs/tailwindcss-config/src/theme');
|
const { theme } = require('../../libs/tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const { getJestProjects } = require('@nx/jest');
|
import { getJestProjects } from '@nx/jest';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
projects: getJestProjects(),
|
projects: getJestProjects(),
|
||||||
|
@ -19,7 +19,6 @@ import {
|
|||||||
TradingButton,
|
TradingButton,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import type { Transfer } from '@vegaprotocol/wallet';
|
import type { Transfer } from '@vegaprotocol/wallet';
|
||||||
import { normalizeTransfer } from '@vegaprotocol/wallet';
|
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
@ -27,6 +26,7 @@ import { Controller, useForm } from 'react-hook-form';
|
|||||||
import { AssetOption, Balance } from '@vegaprotocol/assets';
|
import { AssetOption, Balance } from '@vegaprotocol/assets';
|
||||||
import { AccountType, AccountTypeMapping } from '@vegaprotocol/types';
|
import { AccountType, AccountTypeMapping } from '@vegaprotocol/types';
|
||||||
import { useTransferFeeQuery } from './__generated__/TransferFee';
|
import { useTransferFeeQuery } from './__generated__/TransferFee';
|
||||||
|
import { normalizeTransfer } from './utils';
|
||||||
|
|
||||||
interface FormFields {
|
interface FormFields {
|
||||||
toVegaKey: string;
|
toVegaKey: string;
|
||||||
|
26
libs/accounts/src/lib/utils.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type { Exact } from 'type-fest';
|
||||||
|
import { type Transfer } from '@vegaprotocol/wallet';
|
||||||
|
import { removeDecimal } from '@vegaprotocol/utils';
|
||||||
|
import { type AccountType } from '@vegaprotocol/types';
|
||||||
|
|
||||||
|
export const normalizeTransfer = <T extends Exact<Transfer, T>>(
|
||||||
|
address: string,
|
||||||
|
amount: string,
|
||||||
|
fromAccountType: AccountType,
|
||||||
|
toAccountType: AccountType,
|
||||||
|
asset: {
|
||||||
|
id: string;
|
||||||
|
decimals: number;
|
||||||
|
}
|
||||||
|
): Transfer => {
|
||||||
|
return {
|
||||||
|
to: address,
|
||||||
|
fromAccountType,
|
||||||
|
toAccountType,
|
||||||
|
asset: asset.id,
|
||||||
|
amount: removeDecimal(amount, asset.decimals),
|
||||||
|
// oneOff or recurring required otherwise wallet will error
|
||||||
|
// default oneOff is immediate transfer
|
||||||
|
oneOff: {},
|
||||||
|
};
|
||||||
|
};
|
@ -1,10 +1,9 @@
|
|||||||
import { Controller, type Control } from 'react-hook-form';
|
import { Controller, type Control } from 'react-hook-form';
|
||||||
import type { Market } from '@vegaprotocol/markets';
|
import type { Market } from '@vegaprotocol/markets';
|
||||||
import type { OrderFormValues } from '../../hooks/use-form-values';
|
import type { OrderFormValues } from '../../hooks/use-form-values';
|
||||||
import { toDecimal, useValidateAmount } from '@vegaprotocol/utils';
|
import { determinePriceStep, useValidateAmount } from '@vegaprotocol/utils';
|
||||||
import {
|
import {
|
||||||
TradingFormGroup,
|
TradingFormGroup,
|
||||||
TradingInputError,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
Input,
|
Input,
|
||||||
@ -30,31 +29,7 @@ export const DealTicketPriceTakeProfitStopLoss = ({
|
|||||||
}: DealTicketPriceTakeProfitStopLossProps) => {
|
}: DealTicketPriceTakeProfitStopLossProps) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const validateAmount = useValidateAmount();
|
const validateAmount = useValidateAmount();
|
||||||
const priceStep = toDecimal(market?.decimalPlaces);
|
const priceStep = determinePriceStep(market);
|
||||||
|
|
||||||
const renderTakeProfitError = () => {
|
|
||||||
if (takeProfitError) {
|
|
||||||
return (
|
|
||||||
<TradingInputError testId="deal-ticket-take-profit-error-message">
|
|
||||||
{takeProfitError}
|
|
||||||
</TradingInputError>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderStopLossError = () => {
|
|
||||||
if (stopLossError) {
|
|
||||||
return (
|
|
||||||
<TradingInputError testId="deal-stop-loss-error-message">
|
|
||||||
{stopLossError}
|
|
||||||
</TradingInputError>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
@ -104,9 +79,9 @@ export const DealTicketPriceTakeProfitStopLoss = ({
|
|||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
{fieldState.error && (
|
{(fieldState.error || takeProfitError) && (
|
||||||
<InputError testId="deal-ticket-error-message-price-take-profit">
|
<InputError testId="deal-ticket-error-message-price-take-profit">
|
||||||
{fieldState.error.message}
|
{fieldState.error?.message || takeProfitError}
|
||||||
</InputError>
|
</InputError>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -154,9 +129,9 @@ export const DealTicketPriceTakeProfitStopLoss = ({
|
|||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
{fieldState.error && (
|
{(fieldState.error || stopLossError) && (
|
||||||
<InputError testId="deal-ticket-error-message-price-stop-loss">
|
<InputError testId="deal-ticket-error-message-price-stop-loss">
|
||||||
{fieldState.error.message}
|
{fieldState.error?.message || stopLossError}
|
||||||
</InputError>
|
</InputError>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -165,8 +140,6 @@ export const DealTicketPriceTakeProfitStopLoss = ({
|
|||||||
</TradingFormGroup>
|
</TradingFormGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{renderTakeProfitError()}
|
|
||||||
{renderStopLossError()}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Controller, type Control } from 'react-hook-form';
|
import { Controller, type Control } from 'react-hook-form';
|
||||||
import type { Market } from '@vegaprotocol/markets';
|
import type { Market } from '@vegaprotocol/markets';
|
||||||
import type { OrderFormValues } from '../../hooks/use-form-values';
|
import type { OrderFormValues } from '../../hooks/use-form-values';
|
||||||
import { toDecimal, useValidateAmount } from '@vegaprotocol/utils';
|
import { useValidateAmount } from '@vegaprotocol/utils';
|
||||||
import {
|
import {
|
||||||
TradingFormGroup,
|
TradingFormGroup,
|
||||||
TradingInput,
|
TradingInput,
|
||||||
@ -9,6 +9,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useT } from '../../use-t';
|
import { useT } from '../../use-t';
|
||||||
|
import { determineSizeStep } from '@vegaprotocol/utils';
|
||||||
|
|
||||||
export interface DealTicketSizeIcebergProps {
|
export interface DealTicketSizeIcebergProps {
|
||||||
control: Control<OrderFormValues>;
|
control: Control<OrderFormValues>;
|
||||||
@ -29,7 +30,7 @@ export const DealTicketSizeIceberg = ({
|
|||||||
}: DealTicketSizeIcebergProps) => {
|
}: DealTicketSizeIcebergProps) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const validateAmount = useValidateAmount();
|
const validateAmount = useValidateAmount();
|
||||||
const sizeStep = toDecimal(market?.positionDecimalPlaces);
|
const sizeStep = determineSizeStep(market);
|
||||||
|
|
||||||
const renderPeakSizeError = () => {
|
const renderPeakSizeError = () => {
|
||||||
if (peakSizeError) {
|
if (peakSizeError) {
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
formatForInput,
|
formatForInput,
|
||||||
formatValue,
|
formatValue,
|
||||||
removeDecimal,
|
removeDecimal,
|
||||||
toDecimal,
|
|
||||||
useValidateAmount,
|
useValidateAmount,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { type Control, type UseFormWatch } from 'react-hook-form';
|
import { type Control, type UseFormWatch } from 'react-hook-form';
|
||||||
@ -59,6 +58,7 @@ import { KeyValue } from './key-value';
|
|||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
import { stopOrdersProvider } from '@vegaprotocol/orders';
|
import { stopOrdersProvider } from '@vegaprotocol/orders';
|
||||||
import { useT } from '../../use-t';
|
import { useT } from '../../use-t';
|
||||||
|
import { determinePriceStep, determineSizeStep } from '@vegaprotocol/utils';
|
||||||
|
|
||||||
export interface StopOrderProps {
|
export interface StopOrderProps {
|
||||||
market: Market;
|
market: Market;
|
||||||
@ -904,8 +904,8 @@ export const StopOrder = ({ market, marketPrice, submit }: StopOrderProps) => {
|
|||||||
market.tradableInstrument.instrument.metadata.tags
|
market.tradableInstrument.instrument.metadata.tags
|
||||||
);
|
);
|
||||||
|
|
||||||
const sizeStep = toDecimal(market?.positionDecimalPlaces);
|
const sizeStep = determineSizeStep(market);
|
||||||
const priceStep = toDecimal(market?.decimalPlaces);
|
const priceStep = determinePriceStep(market);
|
||||||
|
|
||||||
useController({
|
useController({
|
||||||
name: 'type',
|
name: 'type',
|
||||||
|
@ -883,7 +883,7 @@ describe('DealTicket', () => {
|
|||||||
'deal-ticket-error-message-price'
|
'deal-ticket-error-message-price'
|
||||||
);
|
);
|
||||||
expect(errorMessage).toHaveTextContent(
|
expect(errorMessage).toHaveTextContent(
|
||||||
'Price accepts up to 2 decimal places'
|
'Price must be a multiple of 0.01 for this market'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -32,7 +32,6 @@ import {
|
|||||||
toBigNum,
|
toBigNum,
|
||||||
removeDecimal,
|
removeDecimal,
|
||||||
useValidateAmount,
|
useValidateAmount,
|
||||||
toDecimal,
|
|
||||||
formatForInput,
|
formatForInput,
|
||||||
formatValue,
|
formatValue,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
@ -82,6 +81,7 @@ import { DocsLinks } from '@vegaprotocol/environment';
|
|||||||
import { useT } from '../../use-t';
|
import { useT } from '../../use-t';
|
||||||
import { DealTicketPriceTakeProfitStopLoss } from './deal-ticket-price-tp-sl';
|
import { DealTicketPriceTakeProfitStopLoss } from './deal-ticket-price-tp-sl';
|
||||||
import uniqueId from 'lodash/uniqueId';
|
import uniqueId from 'lodash/uniqueId';
|
||||||
|
import { determinePriceStep, determineSizeStep } from '@vegaprotocol/utils';
|
||||||
|
|
||||||
export const REDUCE_ONLY_TOOLTIP =
|
export const REDUCE_ONLY_TOOLTIP =
|
||||||
'"Reduce only" will ensure that this order will not increase the size of an open position. When the order is matched, it will only trade enough volume to bring your open volume towards 0 but never change the direction of your position. If applied to a limit order that is not instantly filled, the order will be stopped.';
|
'"Reduce only" will ensure that this order will not increase the size of an open position. When the order is matched, it will only trade enough volume to bring your open volume towards 0 but never change the direction of your position. If applied to a limit order that is not instantly filled, the order will be stopped.';
|
||||||
@ -419,11 +419,12 @@ export const DealTicket = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const priceStep = toDecimal(market?.decimalPlaces);
|
const sizeStep = determineSizeStep(market);
|
||||||
const sizeStep = toDecimal(market?.positionDecimalPlaces);
|
|
||||||
const quoteName = getQuoteName(market);
|
const quoteName = getQuoteName(market);
|
||||||
const isLimitType = type === Schema.OrderType.TYPE_LIMIT;
|
const isLimitType = type === Schema.OrderType.TYPE_LIMIT;
|
||||||
|
|
||||||
|
const priceStep = determinePriceStep(market);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={
|
onSubmit={
|
||||||
|
@ -11,6 +11,7 @@ export function generateMarket(override?: PartialDeep<Market>): Market {
|
|||||||
positionDecimalPlaces: 1,
|
positionDecimalPlaces: 1,
|
||||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
state: Schema.MarketState.STATE_ACTIVE,
|
state: Schema.MarketState.STATE_ACTIVE,
|
||||||
|
tickSize: '1',
|
||||||
marketTimestamps: {
|
marketTimestamps: {
|
||||||
__typename: 'MarketTimestamps',
|
__typename: 'MarketTimestamps',
|
||||||
close: '',
|
close: '',
|
||||||
|
@ -20,5 +20,11 @@
|
|||||||
"jest.config.ts",
|
"jest.config.ts",
|
||||||
"__mocks__"
|
"__mocks__"
|
||||||
],
|
],
|
||||||
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
|
"include": [
|
||||||
|
"**/*.js",
|
||||||
|
"**/*.jsx",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"../utils/src/lib/step.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
|
||||||
|
|
||||||
export const AppFailure = ({
|
|
||||||
title,
|
|
||||||
error,
|
|
||||||
}: {
|
|
||||||
title: string;
|
|
||||||
error?: string | null;
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Splash>
|
|
||||||
<p className="mb-4 text-xl">{title}</p>
|
|
||||||
{error && <p className="mb-8 text-sm">{error}</p>}
|
|
||||||
</Splash>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1 +0,0 @@
|
|||||||
export * from './app-failure';
|
|
@ -1,4 +1,3 @@
|
|||||||
export * from './app-failure';
|
|
||||||
export * from './app-loader';
|
export * from './app-loader';
|
||||||
export * from './network-loader';
|
export * from './network-loader';
|
||||||
export * from './network-switcher';
|
export * from './network-switcher';
|
||||||
|
@ -40,6 +40,16 @@ const mockStatsQuery = (
|
|||||||
vegaTime: new Date().toISOString(),
|
vegaTime: new Date().toISOString(),
|
||||||
chainId: 'test-chain-id',
|
chainId: 'test-chain-id',
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
key: 'a',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -335,6 +345,16 @@ describe('RowData', () => {
|
|||||||
vegaTime: new Date().toISOString(),
|
vegaTime: new Date().toISOString(),
|
||||||
chainId: 'test-chain-id',
|
chainId: 'test-chain-id',
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
key: 'a',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { TradingRadio } from '@vegaprotocol/ui-toolkit';
|
import {
|
||||||
|
CopyWithTooltip,
|
||||||
|
TradingRadio,
|
||||||
|
VegaIcon,
|
||||||
|
VegaIconNames,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { CUSTOM_NODE_KEY } from '../../types';
|
import { CUSTOM_NODE_KEY } from '../../types';
|
||||||
import {
|
import {
|
||||||
@ -127,8 +132,17 @@ export const RowData = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{id !== CUSTOM_NODE_KEY && (
|
{id !== CUSTOM_NODE_KEY && (
|
||||||
<div className="break-all" data-testid="node">
|
<div className="break-all flex gap-2" data-testid="node">
|
||||||
<TradingRadio id={`node-url-${id}`} value={url} label={url} />
|
<TradingRadio id={`node-url-${id}`} value={url} label={url} />
|
||||||
|
{url.length > 0 && url !== 'custom' && (
|
||||||
|
<span className="text-muted">
|
||||||
|
<CopyWithTooltip text={url}>
|
||||||
|
<button>
|
||||||
|
<VegaIcon name={VegaIconNames.COPY} />
|
||||||
|
</button>
|
||||||
|
</CopyWithTooltip>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<LayoutCell
|
<LayoutCell
|
||||||
|
@ -39,6 +39,19 @@ export const getMockStatisticsResult = (
|
|||||||
blockHeight: '11',
|
blockHeight: '11',
|
||||||
vegaTime: new Date().toISOString(),
|
vegaTime: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
__typename: 'NetworkParametersConnection',
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameterEdge',
|
||||||
|
node: {
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'a',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getMockQueryResult = (env: Networks): NodeCheckQuery => ({
|
export const getMockQueryResult = (env: Networks): NodeCheckQuery => ({
|
||||||
@ -48,6 +61,19 @@ export const getMockQueryResult = (env: Networks): NodeCheckQuery => ({
|
|||||||
blockHeight: '11',
|
blockHeight: '11',
|
||||||
vegaTime: new Date().toISOString(),
|
vegaTime: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
__typename: 'NetworkParametersConnection',
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameterEdge',
|
||||||
|
node: {
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'a',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function getHandler<T>(
|
function getHandler<T>(
|
||||||
|
@ -34,6 +34,16 @@ const createDefaultMockClient = () => {
|
|||||||
blockHeight: '100',
|
blockHeight: '100',
|
||||||
vegaTime: new Date().toISOString(),
|
vegaTime: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
key: 'something',
|
||||||
|
value: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
subscribe: () => ({
|
subscribe: () => ({
|
||||||
@ -183,6 +193,16 @@ describe('useEnvironment', () => {
|
|||||||
blockHeight: '100',
|
blockHeight: '100',
|
||||||
vegaTime: new Date(1).toISOString(),
|
vegaTime: new Date(1).toISOString(),
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
key: 'something',
|
||||||
|
value: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, wait);
|
}, wait);
|
||||||
@ -244,6 +264,16 @@ describe('useEnvironment', () => {
|
|||||||
blockHeight: '100',
|
blockHeight: '100',
|
||||||
vegaTime: new Date().toISOString(),
|
vegaTime: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
key: 'something',
|
||||||
|
value: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
subscribe: () => ({
|
subscribe: () => ({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { parse as tomlParse } from 'toml';
|
import { parse as tomlParse } from 'toml';
|
||||||
import { isValidUrl, LocalStorage } from '@vegaprotocol/utils';
|
import { LocalStorage, isValidUrl } from '@vegaprotocol/utils';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { createClient } from '@vegaprotocol/apollo-client';
|
import { createClient } from '@vegaprotocol/apollo-client';
|
||||||
@ -22,6 +22,7 @@ import uniq from 'lodash/uniq';
|
|||||||
import orderBy from 'lodash/orderBy';
|
import orderBy from 'lodash/orderBy';
|
||||||
import first from 'lodash/first';
|
import first from 'lodash/first';
|
||||||
import { canMeasureResponseTime, measureResponseTime } from '../utils/time';
|
import { canMeasureResponseTime, measureResponseTime } from '../utils/time';
|
||||||
|
import compact from 'lodash/compact';
|
||||||
|
|
||||||
type Client = ReturnType<typeof createClient>;
|
type Client = ReturnType<typeof createClient>;
|
||||||
type ClientCollection = {
|
type ClientCollection = {
|
||||||
@ -70,10 +71,19 @@ const fetchConfig = async (url?: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a suitable node by running a test query and test
|
* Find a suitable nodes by running a test query and test
|
||||||
* subscription, against a list of clients, first to resolve wins
|
* subscription, against a list of clients, first to resolve wins
|
||||||
*/
|
*/
|
||||||
const findNode = async (clients: ClientCollection): Promise<string | null> => {
|
const findHealthyNodes = async (nodes: string[]) => {
|
||||||
|
const clients: ClientCollection = {};
|
||||||
|
nodes.forEach((url) => {
|
||||||
|
clients[url] = createClient({
|
||||||
|
url,
|
||||||
|
cacheConfig: undefined,
|
||||||
|
retry: false,
|
||||||
|
connectToDevTools: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
const tests = Object.entries(clients).map((args) => testNode(...args));
|
const tests = Object.entries(clients).map((args) => testNode(...args));
|
||||||
try {
|
try {
|
||||||
const nodes = await Promise.all(tests);
|
const nodes = await Promise.all(tests);
|
||||||
@ -93,11 +103,10 @@ const findNode = async (clients: ClientCollection): Promise<string | null> => {
|
|||||||
['desc', 'desc', 'asc']
|
['desc', 'desc', 'asc']
|
||||||
);
|
);
|
||||||
|
|
||||||
const best = first(ordered);
|
return ordered;
|
||||||
return best ? best.url : null;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// All tests rejected, no suitable node found
|
// All tests rejected, no suitable node found
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -142,6 +151,15 @@ const testQuery = (
|
|||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result && !result.error) {
|
if (result && !result.error) {
|
||||||
|
const netParams = compact(
|
||||||
|
result.data.networkParametersConnection.edges?.map((n) => n?.node)
|
||||||
|
);
|
||||||
|
if (netParams.length === 0) {
|
||||||
|
// any node that doesn't return the network parameters is considered
|
||||||
|
// failed
|
||||||
|
resolve(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const res = {
|
const res = {
|
||||||
blockHeight: Number(result.data.statistics.blockHeight),
|
blockHeight: Number(result.data.statistics.blockHeight),
|
||||||
vegaTime: new Date(result.data.statistics.vegaTime),
|
vegaTime: new Date(result.data.statistics.vegaTime),
|
||||||
@ -600,32 +618,34 @@ export const useEnvironment = create<EnvStore>()((set, get) => ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const state = get();
|
const state = get();
|
||||||
const storedUrl = LocalStorage.getItem(STORAGE_KEY);
|
|
||||||
|
let storedUrl = LocalStorage.getItem(STORAGE_KEY);
|
||||||
|
if (!isValidUrl(storedUrl)) {
|
||||||
|
// remove invalid data from local storage
|
||||||
|
LocalStorage.removeItem(STORAGE_KEY);
|
||||||
|
storedUrl = null;
|
||||||
|
}
|
||||||
|
|
||||||
let nodes: string[] | undefined;
|
let nodes: string[] | undefined;
|
||||||
try {
|
try {
|
||||||
nodes = await fetchConfig(state.VEGA_CONFIG_URL);
|
nodes = uniq(
|
||||||
const enrichedNodes = uniq(
|
compact([
|
||||||
[...nodes, state.VEGA_URL, storedUrl].filter(Boolean) as string[]
|
// url from local storage
|
||||||
|
storedUrl,
|
||||||
|
// url from state (if set via env var)
|
||||||
|
state.VEGA_URL,
|
||||||
|
// urls from network configuration
|
||||||
|
...(await fetchConfig(state.VEGA_CONFIG_URL)),
|
||||||
|
])
|
||||||
);
|
);
|
||||||
set({ nodes: enrichedNodes });
|
set({ nodes });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(`Could not fetch node config from ${state.VEGA_CONFIG_URL}`);
|
console.warn(`Could not fetch node config from ${state.VEGA_CONFIG_URL}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node url found in localStorage, if its valid attempt to connect
|
// skip picking up the best node if VEGA_URL env variable is set
|
||||||
if (storedUrl) {
|
if (state.VEGA_URL && isValidUrl(state.VEGA_URL)) {
|
||||||
if (isValidUrl(storedUrl)) {
|
state.setUrl(state.VEGA_URL);
|
||||||
set({ VEGA_URL: storedUrl, status: 'success' });
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
LocalStorage.removeItem(STORAGE_KEY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// VEGA_URL env var is set and is a valid url no need to proceed
|
|
||||||
if (state.VEGA_URL) {
|
|
||||||
set({ status: 'success' });
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,37 +659,35 @@ export const useEnvironment = create<EnvStore>()((set, get) => ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a map of node urls to client instances
|
const healthyNodes = await findHealthyNodes(nodes);
|
||||||
const clients: ClientCollection = {};
|
|
||||||
nodes.forEach((url) => {
|
|
||||||
clients[url] = createClient({
|
|
||||||
url,
|
|
||||||
cacheConfig: undefined,
|
|
||||||
retry: false,
|
|
||||||
connectToDevTools: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Find a suitable node to connect to by attempting a query and a
|
// A requested node is a node to which the app was previously connected
|
||||||
// subscription, first to fulfill both will be the resulting url.
|
// or the one set via env variable.
|
||||||
const url = await findNode(clients);
|
const requestedNodeUrl = storedUrl || state.VEGA_URL;
|
||||||
|
|
||||||
if (url !== null) {
|
const bestNode = first(healthyNodes);
|
||||||
set({
|
const requestedNode = healthyNodes.find(
|
||||||
status: 'success',
|
(n) => requestedNodeUrl && n.url === requestedNodeUrl
|
||||||
VEGA_URL: url,
|
);
|
||||||
});
|
if (!requestedNode) {
|
||||||
LocalStorage.setItem(STORAGE_KEY, url);
|
// remove unhealthy node url from local storage
|
||||||
|
LocalStorage.removeItem(STORAGE_KEY);
|
||||||
}
|
}
|
||||||
// Every node failed either to make a query or retrieve data from
|
// A node's url (VEGA_URL) is either the requested node (previously
|
||||||
// a subscription
|
// connected or taken form env variable) or the currently best available
|
||||||
else {
|
// node.
|
||||||
|
const url = requestedNode?.url || bestNode?.url;
|
||||||
|
|
||||||
|
if (url != null) {
|
||||||
|
state.setUrl(url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
set({
|
set({
|
||||||
status: 'failed',
|
status: 'failed',
|
||||||
error: 'No node found',
|
error: 'No suitable node found',
|
||||||
});
|
});
|
||||||
console.warn('No suitable vega node was found');
|
console.warn('No suitable node was found');
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -28,6 +28,16 @@ const createStatsMock = (
|
|||||||
blockHeight: blockHeight.toString(),
|
blockHeight: blockHeight.toString(),
|
||||||
vegaTime: '12345',
|
vegaTime: '12345',
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
key: 'a',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,19 @@
|
|||||||
query NodeCheck {
|
query NodeCheck {
|
||||||
|
# statistics needed to get the most recent node in terms of block height
|
||||||
statistics {
|
statistics {
|
||||||
chainId
|
chainId
|
||||||
blockHeight
|
blockHeight
|
||||||
vegaTime
|
vegaTime
|
||||||
}
|
}
|
||||||
|
# net params needed to filter out the nodes that are not suitable
|
||||||
|
networkParametersConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subscription NodeCheckTimeUpdate {
|
subscription NodeCheckTimeUpdate {
|
||||||
|
@ -6,7 +6,7 @@ const defaultOptions = {} as const;
|
|||||||
export type NodeCheckQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
export type NodeCheckQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type NodeCheckQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', chainId: string, blockHeight: string, vegaTime: any } };
|
export type NodeCheckQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', chainId: string, blockHeight: string, vegaTime: any }, networkParametersConnection: { __typename?: 'NetworkParametersConnection', edges?: Array<{ __typename?: 'NetworkParameterEdge', node: { __typename?: 'NetworkParameter', key: string, value: string } } | null> | null } };
|
||||||
|
|
||||||
export type NodeCheckTimeUpdateSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
|
export type NodeCheckTimeUpdateSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
@ -21,6 +21,14 @@ export const NodeCheckDocument = gql`
|
|||||||
blockHeight
|
blockHeight
|
||||||
vegaTime
|
vegaTime
|
||||||
}
|
}
|
||||||
|
networkParametersConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -12,6 +12,19 @@ export const statisticsQuery = (
|
|||||||
blockHeight: '11',
|
blockHeight: '11',
|
||||||
vegaTime: new Date().toISOString(),
|
vegaTime: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
|
networkParametersConnection: {
|
||||||
|
__typename: 'NetworkParametersConnection',
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameterEdge',
|
||||||
|
node: {
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'a',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return merge(defaultResult, override);
|
return merge(defaultResult, override);
|
||||||
|
@ -54,6 +54,7 @@ export const generateFill = (override?: PartialDeep<Trade>) => {
|
|||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
state: MarketState.STATE_ACTIVE,
|
state: MarketState.STATE_ACTIVE,
|
||||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
|
tickSize: '1',
|
||||||
fees: {
|
fees: {
|
||||||
__typename: 'Fees',
|
__typename: 'Fees',
|
||||||
factors: {
|
factors: {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../tailwindcss-config/src/theme');
|
const { theme } = require('../tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
@ -22,7 +22,7 @@ export const generateFundingPayment = (
|
|||||||
decimalPlaces: 5,
|
decimalPlaces: 5,
|
||||||
state: MarketState.STATE_ACTIVE,
|
state: MarketState.STATE_ACTIVE,
|
||||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
|
tickSize: '1',
|
||||||
fees: {
|
fees: {
|
||||||
__typename: 'Fees',
|
__typename: 'Fees',
|
||||||
factors: {
|
factors: {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../tailwindcss-config/src/theme');
|
const { theme } = require('../tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
@ -485,5 +485,7 @@
|
|||||||
"See all the live games on the cards below. Every on-chain game is community funded and designed. <0>Find out how to create one</0>.": "See all the live games on the cards below. Every on-chain game is community funded and designed. <0>Find out how to create one</0>.",
|
"See all the live games on the cards below. Every on-chain game is community funded and designed. <0>Find out how to create one</0>.": "See all the live games on the cards below. Every on-chain game is community funded and designed. <0>Find out how to create one</0>.",
|
||||||
"Teams can earn rewards if they meet the goals set in the on-chain trading competitions. Track your earned rewards here, and see which teams are top of the leaderboard this month.": "Teams can earn rewards if they meet the goals set in the on-chain trading competitions. Track your earned rewards here, and see which teams are top of the leaderboard this month.",
|
"Teams can earn rewards if they meet the goals set in the on-chain trading competitions. Track your earned rewards here, and see which teams are top of the leaderboard this month.": "Teams can earn rewards if they meet the goals set in the on-chain trading competitions. Track your earned rewards here, and see which teams are top of the leaderboard this month.",
|
||||||
"Currently no active games on the network.": "Currently no active games on the network.",
|
"Currently no active games on the network.": "Currently no active games on the network.",
|
||||||
"Currently no active teams on the network.": "Currently no active teams on the network."
|
"Currently no active teams on the network.": "Currently no active teams on the network.",
|
||||||
|
"It looks like you're connection is slow, try switching to another node.": "It looks like you're connection is slow, try switching to another node.",
|
||||||
|
"It appears that the connection to the node <0>{{VEGA_URL}}</0> does not return necessary data, try switching to another node.": "It appears that the connection to the node <0>{{VEGA_URL}}</0> does not return necessary data, try switching to another node."
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../tailwindcss-config/src/theme');
|
const { theme } = require('../tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
5
libs/markets/src/lib/__generated__/markets.ts
generated
@ -139,6 +139,7 @@ query MarketInfo($marketId: ID!) {
|
|||||||
id
|
id
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
positionDecimalPlaces
|
positionDecimalPlaces
|
||||||
|
tickSize
|
||||||
state
|
state
|
||||||
tradingMode
|
tradingMode
|
||||||
linearSlippageFactor
|
linearSlippageFactor
|
||||||
|
@ -23,6 +23,7 @@ import {
|
|||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
|
determinePriceStep,
|
||||||
formatNumber,
|
formatNumber,
|
||||||
formatNumberPercentage,
|
formatNumberPercentage,
|
||||||
getDateTimeFormat,
|
getDateTimeFormat,
|
||||||
@ -320,6 +321,7 @@ export const KeyDetailsInfoPanel = ({
|
|||||||
marketDecimalPlaces: market.decimalPlaces,
|
marketDecimalPlaces: market.decimalPlaces,
|
||||||
positionDecimalPlaces: market.positionDecimalPlaces,
|
positionDecimalPlaces: market.positionDecimalPlaces,
|
||||||
settlementAssetDecimalPlaces: assetDecimals,
|
settlementAssetDecimalPlaces: assetDecimals,
|
||||||
|
tickSize: determinePriceStep(market),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
name: market.tradableInstrument.instrument.name,
|
name: market.tradableInstrument.instrument.name,
|
||||||
@ -330,6 +332,7 @@ export const KeyDetailsInfoPanel = ({
|
|||||||
marketDecimalPlaces: market.decimalPlaces,
|
marketDecimalPlaces: market.decimalPlaces,
|
||||||
positionDecimalPlaces: market.positionDecimalPlaces,
|
positionDecimalPlaces: market.positionDecimalPlaces,
|
||||||
settlementAssetDecimalPlaces: assetDecimals,
|
settlementAssetDecimalPlaces: assetDecimals,
|
||||||
|
tickSize: determinePriceStep(market),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentData={
|
parentData={
|
||||||
|
@ -14,6 +14,7 @@ export const marketInfoQuery = (
|
|||||||
positionDecimalPlaces: 0,
|
positionDecimalPlaces: 0,
|
||||||
state: Schema.MarketState.STATE_ACTIVE,
|
state: Schema.MarketState.STATE_ACTIVE,
|
||||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
|
tickSize: '1',
|
||||||
proposal: {
|
proposal: {
|
||||||
__typename: 'Proposal',
|
__typename: 'Proposal',
|
||||||
id: 'market-0',
|
id: 'market-0',
|
||||||
|
@ -2,6 +2,7 @@ fragment MarketFields on Market {
|
|||||||
id
|
id
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
positionDecimalPlaces
|
positionDecimalPlaces
|
||||||
|
tickSize
|
||||||
state
|
state
|
||||||
tradingMode
|
tradingMode
|
||||||
parentMarketID
|
parentMarketID
|
||||||
|
@ -37,6 +37,7 @@ export const createMarketFragment = (
|
|||||||
positionDecimalPlaces: 0,
|
positionDecimalPlaces: 0,
|
||||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
state: Schema.MarketState.STATE_ACTIVE,
|
state: Schema.MarketState.STATE_ACTIVE,
|
||||||
|
tickSize: '1',
|
||||||
marketTimestamps: {
|
marketTimestamps: {
|
||||||
__typename: 'MarketTimestamps',
|
__typename: 'MarketTimestamps',
|
||||||
close: null,
|
close: null,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../tailwindcss-config/src/theme');
|
const { theme } = require('../tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
@ -11,6 +11,7 @@ export const generateOrder = (partialOrder?: PartialDeep<Order>) => {
|
|||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
id: 'market-id',
|
id: 'market-id',
|
||||||
decimalPlaces: 1,
|
decimalPlaces: 1,
|
||||||
|
tickSize: '1',
|
||||||
fees: {
|
fees: {
|
||||||
__typename: 'Fees',
|
__typename: 'Fees',
|
||||||
factors: {
|
factors: {
|
||||||
|
@ -21,6 +21,7 @@ export const generateStopOrder = (
|
|||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
id: 'market-id',
|
id: 'market-id',
|
||||||
decimalPlaces: 1,
|
decimalPlaces: 1,
|
||||||
|
tickSize: '1',
|
||||||
fees: {
|
fees: {
|
||||||
__typename: 'Fees',
|
__typename: 'Fees',
|
||||||
factors: {
|
factors: {
|
||||||
|
@ -3,7 +3,6 @@ import { type AgGridReact } from 'ag-grid-react';
|
|||||||
import { Pagination, type useDataGridEvents } from '@vegaprotocol/datagrid';
|
import { Pagination, type useDataGridEvents } from '@vegaprotocol/datagrid';
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
import { normalizeOrderAmendment } from '@vegaprotocol/wallet';
|
|
||||||
import { useVegaTransactionStore } from '@vegaprotocol/web3';
|
import { useVegaTransactionStore } from '@vegaprotocol/web3';
|
||||||
import type { OrderTxUpdateFieldsFragment } from '@vegaprotocol/web3';
|
import type { OrderTxUpdateFieldsFragment } from '@vegaprotocol/web3';
|
||||||
import { OrderEditDialog } from '../order-list/order-edit-dialog';
|
import { OrderEditDialog } from '../order-list/order-edit-dialog';
|
||||||
@ -12,6 +11,7 @@ import { OrderViewDialog } from '../order-list/order-view-dialog';
|
|||||||
import { OrderListTable } from '../order-list';
|
import { OrderListTable } from '../order-list';
|
||||||
import { ordersWithMarketProvider } from '../order-data-provider/order-data-provider';
|
import { ordersWithMarketProvider } from '../order-data-provider/order-data-provider';
|
||||||
import { useT } from '../../use-t';
|
import { useT } from '../../use-t';
|
||||||
|
import { normalizeOrderAmendment } from '../../utils';
|
||||||
|
|
||||||
export enum Filter {
|
export enum Filter {
|
||||||
'Open' = 'Open',
|
'Open' = 'Open',
|
||||||
|
@ -17,6 +17,7 @@ describe('OrderEditDialog', () => {
|
|||||||
);
|
);
|
||||||
const editOrder = await screen.findByTestId('edit-order');
|
const editOrder = await screen.findByTestId('edit-order');
|
||||||
const limitPrice = within(editOrder).getByLabelText('Price');
|
const limitPrice = within(editOrder).getByLabelText('Price');
|
||||||
|
await userEvent.clear(limitPrice);
|
||||||
await userEvent.type(limitPrice, '0.111111');
|
await userEvent.type(limitPrice, '0.111111');
|
||||||
const submitButton = within(editOrder).getByRole('button', {
|
const submitButton = within(editOrder).getByRole('button', {
|
||||||
name: 'Update',
|
name: 'Update',
|
||||||
@ -24,7 +25,7 @@ describe('OrderEditDialog', () => {
|
|||||||
await userEvent.click(submitButton);
|
await userEvent.click(submitButton);
|
||||||
const inputErrorText = within(editOrder).getByTestId('input-error-text');
|
const inputErrorText = within(editOrder).getByTestId('input-error-text');
|
||||||
expect(inputErrorText).toHaveTextContent(
|
expect(inputErrorText).toHaveTextContent(
|
||||||
'Price accepts up to 1 decimal places'
|
'Price must be a multiple of 0.1 for this market'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -4,6 +4,8 @@ import {
|
|||||||
addDecimal,
|
addDecimal,
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
useValidateAmount,
|
useValidateAmount,
|
||||||
|
determinePriceStep,
|
||||||
|
determineSizeStep,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { Size } from '@vegaprotocol/datagrid';
|
import { Size } from '@vegaprotocol/datagrid';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
@ -52,8 +54,10 @@ export const OrderEditDialog = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const step = toDecimal(order.market?.decimalPlaces ?? 0);
|
const step = order.market ? determinePriceStep(order.market) : toDecimal(0);
|
||||||
const stepSize = toDecimal(order.market?.positionDecimalPlaces ?? 0);
|
const stepSize = order.market
|
||||||
|
? determineSizeStep(order.market)
|
||||||
|
: toDecimal(0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
@ -117,9 +121,11 @@ export const OrderEditDialog = ({
|
|||||||
required: t('You need to provide a price'),
|
required: t('You need to provide a price'),
|
||||||
validate: {
|
validate: {
|
||||||
min: (value) =>
|
min: (value) =>
|
||||||
Number(value) > 0
|
Number(value) >= Number(step)
|
||||||
? true
|
? true
|
||||||
: t('The price cannot be negative'),
|
: t('Price cannot be lower than {{step}}', {
|
||||||
|
step,
|
||||||
|
}),
|
||||||
validate: validateAmount(step, t('Price')),
|
validate: validateAmount(step, t('Price')),
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
@ -139,7 +145,11 @@ export const OrderEditDialog = ({
|
|||||||
required: t('You need to provide a size'),
|
required: t('You need to provide a size'),
|
||||||
validate: {
|
validate: {
|
||||||
min: (value) =>
|
min: (value) =>
|
||||||
Number(value) > 0 ? true : t('The size cannot be negative'),
|
Number(value) >= Number(stepSize)
|
||||||
|
? true
|
||||||
|
: t('Size cannot be lower than {{stepSize}}', {
|
||||||
|
stepSize,
|
||||||
|
}),
|
||||||
validate: validateAmount(stepSize, t('Size')),
|
validate: validateAmount(stepSize, t('Size')),
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
|
@ -22,6 +22,7 @@ describe('OrderViewDialog', () => {
|
|||||||
positionDecimalPlaces: 3,
|
positionDecimalPlaces: 3,
|
||||||
state: MarketState.STATE_ACTIVE,
|
state: MarketState.STATE_ACTIVE,
|
||||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
|
tickSize: '1',
|
||||||
fees: {
|
fees: {
|
||||||
__typename: 'Fees',
|
__typename: 'Fees',
|
||||||
factors: {
|
factors: {
|
||||||
|
56
libs/orders/src/lib/utils.spec.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { OrderTimeInForce } from '@vegaprotocol/types';
|
||||||
|
import { normalizeOrderAmendment } from './utils';
|
||||||
|
|
||||||
|
describe('normalizeOrderAmendment', () => {
|
||||||
|
type Order = Parameters<typeof normalizeOrderAmendment>[0];
|
||||||
|
type Market = Parameters<typeof normalizeOrderAmendment>[1];
|
||||||
|
const order: Order = {
|
||||||
|
id: '123',
|
||||||
|
timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTT,
|
||||||
|
size: '100',
|
||||||
|
expiresAt: '2022-01-01T00:00:00.000Z',
|
||||||
|
};
|
||||||
|
const market: Market = {
|
||||||
|
id: '456',
|
||||||
|
decimalPlaces: 1,
|
||||||
|
positionDecimalPlaces: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
it('sets and formats order id, market id, expires and timeInForce as given', () => {
|
||||||
|
const orderAmendment = normalizeOrderAmendment(order, market, '1', '1');
|
||||||
|
expect(orderAmendment.orderId).toEqual('123');
|
||||||
|
expect(orderAmendment.marketId).toEqual('456');
|
||||||
|
expect(orderAmendment.expiresAt).toEqual('1640995200000000000');
|
||||||
|
expect(orderAmendment.timeInForce).toEqual(
|
||||||
|
OrderTimeInForce.TIME_IN_FORCE_GTT
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
['1.1', 1, '11'],
|
||||||
|
['1.1', 2, '110'],
|
||||||
|
['0.001', 8, '100000'],
|
||||||
|
])('sets and formats price', (price, decimalPlaces, output) => {
|
||||||
|
const orderAmendment = normalizeOrderAmendment(
|
||||||
|
order,
|
||||||
|
{ ...market, decimalPlaces },
|
||||||
|
price,
|
||||||
|
'1'
|
||||||
|
);
|
||||||
|
expect(orderAmendment.price).toEqual(output);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
['9', 1, -10],
|
||||||
|
['90', 2, 8900],
|
||||||
|
['0.001', 8, 99900],
|
||||||
|
])('sets and formats size delta', (size, positionDecimalPlaces, output) => {
|
||||||
|
const orderAmendment = normalizeOrderAmendment(
|
||||||
|
order,
|
||||||
|
{ ...market, positionDecimalPlaces },
|
||||||
|
'1',
|
||||||
|
size
|
||||||
|
);
|
||||||
|
expect(orderAmendment.sizeDelta).toEqual(output);
|
||||||
|
});
|
||||||
|
});
|
25
libs/orders/src/lib/utils.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import type { Exact } from 'type-fest';
|
||||||
|
import { type OrderAmendment } from '@vegaprotocol/wallet';
|
||||||
|
import { removeDecimal, toNanoSeconds } from '@vegaprotocol/utils';
|
||||||
|
import { type Market, type Order } from '@vegaprotocol/types';
|
||||||
|
|
||||||
|
export const normalizeOrderAmendment = <T extends Exact<OrderAmendment, T>>(
|
||||||
|
order: Pick<Order, 'id' | 'timeInForce' | 'size' | 'expiresAt'>,
|
||||||
|
market: Pick<Market, 'id' | 'decimalPlaces' | 'positionDecimalPlaces'>,
|
||||||
|
price: string,
|
||||||
|
size: string
|
||||||
|
): OrderAmendment => ({
|
||||||
|
orderId: order.id,
|
||||||
|
marketId: market.id,
|
||||||
|
price: removeDecimal(price, market.decimalPlaces),
|
||||||
|
timeInForce: order.timeInForce,
|
||||||
|
sizeDelta: size
|
||||||
|
? new BigNumber(removeDecimal(size, market.positionDecimalPlaces))
|
||||||
|
.minus(order.size)
|
||||||
|
.toNumber()
|
||||||
|
: 0,
|
||||||
|
expiresAt: order.expiresAt
|
||||||
|
? toNanoSeconds(order.expiresAt) // Wallet expects timestamp in nanoseconds
|
||||||
|
: undefined,
|
||||||
|
});
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../tailwindcss-config/src/theme');
|
const { theme } = require('../tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
|
||||||
const theme = require('../tailwindcss-config/src/theme');
|
const { theme } = require('../tailwindcss-config/src/theme');
|
||||||
const vegaCustomClasses = require('../tailwindcss-config/src/vega-custom-classes');
|
const {
|
||||||
|
vegaCustomClasses,
|
||||||
|
} = require('../tailwindcss-config/src/vega-custom-classes');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
@ -13,6 +13,18 @@
|
|||||||
{
|
{
|
||||||
"files": ["*.js", "*.jsx"],
|
"files": ["*.js", "*.jsx"],
|
||||||
"rules": {}
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.json"],
|
||||||
|
"parser": "jsonc-eslint-parser",
|
||||||
|
"rules": {
|
||||||
|
"@nx/dependency-checks": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"ignoredFiles": ["{projectRoot}/rollup.config.{js,ts,mjs,mts}"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
29
libs/tailwindcss-config/.swcrc
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"jsc": {
|
||||||
|
"target": "es2017",
|
||||||
|
"parser": {
|
||||||
|
"syntax": "typescript",
|
||||||
|
"decorators": true,
|
||||||
|
"dynamicImport": true
|
||||||
|
},
|
||||||
|
"transform": {
|
||||||
|
"decoratorMetadata": true,
|
||||||
|
"legacyDecorator": true
|
||||||
|
},
|
||||||
|
"keepClassNames": true,
|
||||||
|
"externalHelpers": true,
|
||||||
|
"loose": true
|
||||||
|
},
|
||||||
|
"module": {
|
||||||
|
"type": "es6"
|
||||||
|
},
|
||||||
|
"sourceMaps": true,
|
||||||
|
"exclude": [
|
||||||
|
"jest.config.ts",
|
||||||
|
".*\\.spec.tsx?$",
|
||||||
|
".*\\.test.tsx?$",
|
||||||
|
"./src/jest-setup.ts$",
|
||||||
|
"./**/jest-setup.ts$",
|
||||||
|
".*.js$"
|
||||||
|
]
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
displayName: 'tailwindcss-config',
|
|
||||||
preset: '../../jest.preset.js',
|
|
||||||
globals: {},
|
|
||||||
transform: {
|
|
||||||
'^.+\\.[tj]s$': [
|
|
||||||
'ts-jest',
|
|
||||||
{
|
|
||||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
|
||||||
coverageDirectory: '../../coverage/libs/tailwindcss-config',
|
|
||||||
};
|
|
@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@vegaprotocol/tailwindcss-config",
|
"name": "@vegaprotocol/tailwindcss-config",
|
||||||
"version": "0.0.5"
|
"version": "0.0.6",
|
||||||
|
"dependencies": {
|
||||||
|
"tailwindcss": "3.3.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,28 +5,30 @@
|
|||||||
"projectType": "library",
|
"projectType": "library",
|
||||||
"targets": {
|
"targets": {
|
||||||
"build": {
|
"build": {
|
||||||
"executor": "@nx/js:tsc",
|
"executor": "@nx/rollup:rollup",
|
||||||
"outputs": ["{options.outputPath}"],
|
"outputs": ["{options.outputPath}"],
|
||||||
"format": ["esm", "cjs"],
|
|
||||||
"options": {
|
"options": {
|
||||||
"outputPath": "dist/libs/tailwindcss-config",
|
"outputPath": "dist/libs/tailwindcss-config",
|
||||||
"main": "libs/tailwindcss-config/src/index.js",
|
"main": "libs/tailwindcss-config/src/index.ts",
|
||||||
"tsConfig": "libs/tailwindcss-config/tsconfig.lib.json",
|
"tsConfig": "libs/tailwindcss-config/tsconfig.lib.json",
|
||||||
"assets": ["libs/tailwindcss-config/*.md"]
|
"assets": [],
|
||||||
|
"project": "libs/tailwindcss-config/package.json",
|
||||||
|
"compiler": "swc",
|
||||||
|
"format": ["esm", "cjs"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"publish": {
|
||||||
|
"command": "node tools/scripts/publish.mjs tailwindcss-config {args.ver} {args.tag}",
|
||||||
|
"dependsOn": ["build"]
|
||||||
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"executor": "@nx/eslint:lint",
|
"executor": "@nx/eslint:lint",
|
||||||
"outputs": ["{options.outputFile}"],
|
"outputs": ["{options.outputFile}"],
|
||||||
"options": {
|
"options": {
|
||||||
"lintFilePatterns": ["libs/tailwindcss-config/**/*.js"]
|
"lintFilePatterns": [
|
||||||
}
|
"libs/tailwindcss-config/**/*.ts",
|
||||||
},
|
"libs/tailwindcss-config/package.json"
|
||||||
"test": {
|
]
|
||||||
"executor": "@nx/jest:jest",
|
|
||||||
"outputs": ["{workspaceRoot}/coverage/libs/tailwindcss-config"],
|
|
||||||
"options": {
|
|
||||||
"jestConfig": "libs/tailwindcss-config/jest.config.js"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
const theme = require('./theme');
|
|
||||||
const themelite = require('./theme-lite');
|
|
||||||
const vegaCustomClasses = require('./vega-custom-classes');
|
|
||||||
const { VegaColours } = require('./vega-colours');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
theme,
|
|
||||||
themelite,
|
|
||||||
plugins: [vegaCustomClasses],
|
|
||||||
VegaColours,
|
|
||||||
};
|
|
4
libs/tailwindcss-config/src/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export { theme } from './theme';
|
||||||
|
export { themeLite } from './theme-lite';
|
||||||
|
export { vegaCustomClasses } from './vega-custom-classes';
|
||||||
|
export { VegaColours } from './vega-colours';
|
@ -1,8 +1,8 @@
|
|||||||
const defaultTheme = require('tailwindcss/defaultTheme');
|
import defaultTheme from 'tailwindcss/defaultTheme';
|
||||||
const colors = require('tailwindcss/colors');
|
import colors from 'tailwindcss/colors';
|
||||||
const theme = require('./theme');
|
import { theme } from './theme';
|
||||||
|
|
||||||
module.exports = {
|
export const themeLite = {
|
||||||
...theme,
|
...theme,
|
||||||
colors: {
|
colors: {
|
||||||
...theme.colors,
|
...theme.colors,
|
@ -1,4 +1,4 @@
|
|||||||
module.exports = {
|
export const theme = {
|
||||||
screens: {
|
screens: {
|
||||||
xs: '500px',
|
xs: '500px',
|
||||||
sm: '640px',
|
sm: '640px',
|
@ -1,4 +1,4 @@
|
|||||||
const VegaColours = {
|
export const VegaColours = {
|
||||||
yellow: {
|
yellow: {
|
||||||
DEFAULT: '#D7FB50',
|
DEFAULT: '#D7FB50',
|
||||||
dark: '#9BE106',
|
dark: '#9BE106',
|
||||||
@ -32,7 +32,3 @@ const VegaColours = {
|
|||||||
400: '#626262',
|
400: '#626262',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
VegaColours,
|
|
||||||
};
|
|
@ -1,8 +1,8 @@
|
|||||||
const plugin = require('tailwindcss/plugin');
|
import plugin from 'tailwindcss/plugin';
|
||||||
const colors = require('tailwindcss/colors');
|
import colors from 'tailwindcss/colors';
|
||||||
const themelite = require('./theme-lite');
|
import { themeLite } from './theme-lite';
|
||||||
|
|
||||||
const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
|
export const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
|
||||||
addUtilities({
|
addUtilities({
|
||||||
'.percent-change-up::before': {
|
'.percent-change-up::before': {
|
||||||
content: ' ',
|
content: ' ',
|
||||||
@ -35,19 +35,19 @@ const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
|
|||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
backgroundColor: 'rgba(0, 143, 74, 0.1)',
|
backgroundColor: 'rgba(0, 143, 74, 0.1)',
|
||||||
border: `1px solid ${themelite.colors.darkerGreen}`,
|
border: `1px solid ${themeLite.colors.darkerGreen}`,
|
||||||
color: themelite.colors.darkerGreen,
|
color: themeLite.colors.darkerGreen,
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: themelite.colors.darkerGreen,
|
backgroundColor: themeLite.colors.darkerGreen,
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
},
|
},
|
||||||
'&.selected': {
|
'&.selected': {
|
||||||
backgroundColor: themelite.colors.darkerGreen,
|
backgroundColor: themeLite.colors.darkerGreen,
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'.buyButtonDark': {
|
'.buyButtonDark': {
|
||||||
color: themelite.colors.darkerGreen,
|
color: themeLite.colors.darkerGreen,
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
color: colors.black,
|
color: colors.black,
|
||||||
},
|
},
|
||||||
@ -59,19 +59,19 @@ const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
|
|||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
backgroundColor: 'rgba(255, 8, 126, 0.1)',
|
backgroundColor: 'rgba(255, 8, 126, 0.1)',
|
||||||
border: `1px solid ${themelite.colors.pink}`,
|
border: `1px solid ${themeLite.colors.pink}`,
|
||||||
color: themelite.colors.pink,
|
color: themeLite.colors.pink,
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
backgroundColor: themelite.colors.pink,
|
backgroundColor: themeLite.colors.pink,
|
||||||
},
|
},
|
||||||
'&.selected': {
|
'&.selected': {
|
||||||
backgroundColor: themelite.colors.pink,
|
backgroundColor: themeLite.colors.pink,
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'.sellButtonDark': {
|
'.sellButtonDark': {
|
||||||
color: themelite.colors.pink,
|
color: themeLite.colors.pink,
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
color: colors.black,
|
color: colors.black,
|
||||||
},
|
},
|
||||||
@ -110,5 +110,3 @@ const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
|
|||||||
// },
|
// },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = vegaCustomClassesLite;
|
|
@ -1,8 +1,8 @@
|
|||||||
const plugin = require('tailwindcss/plugin');
|
import plugin from 'tailwindcss/plugin';
|
||||||
const colors = require('tailwindcss/colors');
|
import colors from 'tailwindcss/colors';
|
||||||
const theme = require('./theme');
|
import { theme } from './theme';
|
||||||
|
|
||||||
const vegaCustomClasses = plugin(function ({ addUtilities }) {
|
export const vegaCustomClasses = plugin(function ({ addUtilities }) {
|
||||||
addUtilities({
|
addUtilities({
|
||||||
'.calt': {
|
'.calt': {
|
||||||
fontFeatureSettings: "'calt'",
|
fontFeatureSettings: "'calt'",
|
||||||
@ -32,7 +32,7 @@ const vegaCustomClasses = plugin(function ({ addUtilities }) {
|
|||||||
'.dark .syntax-highlighter-wrapper .hljs': {
|
'.dark .syntax-highlighter-wrapper .hljs': {
|
||||||
background: theme.colors.vega.cdark[900],
|
background: theme.colors.vega.cdark[900],
|
||||||
color: theme.colors.vega.green.DEFAULT,
|
color: theme.colors.vega.green.DEFAULT,
|
||||||
border: 0,
|
border: '0',
|
||||||
},
|
},
|
||||||
'.syntax-highlighter-wrapper .hljs-literal': {
|
'.syntax-highlighter-wrapper .hljs-literal': {
|
||||||
color: theme.colors.vega.pink.DEFAULT,
|
color: theme.colors.vega.pink.DEFAULT,
|
||||||
@ -60,5 +60,3 @@ const vegaCustomClasses = plugin(function ({ addUtilities }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = vegaCustomClasses;
|
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "./tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../dist/out-tsc",
|
|
||||||
"module": "commonjs",
|
|
||||||
"types": ["jest", "node"]
|
|
||||||
},
|
|
||||||
"include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"@nx/react/babel",
|
|
||||||
{
|
|
||||||
"runtime": "automatic",
|
|
||||||
"useBuiltIns": "usage"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"plugins": []
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
|
"extends": ["../../.eslintrc.json"],
|
||||||
"ignorePatterns": ["!**/*", "__generated__"],
|
"ignorePatterns": ["!**/*", "__generated__"],
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
@ -13,6 +13,18 @@
|
|||||||
{
|
{
|
||||||
"files": ["*.js", "*.jsx"],
|
"files": ["*.js", "*.jsx"],
|
||||||
"rules": {}
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.json"],
|
||||||
|
"parser": "jsonc-eslint-parser",
|
||||||
|
"rules": {
|
||||||
|
"@nx/dependency-checks": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"ignoredFiles": ["{projectRoot}/rollup.config.{js,ts,mjs,mts}"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
29
libs/types/.swcrc
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"jsc": {
|
||||||
|
"target": "es2017",
|
||||||
|
"parser": {
|
||||||
|
"syntax": "typescript",
|
||||||
|
"decorators": true,
|
||||||
|
"dynamicImport": true
|
||||||
|
},
|
||||||
|
"transform": {
|
||||||
|
"decoratorMetadata": true,
|
||||||
|
"legacyDecorator": true
|
||||||
|
},
|
||||||
|
"keepClassNames": true,
|
||||||
|
"externalHelpers": true,
|
||||||
|
"loose": true
|
||||||
|
},
|
||||||
|
"module": {
|
||||||
|
"type": "es6"
|
||||||
|
},
|
||||||
|
"sourceMaps": true,
|
||||||
|
"exclude": [
|
||||||
|
"jest.config.ts",
|
||||||
|
".*\\.spec.tsx?$",
|
||||||
|
".*\\.test.tsx?$",
|
||||||
|
"./src/jest-setup.ts$",
|
||||||
|
"./**/jest-setup.ts$",
|
||||||
|
".*.js$"
|
||||||
|
]
|
||||||
|
}
|
@ -1,11 +1,30 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
|
|
||||||
|
// Reading the SWC compilation config and remove the "exclude"
|
||||||
|
// for the test files to be compiled by SWC
|
||||||
|
const { exclude: _, ...swcJestConfig } = JSON.parse(
|
||||||
|
readFileSync(`${__dirname}/.swcrc`, 'utf-8')
|
||||||
|
);
|
||||||
|
|
||||||
|
// disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves.
|
||||||
|
// If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude"
|
||||||
|
if (swcJestConfig.swcrc === undefined) {
|
||||||
|
swcJestConfig.swcrc = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uncomment if using global setup/teardown files being transformed via swc
|
||||||
|
// https://nx.dev/packages/jest/documents/overview#global-setup/teardown-with-nx-libraries
|
||||||
|
// jest needs EsModule Interop to find the default exported setup/teardown functions
|
||||||
|
// swcJestConfig.module.noInterop = false;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
displayName: 'types',
|
displayName: 'types',
|
||||||
preset: '../../jest.preset.js',
|
preset: '../../jest.preset.js',
|
||||||
transform: {
|
transform: {
|
||||||
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest',
|
'^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
|
||||||
'^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }],
|
|
||||||
},
|
},
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||||
|
testEnvironment: 'node',
|
||||||
coverageDirectory: '../../coverage/libs/types',
|
coverageDirectory: '../../coverage/libs/types',
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@vegaprotocol/types",
|
"name": "@vegaprotocol/types",
|
||||||
"version": "0.0.6"
|
"version": "0.0.7",
|
||||||
|
"dependencies": {},
|
||||||
|
"type": "module",
|
||||||
|
"module": "./index.js"
|
||||||
}
|
}
|
||||||
|
@ -3,38 +3,34 @@
|
|||||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
"sourceRoot": "libs/types/src",
|
"sourceRoot": "libs/types/src",
|
||||||
"projectType": "library",
|
"projectType": "library",
|
||||||
"tags": [],
|
|
||||||
"targets": {
|
"targets": {
|
||||||
"build": {
|
"build": {
|
||||||
"executor": "@nx/rollup:rollup",
|
"executor": "@nx/rollup:rollup",
|
||||||
"outputs": ["{options.outputPath}"],
|
"outputs": ["{options.outputPath}"],
|
||||||
"options": {
|
"options": {
|
||||||
"outputPath": "dist/libs/types",
|
"outputPath": "dist/libs/types",
|
||||||
|
"main": "libs/types/src/index.ts",
|
||||||
"tsConfig": "libs/types/tsconfig.lib.json",
|
"tsConfig": "libs/types/tsconfig.lib.json",
|
||||||
|
"assets": [],
|
||||||
"project": "libs/types/package.json",
|
"project": "libs/types/package.json",
|
||||||
"entryFile": "libs/types/src/index.ts",
|
"compiler": "swc",
|
||||||
"rollupConfig": "@nx/react/plugins/bundle-rollup",
|
"format": ["esm"]
|
||||||
"compiler": "babel",
|
|
||||||
"format": ["esm", "cjs"],
|
|
||||||
"assets": [
|
|
||||||
{
|
|
||||||
"glob": "libs/types/README.md",
|
|
||||||
"input": ".",
|
|
||||||
"output": "."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"publish": {
|
||||||
|
"command": "node tools/scripts/publish.mjs types {args.ver} {args.tag}",
|
||||||
|
"dependsOn": ["build"]
|
||||||
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"executor": "@nx/eslint:lint",
|
"executor": "@nx/eslint:lint",
|
||||||
"outputs": ["{options.outputFile}"],
|
"outputs": ["{options.outputFile}"],
|
||||||
"options": {
|
"options": {
|
||||||
"lintFilePatterns": ["libs/types/**/*.{ts,tsx,js,jsx}"]
|
"lintFilePatterns": ["libs/types/**/*.ts", "libs/types/package.json"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"executor": "@nx/jest:jest",
|
"executor": "@nx/jest:jest",
|
||||||
"outputs": ["{workspaceRoot}/coverage/libs/types"],
|
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||||
"options": {
|
"options": {
|
||||||
"jestConfig": "libs/types/jest.config.ts"
|
"jestConfig": "libs/types/jest.config.ts"
|
||||||
}
|
}
|
||||||
@ -45,6 +41,15 @@
|
|||||||
"commands": ["npx graphql-codegen --config=libs/types/codegen.yml"],
|
"commands": ["npx graphql-codegen --config=libs/types/codegen.yml"],
|
||||||
"parallel": false
|
"parallel": false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"local-registry": {
|
||||||
|
"executor": "@nx/js:verdaccio",
|
||||||
|
"options": {
|
||||||
|
"port": 4873,
|
||||||
|
"config": ".verdaccio/config.yml",
|
||||||
|
"storage": "tmp/local-registry/storage"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tags": []
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"jsx": "react-jsx",
|
"module": "esnext",
|
||||||
"allowJs": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": false,
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
|
"files": [],
|
||||||
"include": [],
|
"include": [],
|
||||||
"references": [
|
"references": [
|
||||||
{
|
{
|
||||||
|
@ -2,22 +2,9 @@
|
|||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../../dist/out-tsc",
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"declaration": true,
|
||||||
"types": ["node"]
|
"types": ["node"]
|
||||||
},
|
},
|
||||||
"files": [
|
"include": ["src/**/*.ts"],
|
||||||
"../../node_modules/@nx/react/typings/cssmodule.d.ts",
|
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
|
||||||
"../../node_modules/@nx/react/typings/image.d.ts"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"**/*.spec.ts",
|
|
||||||
"**/*.test.ts",
|
|
||||||
"**/*.spec.tsx",
|
|
||||||
"**/*.test.tsx",
|
|
||||||
"**/*.spec.js",
|
|
||||||
"**/*.test.js",
|
|
||||||
"**/*.spec.jsx",
|
|
||||||
"**/*.test.jsx",
|
|
||||||
"jest.config.ts"
|
|
||||||
],
|
|
||||||
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
|
|
||||||
}
|
}
|
||||||
|