Skip to content

Commit cc1cc55

Browse files
committed
Merge branch 'feat/perps/price-caching' of github.com:MetaMask/metamask-mobile into feat/perps/price-caching
2 parents 4484179 + f10bf62 commit cc1cc55

File tree

13 files changed

+248
-288
lines changed

13 files changed

+248
-288
lines changed

app/components/UI/Perps/Views/PerpsClosePositionView/PerpsClosePositionView.test.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
defaultPerpsClosePositionValidationMock,
1414
defaultPerpsEventTrackingMock,
1515
defaultPerpsLivePricesMock,
16-
defaultPerpsOrderBookMock,
16+
defaultPerpsTopOfBookMock,
1717
defaultPerpsOrderFeesMock,
1818
defaultPerpsPositionMock,
1919
defaultPerpsRewardsMock,
@@ -52,7 +52,7 @@ jest.mock('../../hooks', () => ({
5252

5353
jest.mock('../../hooks/stream', () => ({
5454
usePerpsLivePrices: jest.fn(),
55-
usePerpsOrderBook: jest.fn(),
55+
usePerpsTopOfBook: jest.fn(),
5656
}));
5757

5858
jest.mock('../../hooks/usePerpsEventTracking', () => ({
@@ -122,8 +122,8 @@ describe('PerpsClosePositionView', () => {
122122
const usePerpsLivePricesMock = jest.mocked(
123123
jest.requireMock('../../hooks/stream').usePerpsLivePrices,
124124
);
125-
const usePerpsOrderBookMock = jest.mocked(
126-
jest.requireMock('../../hooks/stream').usePerpsOrderBook,
125+
const usePerpsTopOfBookMock = jest.mocked(
126+
jest.requireMock('../../hooks/stream').usePerpsTopOfBook,
127127
);
128128
const usePerpsOrderFeesMock = jest.mocked(
129129
jest.requireMock('../../hooks').usePerpsOrderFees,
@@ -167,7 +167,7 @@ describe('PerpsClosePositionView', () => {
167167

168168
// Setup hook mocks with default values
169169
usePerpsLivePricesMock.mockReturnValue(defaultPerpsLivePricesMock);
170-
usePerpsOrderBookMock.mockReturnValue(defaultPerpsOrderBookMock);
170+
usePerpsTopOfBookMock.mockReturnValue(defaultPerpsTopOfBookMock);
171171
usePerpsOrderFeesMock.mockReturnValue(defaultPerpsOrderFeesMock);
172172
usePerpsClosePositionValidationMock.mockReturnValue(
173173
defaultPerpsClosePositionValidationMock,

app/components/UI/Perps/Views/PerpsClosePositionView/PerpsClosePositionView.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import {
4646
usePerpsToasts,
4747
usePerpsMarketData,
4848
} from '../../hooks';
49-
import { usePerpsLivePrices, usePerpsOrderBook } from '../../hooks/stream';
49+
import { usePerpsLivePrices, usePerpsTopOfBook } from '../../hooks/stream';
5050
import { usePerpsEventTracking } from '../../hooks/usePerpsEventTracking';
5151
import { usePerpsMeasurement } from '../../hooks/usePerpsMeasurement';
5252
import {
@@ -115,11 +115,10 @@ const PerpsClosePositionView: React.FC = () => {
115115
? parseFloat(priceData[position.coin].price)
116116
: parseFloat(position.entryPrice);
117117

118-
// Get order book data for maker/taker fee determination
119-
const orderBooks = usePerpsOrderBook({
120-
symbols: [position.coin],
118+
// Get top of book data for maker/taker fee determination
119+
const currentTopOfBook = usePerpsTopOfBook({
120+
symbol: position.coin,
121121
});
122-
const currentOrderBook = orderBooks[position.coin];
123122

124123
// Determine position direction
125124
const isLong = parseFloat(position.size) > 0;
@@ -198,11 +197,11 @@ const PerpsClosePositionView: React.FC = () => {
198197
isClosing: true,
199198
limitPrice,
200199
direction: isLong ? 'short' : 'long',
201-
currentAskPrice: currentOrderBook?.bestAsk
202-
? Number.parseFloat(currentOrderBook.bestAsk)
200+
currentAskPrice: currentTopOfBook?.bestAsk
201+
? Number.parseFloat(currentTopOfBook.bestAsk)
203202
: undefined,
204-
currentBidPrice: currentOrderBook?.bestBid
205-
? Number.parseFloat(currentOrderBook.bestBid)
203+
currentBidPrice: currentTopOfBook?.bestBid
204+
? Number.parseFloat(currentTopOfBook.bestBid)
206205
: undefined,
207206
});
208207

app/components/UI/Perps/Views/PerpsOrderView/PerpsOrderView.test.tsx

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -571,26 +571,23 @@ const createMockStreamManager = () => {
571571
account: {
572572
subscribe: jest.fn(() => jest.fn()),
573573
},
574-
orderBooks: {
575-
subscribeToSymbols: ({
576-
symbols,
574+
topOfBook: {
575+
subscribeToSymbol: ({
576+
symbol: _symbol,
577577
callback,
578578
}: {
579-
symbols: string[];
579+
symbol: string;
580580
callback: (data: unknown) => void;
581581
}) => {
582582
const id = Math.random().toString();
583583
subscribers.set(id, callback);
584-
// Immediately provide mock order book data
585-
const mockOrderBooks: Record<string, unknown> = {};
586-
symbols.forEach((symbol: string) => {
587-
mockOrderBooks[symbol] = {
588-
bestBid: '2999',
589-
bestAsk: '3001',
590-
spread: '2',
591-
};
592-
});
593-
callback(mockOrderBooks);
584+
// Immediately provide mock top of book data
585+
const mockTopOfBook = {
586+
bestBid: '2999',
587+
bestAsk: '3001',
588+
spread: '2',
589+
};
590+
callback(mockTopOfBook);
594591
return () => {
595592
subscribers.delete(id);
596593
};

app/components/UI/Perps/Views/PerpsOrderView/PerpsOrderView.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ import {
8888
import {
8989
usePerpsLiveAccount,
9090
usePerpsLivePrices,
91-
usePerpsOrderBook,
91+
usePerpsTopOfBook,
9292
} from '../../hooks/stream';
9393
import { usePerpsEventTracking } from '../../hooks/usePerpsEventTracking';
9494
import { usePerpsMeasurement } from '../../hooks/usePerpsMeasurement';
@@ -275,11 +275,10 @@ const PerpsOrderViewContentBase: React.FC = () => {
275275
});
276276
const currentPrice = prices[orderForm.asset];
277277

278-
// Get order book data for maker/taker fee determination
279-
const orderBooks = usePerpsOrderBook({
280-
symbols: [orderForm.asset],
278+
// Get top of book data for maker/taker fee determination
279+
const currentTopOfBook = usePerpsTopOfBook({
280+
symbol: orderForm.asset,
281281
});
282-
const currentOrderBook = orderBooks[orderForm.asset];
283282

284283
// Track screen load with unified hook
285284
usePerpsMeasurement({
@@ -309,11 +308,11 @@ const PerpsOrderViewContentBase: React.FC = () => {
309308
isClosing: false,
310309
limitPrice: orderForm.limitPrice,
311310
direction: orderForm.direction,
312-
currentAskPrice: currentOrderBook?.bestAsk
313-
? Number.parseFloat(currentOrderBook.bestAsk)
311+
currentAskPrice: currentTopOfBook?.bestAsk
312+
? Number.parseFloat(currentTopOfBook.bestAsk)
314313
: undefined,
315-
currentBidPrice: currentOrderBook?.bestBid
316-
? Number.parseFloat(currentOrderBook.bestBid)
314+
currentBidPrice: currentTopOfBook?.bestBid
315+
? Number.parseFloat(currentTopOfBook.bestBid)
317316
: undefined,
318317
});
319318

app/components/UI/Perps/__mocks__/perpsHooksMocks.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ export const defaultPerpsLivePricesMock = {
1111
BTC: { price: '45000.00', change24h: 1.2 },
1212
};
1313

14-
export const defaultPerpsOrderBookMock = {
15-
ETH: { bestBid: '2999.00', bestAsk: '3001.00', spread: '2.00' },
16-
BTC: { bestBid: '44999.00', bestAsk: '45001.00', spread: '2.00' },
14+
export const defaultPerpsTopOfBookMock = {
15+
bestBid: '2999.00',
16+
bestAsk: '3001.00',
17+
spread: '2.00',
1718
};
1819

1920
export const defaultPerpsOrderFeesMock = {

app/components/UI/Perps/hooks/stream/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export { usePerpsLiveOrders } from './usePerpsLiveOrders';
44
export { usePerpsLivePositions } from './usePerpsLivePositions';
55
export { usePerpsLiveFills } from './usePerpsLiveFills';
66
export { usePerpsLiveAccount } from './usePerpsLiveAccount';
7-
export { usePerpsOrderBook } from './usePerpsOrderBook';
7+
export { usePerpsTopOfBook } from './usePerpsTopOfBook';
88

99
// Export types for convenience
1010
export type { UsePerpsLivePricesOptions } from './usePerpsLivePrices';
@@ -16,9 +16,9 @@ export type {
1616
UsePerpsLiveAccountReturn,
1717
} from './usePerpsLiveAccount';
1818
export type {
19-
UsePerpsOrderBookOptions,
20-
OrderBookData,
21-
} from './usePerpsOrderBook';
19+
UsePerpsTopOfBookOptions,
20+
TopOfBookData,
21+
} from './usePerpsTopOfBook';
2222

2323
// Re-export types from controllers
2424
export type {

app/components/UI/Perps/hooks/stream/usePerpsLivePrices.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useEffect, useMemo, useState } from 'react';
22
import { usePerpsStream } from '../../providers/PerpsStreamManager';
33
import type { PriceUpdate } from '../../controllers/types';
44

@@ -28,6 +28,9 @@ export function usePerpsLivePrices(
2828
const stream = usePerpsStream();
2929
const [prices, setPrices] = useState<Record<string, PriceUpdate>>({});
3030

31+
// Memoize joined symbols to prevent unnecessary effect re-runs
32+
const symbolsKey = useMemo(() => symbols.join(','), [symbols]);
33+
3134
useEffect(() => {
3235
if (symbols.length === 0) return;
3336

@@ -45,8 +48,10 @@ export function usePerpsLivePrices(
4548
return () => {
4649
unsubscribe();
4750
};
51+
// symbolsKey captures symbols changes via memoization, so symbols is intentionally omitted
52+
// to prevent re-subscriptions when array reference changes but content is the same
4853
// eslint-disable-next-line react-hooks/exhaustive-deps
49-
}, [stream, symbols.join(','), throttleMs]);
54+
}, [stream, symbolsKey, throttleMs]);
5055

5156
return prices;
5257
}

app/components/UI/Perps/hooks/stream/usePerpsOrderBook.test.ts

Lines changed: 0 additions & 65 deletions
This file was deleted.

app/components/UI/Perps/hooks/stream/usePerpsOrderBook.ts

Lines changed: 0 additions & 77 deletions
This file was deleted.

0 commit comments

Comments
 (0)