;
+ const hasAmendableOrder = activeOrders.some(
+ (edge) => !(edge.node.liquidityProvision || edge.node.peggedOrder)
+ );
+ return hasAmendableOrder;
+});
diff --git a/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx b/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx
index 4be809922..f662a2b07 100644
--- a/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx
+++ b/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx
@@ -8,7 +8,7 @@ import type { GridReadyEvent } from 'ag-grid-community';
import { OrderListTable } from '../order-list/order-list';
import { useOrderListData } from './use-order-list-data';
-import { useHasActiveOrder } from '../../order-hooks/use-has-active-order';
+import { useHasAmendableOrder } from '../../order-hooks/use-has-amendable-order';
import type { Filter, Sort } from './use-order-list-data';
import { useBottomPlaceholder } from '@vegaprotocol/react-helpers';
import { OrderStatus } from '@vegaprotocol/types';
@@ -16,6 +16,7 @@ import {
normalizeOrderAmendment,
useVegaTransactionStore,
} from '@vegaprotocol/wallet';
+import isEqual from 'lodash/isEqual';
import type { OrderTxUpdateFieldsFragment } from '@vegaprotocol/wallet';
import { OrderEditDialog } from '../order-list/order-edit-dialog';
import type { Order, OrderEdge } from '../order-data-provider';
@@ -28,27 +29,18 @@ export interface OrderListManagerProps {
enforceBottomPlaceholder?: boolean;
}
-const CancelAllOrdersButton = ({
- onClick,
- marketId,
-}: {
- onClick: (marketId?: string) => void;
- marketId?: string;
-}) => {
- const hasActiveOrder = useHasActiveOrder(marketId);
- return hasActiveOrder ? (
-
-
-
- ) : null;
-};
+const CancelAllOrdersButton = ({ onClick }: { onClick: () => void }) => (
+
+
+
+);
const initialFilter: Filter = {
status: {
@@ -68,9 +60,10 @@ export const OrderListManager = ({
const scrolledToTop = useRef(false);
const [sort, setSort] = useState();
const [filter, setFilter] = useState(initialFilter);
+ const filterRef = useRef(initialFilter);
const [editOrder, setEditOrder] = useState(null);
const create = useVegaTransactionStore((state) => state.create);
- const hasActiveOrder = useHasActiveOrder(marketId);
+ const hasAmendableOrder = useHasAmendableOrder(marketId);
const { data, error, loading, reload } = useOrderListData({
partyId,
@@ -86,12 +79,16 @@ export const OrderListManager = ({
...bottomPlaceholderProps
} = useBottomPlaceholder({
gridRef,
- disabled: !enforceBottomPlaceholder && !isReadOnly && !hasActiveOrder,
+ disabled: !enforceBottomPlaceholder && !isReadOnly && !hasAmendableOrder,
});
const onFilterChanged = useCallback(
(event: FilterChangedEvent) => {
const updatedFilter = event.api.getFilterModel();
+ if (isEqual(updatedFilter, filterRef.current)) {
+ return;
+ }
+ filterRef.current = updatedFilter;
if (Object.keys(updatedFilter).length) {
setFilter(updatedFilter);
} else {
@@ -142,16 +139,13 @@ export const OrderListManager = ({
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
}, [data]);
- const cancelAll = useCallback(
- (marketId?: string) => {
- create({
- orderCancellation: {
- marketId,
- },
- });
- },
- [create]
- );
+ const cancelAll = useCallback(() => {
+ create({
+ orderCancellation: {
+ marketId,
+ },
+ });
+ }, [create, marketId]);
const extractedData =
data && !loading
? data
@@ -188,8 +182,8 @@ export const OrderListManager = ({
/>
- {!isReadOnly && (
-
+ {!isReadOnly && hasAmendableOrder && (
+
)}
{editOrder && (
{
+export const useHasAmendableOrder = (marketId?: string) => {
const { pubKey } = useVegaWallet();
- const [hasActiveOrder, setHasActiveOrder] = useState(false);
+ const [hasAmendableOrder, setHasAmendableOrder] = useState(false);
const update = useCallback(({ data }: { data: boolean | null }) => {
- setHasActiveOrder(Boolean(data));
+ setHasAmendableOrder(Boolean(data));
return true;
}, []);
useDataProvider({
- dataProvider: hasActiveOrderProvider,
+ dataProvider: hasAmendableOrderProvider,
update,
variables: {
partyId: pubKey || '',
@@ -20,5 +20,5 @@ export const useHasActiveOrder = (marketId?: string) => {
skip: !pubKey,
});
- return hasActiveOrder;
+ return hasAmendableOrder;
};
diff --git a/libs/orders/src/lib/order-hooks/use-pending-orders-volume.ts b/libs/orders/src/lib/order-hooks/use-pending-orders-volume.ts
deleted file mode 100644
index 988570419..000000000
--- a/libs/orders/src/lib/order-hooks/use-pending-orders-volume.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { useState, useCallback } from 'react';
-import { OrderStatus, Side } from '@vegaprotocol/types';
-import { ordersProvider } from '../components/order-data-provider/order-data-provider';
-import type { OrderFieldsFragment } from '../components/order-data-provider/__generated__/Orders';
-import type { Edge } from '@vegaprotocol/utils';
-import { useDataProvider } from '@vegaprotocol/react-helpers';
-
-const sumVolume = (orders: (Edge | null)[], side: Side) =>
- orders
- .reduce(
- (sum, order) =>
- order?.node.side === side
- ? sum +
- BigInt(
- order?.node.status === OrderStatus.STATUS_PARTIALLY_FILLED
- ? order?.node.remaining
- : order?.node.size
- )
- : sum,
- BigInt(0)
- )
- .toString();
-
-export const useActiveOrdersVolumeAndMargin = (
- partyId: string | null | undefined,
- marketId: string
-) => {
- const [buyVolume, setBuyVolume] = useState();
- const [sellVolume, setSellVolume] = useState();
- const [buyInitialMargin, setBuyInitialMargin] = useState<
- string | undefined
- >();
- const [sellInitialMargin, setSellInitialMargin] = useState<
- string | undefined
- >();
- const update = useCallback(
- ({ data }: { data: (Edge | null)[] | null }) => {
- if (!data) {
- setBuyVolume(undefined);
- setSellVolume(undefined);
- setBuyInitialMargin(undefined);
- setSellInitialMargin(undefined);
- } else {
- setBuyVolume(sumVolume(data, Side.SIDE_BUY));
- setSellVolume(sumVolume(data, Side.SIDE_SELL));
- }
- return true;
- },
- []
- );
- useDataProvider({
- dataProvider: ordersProvider,
- update,
- variables: {
- partyId: partyId || '',
- marketIds: [marketId],
- filter: {
- status: [
- OrderStatus.STATUS_ACTIVE,
- OrderStatus.STATUS_PARTIALLY_FILLED,
- ],
- },
- },
- skip: !partyId,
- });
- return buyVolume || sellVolume
- ? {
- buyVolume,
- sellVolume,
- buyInitialMargin,
- sellInitialMargin,
- }
- : undefined;
-};
diff --git a/libs/positions/src/lib/positions-data-providers.ts b/libs/positions/src/lib/positions-data-providers.ts
index 7e827927e..eead272c9 100644
--- a/libs/positions/src/lib/positions-data-providers.ts
+++ b/libs/positions/src/lib/positions-data-providers.ts
@@ -30,12 +30,12 @@ import {
import { marginsDataProvider } from './margin-data-provider';
import { calculateMargins } from './margin-calculator';
import type { Edge } from '@vegaprotocol/utils';
-import { OrderStatus, Side } from '@vegaprotocol/types';
+import { Side } from '@vegaprotocol/types';
import { marketInfoProvider } from '@vegaprotocol/market-info';
import type { MarketInfoQuery } from '@vegaprotocol/market-info';
import { marketDataProvider } from '@vegaprotocol/market-list';
import type { MarketData } from '@vegaprotocol/market-list';
-import { ordersProvider } from '@vegaprotocol/orders';
+import { activeOrdersProvider } from '@vegaprotocol/orders';
import type { OrderFieldsFragment } from '@vegaprotocol/orders';
import type { PositionStatus } from '@vegaprotocol/types';
@@ -350,12 +350,9 @@ export const volumeAndMarginProvider = makeDerivedDataProvider<
>(
[
(callback, client, { partyId, marketId }) =>
- ordersProvider(callback, client, {
+ activeOrdersProvider(callback, client, {
partyId,
- marketIds: [marketId],
- filter: {
- status: [OrderStatus.STATUS_ACTIVE, OrderStatus.STATUS_PARKED],
- },
+ marketId,
}),
(callback, client, variables) =>
marketDataProvider(callback, client, { marketId: variables.marketId }),
diff --git a/libs/react-helpers/src/hooks/use-data-provider.ts b/libs/react-helpers/src/hooks/use-data-provider.ts
index addd5d3fc..3419983fc 100644
--- a/libs/react-helpers/src/hooks/use-data-provider.ts
+++ b/libs/react-helpers/src/hooks/use-data-provider.ts
@@ -1,10 +1,10 @@
-import { useState, useEffect, useRef, useCallback } from 'react';
+import { useState, useEffect, useRef, useMemo, useCallback } from 'react';
import throttle from 'lodash/throttle';
-import isEqual from 'lodash/isEqual';
+import isEqualWith from 'lodash/isEqualWith';
import { useApolloClient } from '@apollo/client';
-import { usePrevious } from './use-previous';
import type { OperationVariables } from '@apollo/client';
import type { Subscribe, Load, UpdateCallback } from '@vegaprotocol/utils';
+import { variablesIsEqualCustomizer } from '@vegaprotocol/utils';
export interface useDataProviderParams<
Data,
@@ -62,13 +62,19 @@ export const useDataProvider = <
const flushRef = useRef<(() => void) | undefined>(undefined);
const reloadRef = useRef<((force?: boolean) => void) | undefined>(undefined);
const loadRef = useRef | undefined>(undefined);
- const prevVariables = usePrevious(props.variables);
- const [variables, setVariables] = useState(props.variables);
- useEffect(() => {
- if (!isEqual(prevVariables, props.variables)) {
- setVariables(props.variables);
+ const variablesRef = useRef(props.variables);
+ const variables = useMemo(() => {
+ if (
+ !isEqualWith(
+ variablesRef.current,
+ props.variables,
+ variablesIsEqualCustomizer
+ )
+ ) {
+ variablesRef.current = props.variables;
}
- }, [props.variables, prevVariables]);
+ return variablesRef.current;
+ }, [props.variables]);
const flush = useCallback(() => {
if (flushRef.current) {
flushRef.current();
diff --git a/libs/utils/src/lib/generic-data-provider.spec.ts b/libs/utils/src/lib/generic-data-provider.spec.ts
index e68d588f0..c48d685e0 100644
--- a/libs/utils/src/lib/generic-data-provider.spec.ts
+++ b/libs/utils/src/lib/generic-data-provider.spec.ts
@@ -45,7 +45,7 @@ type CombinedData = {
type SubscriptionData = QueryData;
type Delta = Data;
-type Variables = { var: string };
+type Variables = { var: string; filter?: string[] };
const update = jest.fn<
ReturnType>,
@@ -231,10 +231,14 @@ describe('data provider', () => {
clientSubscribeSubscribe.mockClear();
});
it('memoize instance and unsubscribe if no subscribers', () => {
- const subscription1 = subscribe(jest.fn(), client, variables);
- const subscription2 = subscribe(jest.fn(), client, { ...variables });
- // const subscription1 = subscribe(jest.fn(), client);
- // const subscription2 = subscribe(jest.fn(), client);
+ const subscription1 = subscribe(jest.fn(), client, {
+ ...variables,
+ filter: ['1', '2'],
+ });
+ const subscription2 = subscribe(jest.fn(), client, {
+ ...variables,
+ filter: ['2', '1'],
+ });
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(1);
subscription1.unsubscribe();
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(0);
diff --git a/libs/utils/src/lib/generic-data-provider.ts b/libs/utils/src/lib/generic-data-provider.ts
index 2dae214a5..9de04913e 100644
--- a/libs/utils/src/lib/generic-data-provider.ts
+++ b/libs/utils/src/lib/generic-data-provider.ts
@@ -10,7 +10,7 @@ import type {
} from '@apollo/client';
import type { GraphQLErrors } from '@apollo/client/errors';
import type { Subscription } from 'zen-observable-ts';
-import isEqual from 'lodash/isEqual';
+import isEqualWith from 'lodash/isEqualWith';
import { isNotFoundGraphQLError } from './apollo-client';
import type * as Schema from '@vegaprotocol/types';
interface UpdateData {
@@ -512,11 +512,26 @@ function makeDataProviderInternal<
};
}
+/**
+ * Compares two arrays assuming that they are sets of primitive values, used to compare gql query variables
+ */
+export const variablesIsEqualCustomizer: NonNullable<
+ Parameters['2']
+> = (value, other) => {
+ if (Array.isArray(value) && Array.isArray(other)) {
+ return (
+ value.length === other.length &&
+ new Set([...value, ...other]).size === value.length
+ );
+ }
+ return undefined;
+};
+
/**
* Memoizes data provider instances using query variables as cache key
*
* @param fn
- * @returns subscibe function
+ * @returns subscribe function
*/
const memoize = <
Data,
@@ -530,7 +545,9 @@ const memoize = <
variables?: Variables;
}[] = [];
return (variables?: Variables) => {
- const cached = cache.find((c) => isEqual(c.variables, variables));
+ const cached = cache.find((c) =>
+ isEqualWith(c.variables, variables, variablesIsEqualCustomizer)
+ );
if (cached) {
return cached.subscribe;
}
@@ -582,8 +599,10 @@ export function makeDataProvider<
const getInstance = memoize(() =>
makeDataProviderInternal(params)
);
- return (callback, client, variables) =>
- getInstance(variables)(callback, client, variables);
+ return (callback, client, variables) => {
+ const instance = getInstance(variables)(callback, client, variables);
+ return instance;
+ };
}
/**
@@ -605,7 +624,9 @@ export type CombineDerivedData<
> = (
data: DerivedPart['data'][],
variables: Variables,
- prevData: Data | null
+ prevData: Data | null,
+ parts: DerivedPart[],
+ subscriptions?: ReturnType>[]
) => Data | null;
export type CombineDerivedDelta<
@@ -687,7 +708,9 @@ function makeDerivedDataProviderInternal<
? combineData(
parts.map((part) => part.data),
variables,
- data
+ data,
+ parts,
+ subscriptions
)
: data;
if (