Task/Strict mode enabled for trading app (#150)
* enable strict mode and fix resulting type errors * fix print affected command * remove assign-deep and use lodash/merge, fix some type errors after enabling strict mode
This commit is contained in:
parent
859dc60133
commit
d4652b3dd8
@ -3,8 +3,8 @@ import { ReactNode } from 'react';
|
||||
|
||||
interface AsyncRendererProps<T> {
|
||||
loading: boolean;
|
||||
error: Error | undefined;
|
||||
data: T;
|
||||
error: Error | undefined | null;
|
||||
data: T | undefined;
|
||||
children: (data: T) => ReactNode;
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ export function AsyncRenderer<T = any>({
|
||||
return <Splash>Something went wrong: {error.message}</Splash>;
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
if (loading || !data) {
|
||||
return <Splash>Loading...</Splash>;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,16 @@
|
||||
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import { DealTicket } from '@vegaprotocol/deal-ticket';
|
||||
import { OrderStatus } from '@vegaprotocol/graphql';
|
||||
import { Market_market, OrderStatus } from '@vegaprotocol/graphql';
|
||||
import { useOrderSubmit } from '../../hooks/use-order-submit';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { VegaTxStatus } from '../../hooks/use-vega-transaction';
|
||||
import { OrderDialog } from './order-dialog';
|
||||
|
||||
export const DealTicketContainer = ({ market }) => {
|
||||
interface DealTicketContainerProps {
|
||||
market: Market_market;
|
||||
}
|
||||
|
||||
export const DealTicketContainer = ({ market }: DealTicketContainerProps) => {
|
||||
const [orderDialogOpen, setOrderDialogOpen] = useState(false);
|
||||
const { submit, transaction, finalizedOrder, reset } = useOrderSubmit(market);
|
||||
|
||||
|
@ -66,10 +66,10 @@ export const OrderDialog = ({
|
||||
icon={<Icon name="tick" size={20} />}
|
||||
>
|
||||
<p>Status: {finalizedOrder.status}</p>
|
||||
<p>Market: {finalizedOrder.market.name}</p>
|
||||
{finalizedOrder.market && <p>Market: {finalizedOrder.market.name}</p>}
|
||||
<p>Type: {finalizedOrder.type}</p>
|
||||
<p>Amount: {finalizedOrder.size}</p>
|
||||
{finalizedOrder.type === 'Limit' && (
|
||||
{finalizedOrder.type === 'Limit' && finalizedOrder.market && (
|
||||
<p>
|
||||
Price:{' '}
|
||||
{formatNumber(
|
||||
|
@ -17,11 +17,7 @@ export const PageQueryContainer = <TData, TVariables = OperationVariables>({
|
||||
const { data, loading, error } = useQuery<TData, TVariables>(query, options);
|
||||
|
||||
return (
|
||||
<AsyncRenderer<TData>
|
||||
loading={loading || Boolean(!data)}
|
||||
error={error}
|
||||
data={data}
|
||||
>
|
||||
<AsyncRenderer<TData> loading={loading} error={error} data={data}>
|
||||
{(data) => children(data)}
|
||||
</AsyncRenderer>
|
||||
);
|
||||
|
@ -33,7 +33,9 @@ export const Web3Content = ({ children, setDialogOpen }: Web3ContentProps) => {
|
||||
const { isActive, error, connector, chainId } = useWeb3React();
|
||||
|
||||
useEffect(() => {
|
||||
connector?.connectEagerly();
|
||||
if (typeof connector?.connectEagerly === 'function') {
|
||||
connector.connectEagerly();
|
||||
}
|
||||
}, [connector]);
|
||||
|
||||
if (error) {
|
||||
|
@ -54,7 +54,7 @@ export const useOrderSubmit = (market: UseOrderSubmitMarket) => {
|
||||
variables: { partyId: keypair?.pub || '' },
|
||||
skip: !id,
|
||||
onSubscriptionData: ({ subscriptionData }) => {
|
||||
if (!subscriptionData.data.busEvents.length) {
|
||||
if (!subscriptionData.data?.busEvents?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -100,9 +100,9 @@ export const useOrderSubmit = (market: UseOrderSubmitMarket) => {
|
||||
orderSubmission: {
|
||||
marketId: market.id,
|
||||
price:
|
||||
order.type === OrderType.Market
|
||||
? undefined
|
||||
: removeDecimal(order.price, market.decimalPlaces),
|
||||
order.type === OrderType.Limit && order.price
|
||||
? removeDecimal(order.price, market.decimalPlaces)
|
||||
: undefined,
|
||||
size: order.size,
|
||||
type: order.type,
|
||||
side: order.side,
|
||||
|
@ -103,11 +103,13 @@ export const useOrders = (): UseOrders => {
|
||||
variables: { partyId: keypair.pub },
|
||||
});
|
||||
|
||||
if (!res.data.party?.orders.length) return;
|
||||
if (!res.data.party?.orders?.length) return;
|
||||
|
||||
mergeOrders(res.data.party.orders);
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
setError(
|
||||
err instanceof Error ? err : new Error('Something went wrong')
|
||||
);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@ -126,6 +128,9 @@ export const useOrders = (): UseOrders => {
|
||||
variables: { partyId: keypair.pub },
|
||||
})
|
||||
.subscribe(({ data }) => {
|
||||
if (!data?.orders) {
|
||||
return;
|
||||
}
|
||||
mergeOrders(data.orders);
|
||||
});
|
||||
|
||||
|
@ -60,7 +60,7 @@ export const useVegaTransaction = () => {
|
||||
} else if ('errors' in res) {
|
||||
handleError(res);
|
||||
return null;
|
||||
} else if (res.tx && res.txHash) {
|
||||
} else if (res.tx?.signature?.value && res.txHash) {
|
||||
setTransaction({
|
||||
status: VegaTxStatus.Pending,
|
||||
hash: res.txHash,
|
||||
|
@ -8,9 +8,15 @@ export function useEagerConnect() {
|
||||
|
||||
useEffect(() => {
|
||||
const cfg = LocalStorage.getItem(WALLET_CONFIG);
|
||||
const cfgObj = JSON.parse(cfg);
|
||||
let cfgObj: { connector: 'rest'; token: string } | null;
|
||||
|
||||
// No stored config, user has never connected or manually cleared storage
|
||||
try {
|
||||
cfgObj = cfg ? JSON.parse(cfg) : null;
|
||||
} catch {
|
||||
cfgObj = null;
|
||||
}
|
||||
|
||||
// No stored config, or config was malformed
|
||||
if (!cfgObj || !cfgObj.connector) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {
|
||||
ApolloClient,
|
||||
ApolloLink,
|
||||
split,
|
||||
from,
|
||||
HttpLink,
|
||||
@ -60,7 +61,7 @@ export function createClient(base?: string) {
|
||||
url: urlWS.href,
|
||||
})
|
||||
)
|
||||
: null;
|
||||
: new ApolloLink((operation, forward) => forward(operation));
|
||||
|
||||
const splitLink = process.browser
|
||||
? split(
|
||||
|
@ -46,21 +46,29 @@ const MARKET_QUERY = gql`
|
||||
`;
|
||||
|
||||
const MarketPage = () => {
|
||||
const {
|
||||
query: { marketId },
|
||||
} = useRouter();
|
||||
const { query } = useRouter();
|
||||
const { w } = useWindowSize();
|
||||
|
||||
// Default to first marketId query item if found
|
||||
const marketId = Array.isArray(query.marketId)
|
||||
? query.marketId[0]
|
||||
: query.marketId;
|
||||
|
||||
if (!marketId) {
|
||||
return (
|
||||
<Splash>
|
||||
<p>Not found</p>
|
||||
</Splash>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<PageQueryContainer<Market, MarketVariables>
|
||||
query={MARKET_QUERY}
|
||||
options={{
|
||||
// Not sure exactly why marketId is string | string[] but just the first item in the array if
|
||||
// it is one
|
||||
variables: {
|
||||
marketId: Array.isArray(marketId) ? marketId[0] : marketId,
|
||||
marketId,
|
||||
},
|
||||
skip: !marketId,
|
||||
fetchPolicy: 'network-only',
|
||||
}}
|
||||
>
|
||||
|
@ -4,21 +4,24 @@ import { useRouter } from 'next/router';
|
||||
import {
|
||||
Children,
|
||||
isValidElement,
|
||||
ReactElement,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
interface GridTabsProps {
|
||||
children: ReactNode;
|
||||
children: ReactElement<GridTabProps>[];
|
||||
group: string;
|
||||
}
|
||||
|
||||
export const GridTabs = ({ children, group }: GridTabsProps) => {
|
||||
const { query, asPath, replace } = useRouter();
|
||||
const [activeTab, setActiveTab] = useState<string>(() => {
|
||||
if (query[group]) {
|
||||
return query[group];
|
||||
const tab = query[group];
|
||||
|
||||
if (typeof tab === 'string') {
|
||||
return tab;
|
||||
}
|
||||
|
||||
// Default to first tab
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { produce } from 'immer';
|
||||
import assign from 'assign-deep';
|
||||
import merge from 'lodash/merge';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useRouter } from 'next/router';
|
||||
import { AsyncRenderer } from '../../components/async-renderer';
|
||||
@ -16,11 +16,11 @@ import type { AgGridReact } from 'ag-grid-react';
|
||||
|
||||
const Markets = () => {
|
||||
const { pathname, push } = useRouter();
|
||||
const [markets, setMarkets] = useState<Markets_markets[]>(undefined);
|
||||
const [markets, setMarkets] = useState<Markets_markets[] | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<Error>(undefined);
|
||||
const [error, setError] = useState<Error>();
|
||||
const client = useApolloClient();
|
||||
const gridRef = useRef<AgGridReact>();
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const initialized = useRef<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
@ -38,7 +38,8 @@ const Markets = () => {
|
||||
const add: Markets_markets[] = [];
|
||||
|
||||
// split into updates and adds
|
||||
if (!gridRef.current) return;
|
||||
if (!gridRef.current || !delta) return;
|
||||
|
||||
const rowNode = gridRef.current.api.getRowNode(
|
||||
getRowNodeId(delta.market)
|
||||
);
|
||||
@ -46,7 +47,7 @@ const Markets = () => {
|
||||
if (rowNode) {
|
||||
const updatedData = produce(
|
||||
rowNode.data.data,
|
||||
(draft: Markets_markets_data) => assign(draft, delta)
|
||||
(draft: Markets_markets_data) => merge(draft, delta)
|
||||
);
|
||||
if (updatedData !== rowNode.data.data) {
|
||||
update.push({ ...rowNode.data, data: delta });
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Market_market } from '@vegaprotocol/graphql';
|
||||
import classNames from 'classnames';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import { useState, ReactNode } from 'react';
|
||||
import { useState, ReactNode, ComponentType } from 'react';
|
||||
import { GridTab, GridTabs } from './grid-tabs';
|
||||
import { DealTicketContainer } from '../../components/deal-ticket-container';
|
||||
import { OrderListContainer } from '../..//components/order-list-container';
|
||||
@ -33,18 +33,28 @@ const Trades = () => (
|
||||
</Splash>
|
||||
);
|
||||
|
||||
type TradingView = keyof typeof TradingViews;
|
||||
// enum TradingView {
|
||||
// Chart = 'Chart',
|
||||
// Ticket = 'Ticket',
|
||||
// Orderbook = 'Orderbook',
|
||||
// Orders = 'Orders',
|
||||
// Positions = 'Positions',
|
||||
// Collateral = 'Collateral',
|
||||
// Trades = 'Trades',
|
||||
// }
|
||||
|
||||
const TradingViews = {
|
||||
chart: Chart,
|
||||
ticket: DealTicketContainer,
|
||||
orderbook: Orderbook,
|
||||
orders: OrderListContainer,
|
||||
positions: Positions,
|
||||
collateral: Collateral,
|
||||
trades: Trades,
|
||||
Chart: Chart,
|
||||
Ticket: DealTicketContainer,
|
||||
Orderbook: Orderbook,
|
||||
Orders: OrderListContainer,
|
||||
Positions: Positions,
|
||||
Collateral: Collateral,
|
||||
Trades: Trades,
|
||||
};
|
||||
|
||||
type TradingView = keyof typeof TradingViews;
|
||||
|
||||
interface TradeGridProps {
|
||||
market: Market_market;
|
||||
}
|
||||
@ -62,31 +72,31 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
|
||||
<h1>Market: {market.name}</h1>
|
||||
</header>
|
||||
<TradeGridChild className="col-start-1 col-end-2">
|
||||
<TradingViews.chart />
|
||||
<TradingViews.Chart />
|
||||
</TradeGridChild>
|
||||
<TradeGridChild className="row-start-1 row-end-3">
|
||||
<TradingViews.ticket market={market} />
|
||||
<TradingViews.Ticket market={market} />
|
||||
</TradeGridChild>
|
||||
<TradeGridChild className="row-start-1 row-end-3">
|
||||
<GridTabs group="trade">
|
||||
<GridTab name="trades">
|
||||
<TradingViews.trades />
|
||||
<TradingViews.Trades />
|
||||
</GridTab>
|
||||
<GridTab name="orderbook">
|
||||
<TradingViews.orderbook />
|
||||
<TradingViews.Orderbook />
|
||||
</GridTab>
|
||||
</GridTabs>
|
||||
</TradeGridChild>
|
||||
<TradeGridChild className="col-span-3">
|
||||
<GridTabs group="portfolio">
|
||||
<GridTab name="orders">
|
||||
<TradingViews.orders />
|
||||
<TradingViews.Orders />
|
||||
</GridTab>
|
||||
<GridTab name="positions">
|
||||
<TradingViews.positions />
|
||||
<TradingViews.Positions />
|
||||
</GridTab>
|
||||
<GridTab name="collateral">
|
||||
<TradingViews.collateral />
|
||||
<TradingViews.Collateral />
|
||||
</GridTab>
|
||||
</GridTabs>
|
||||
</TradeGridChild>
|
||||
@ -119,7 +129,7 @@ interface TradePanelsProps {
|
||||
}
|
||||
|
||||
export const TradePanels = ({ market }: TradePanelsProps) => {
|
||||
const [view, setView] = useState<TradingView>('chart');
|
||||
const [view, setView] = useState<TradingView>('Chart');
|
||||
|
||||
const renderView = () => {
|
||||
const Component = TradingViews[view];
|
||||
@ -144,7 +154,7 @@ export const TradePanels = ({ market }: TradePanelsProps) => {
|
||||
</AutoSizer>
|
||||
</div>
|
||||
<div className="flex flex-nowrap gap-4 overflow-x-auto my-4 max-w-full">
|
||||
{Object.keys(TradingViews).map((key: TradingView) => {
|
||||
{Object.keys(TradingViews).map((key) => {
|
||||
const isActive = view === key;
|
||||
const className = classNames('py-4', 'px-12', 'capitalize', {
|
||||
'text-black dark:text-vega-yellow': isActive,
|
||||
@ -154,7 +164,7 @@ export const TradePanels = ({ market }: TradePanelsProps) => {
|
||||
});
|
||||
return (
|
||||
<button
|
||||
onClick={() => setView(key)}
|
||||
onClick={() => setView(key as TradingView)}
|
||||
className={className}
|
||||
key={key}
|
||||
>
|
||||
|
@ -13,14 +13,14 @@ const Deposit = () => {
|
||||
};
|
||||
|
||||
const Info = () => {
|
||||
const { isActive, chainId, accounts } = useWeb3React();
|
||||
const { isActive, chainId, account } = useWeb3React();
|
||||
if (!isActive) {
|
||||
return <div>Not active</div>;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<p>{chainId}</p>
|
||||
<p>{accounts[0]}</p>
|
||||
<p>{account ? account : 'No account'}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"types": ["node", "jest"],
|
||||
"strict": false,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true,
|
||||
|
@ -1,6 +1,6 @@
|
||||
const currentProject = process.env.NX_PROJECT_NAME;
|
||||
const execSync = require('child_process').execSync;
|
||||
const getAffected = `nx print-affected`;
|
||||
const getAffected = `npx nx print-affected`;
|
||||
const output = execSync(getAffected).toString();
|
||||
//get the list of changed projects from the output
|
||||
const changedProjects = JSON.parse(output).projects; // array of affected projects
|
||||
|
@ -5,10 +5,9 @@ import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||
import { Markets_markets } from '@vegaprotocol/graphql';
|
||||
import { AgGridColumn } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
interface MarketListTableProps {
|
||||
markets: Markets_markets[];
|
||||
markets: Markets_markets[] | null;
|
||||
onRowClicked: (marketId: string) => void;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
"ag-grid-community": "^27.0.1",
|
||||
"ag-grid-react": "^27.0.1",
|
||||
"apollo": "^2.33.9",
|
||||
"assign-deep": "^1.0.1",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"bignumber.js": "^9.0.2",
|
||||
"classnames": "^2.3.1",
|
||||
@ -41,8 +40,8 @@
|
||||
"ethers": "^5.6.0",
|
||||
"graphql": "^15.7.2",
|
||||
"graphql-ws": "^5.6.3",
|
||||
"lodash": "^4.17.21",
|
||||
"immer": "^9.0.12",
|
||||
"lodash": "^4.17.21",
|
||||
"next": "12.0.7",
|
||||
"nx": "^13.8.3",
|
||||
"postcss": "^8.4.6",
|
||||
@ -89,6 +88,7 @@
|
||||
"@types/prismjs": "^1.26.0",
|
||||
"@types/react": "17.0.30",
|
||||
"@types/react-dom": "17.0.9",
|
||||
"@types/react-virtualized-auto-sizer": "^1.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~5.10.0",
|
||||
"@typescript-eslint/parser": "~5.10.0",
|
||||
"babel-jest": "27.2.3",
|
||||
|
19
yarn.lock
19
yarn.lock
@ -5394,6 +5394,13 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-virtualized-auto-sizer@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz#b3187dae1dfc4c15880c9cfc5b45f2719ea6ebd4"
|
||||
integrity sha512-GH8sAnBEM5GV9LTeiz56r4ZhMOUSrP43tAQNSRVxNexDjcNKLCEtnxusAItg1owFUFE6k0NslV26gqVClVvong==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*":
|
||||
version "17.0.39"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce"
|
||||
@ -7026,23 +7033,11 @@ assertion-error@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
|
||||
integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
|
||||
|
||||
assign-deep@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/assign-deep/-/assign-deep-1.0.1.tgz#b6d21d74e2f28bf6592e4c0c541bed6ab59c5f27"
|
||||
integrity sha512-CSXAX79mibneEYfqLT5FEmkqR5WXF+xDRjgQQuVf6wSCXCYU8/vHttPidNar7wJ5BFmKAo8Wei0rCtzb+M/yeA==
|
||||
dependencies:
|
||||
assign-symbols "^2.0.2"
|
||||
|
||||
assign-symbols@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
|
||||
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
|
||||
|
||||
assign-symbols@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-2.0.2.tgz#0fb9191dd9d617042746ecfc354f3a3d768a0c98"
|
||||
integrity sha512-9sBQUQZMKFKcO/C3Bo6Rx4CQany0R0UeVcefNGRRdW2vbmaMOhV1sbmlXcQLcD56juLXbSGTBm0GGuvmrAF8pA==
|
||||
|
||||
ast-types-flow@^0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
|
||||
|
Loading…
Reference in New Issue
Block a user