diff --git a/src/custom/state/orders/reducer.ts b/src/custom/state/orders/reducer.ts index bfd3b490f..3b525505f 100644 --- a/src/custom/state/orders/reducer.ts +++ b/src/custom/state/orders/reducer.ts @@ -123,6 +123,21 @@ function deleteOrderById(state: Required, chainId: ChainId, id: str delete stateForChain.cancelled[id] } +function addOrderToState( + state: Required, + chainId: ChainId, + id: string, + status: OrderTypeKeys, + order: SerializedOrder +): void { + // Attempt to fix `TypeError: Cannot add property , object is not extensible` + // seen on https://user-images.githubusercontent.com/34510341/138450105-bb94a2d1-656e-4e15-ae99-df9fb33c8ca4.png + // by creating a new object instead of trying to edit the existing one + // Seems to be due to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions + // but only happened on Chrome + state[chainId][status] = { ...state[chainId][status], [id]: { order, id } } +} + function popOrder(state: OrdersState, chainId: ChainId, status: OrderStatus, id: string): OrderObject | undefined { const orderObj = state?.[chainId]?.[status]?.[id] if (orderObj) { @@ -140,12 +155,12 @@ export default createReducer(initialState, (builder) => const { order, id, chainId } = action.payload const orderStateList = order.status === OrderStatus.PRESIGNATURE_PENDING ? 'presignaturePending' : 'pending' - state[chainId][orderStateList][id] = { order, id } + + addOrderToState(state, chainId, id, orderStateList, order) }) .addCase(preSignOrders, (state, action) => { prefillState(state, action) const { ids, chainId } = action.payload - const pendingOrders = state[chainId].pending ids.forEach((id) => { const orderObject = getOrderById(state, chainId, id) @@ -154,7 +169,8 @@ export default createReducer(initialState, (builder) => deleteOrderById(state, chainId, id) orderObject.order.status = OrderStatus.PENDING - pendingOrders[id] = orderObject + + addOrderToState(state, chainId, id, 'pending', orderObject.order) } }) }) @@ -195,7 +211,7 @@ export default createReducer(initialState, (builder) => : newOrder // add order to respective state - state[chainId][status][id] = { order, id } + addOrderToState(state, chainId, id, status, order) }) }) .addCase(fulfillOrder, (state, action) => { @@ -212,7 +228,7 @@ export default createReducer(initialState, (builder) => orderObject.order.fulfilledTransactionHash = transactionHash orderObject.order.isCancelling = false - state[chainId].fulfilled[id] = orderObject + addOrderToState(state, chainId, id, 'fulfilled', orderObject.order) } }) .addCase(fulfillOrdersBatch, (state, action) => { @@ -235,7 +251,7 @@ export default createReducer(initialState, (builder) => orderObject.order.apiAdditionalInfo = apiAdditionalInfo - state[chainId].fulfilled[id] = orderObject + addOrderToState(state, chainId, id, 'fulfilled', orderObject.order) } }) }) @@ -251,13 +267,12 @@ export default createReducer(initialState, (builder) => orderObject.order.status = OrderStatus.EXPIRED orderObject.order.isCancelling = false - state[chainId].expired[id] = orderObject + addOrderToState(state, chainId, id, 'expired', orderObject.order) } }) .addCase(expireOrdersBatch, (state, action) => { prefillState(state, action) const { ids, chainId } = action.payload - const fulfilledOrders = state[chainId].expired // if there are any newly fulfilled orders // update them @@ -269,7 +284,8 @@ export default createReducer(initialState, (builder) => orderObject.order.status = OrderStatus.EXPIRED orderObject.order.isCancelling = false - fulfilledOrders[id] = orderObject + + addOrderToState(state, chainId, id, 'expired', orderObject.order) } }) }) @@ -295,13 +311,12 @@ export default createReducer(initialState, (builder) => orderObject.order.status = OrderStatus.CANCELLED orderObject.order.isCancelling = false - state[chainId].cancelled[id] = orderObject + addOrderToState(state, chainId, id, 'cancelled', orderObject.order) } }) .addCase(cancelOrdersBatch, (state, action) => { prefillState(state, action) const { ids, chainId } = action.payload - const cancelledOrders = state[chainId].cancelled ids.forEach((id) => { const orderObject = getOrderById(state, chainId, id) @@ -311,7 +326,8 @@ export default createReducer(initialState, (builder) => orderObject.order.status = OrderStatus.CANCELLED orderObject.order.isCancelling = false - cancelledOrders[id] = orderObject + + addOrderToState(state, chainId, id, 'cancelled', orderObject.order) } }) }) diff --git a/src/custom/state/orders/updaters/CancelledOrdersUpdater.ts b/src/custom/state/orders/updaters/CancelledOrdersUpdater.ts index d6163cca1..6b0843cc6 100644 --- a/src/custom/state/orders/updaters/CancelledOrdersUpdater.ts +++ b/src/custom/state/orders/updaters/CancelledOrdersUpdater.ts @@ -27,7 +27,7 @@ import { fetchOrderPopupData, OrderLogPopupMixData } from 'state/orders/updaters * period and say it's cancelled even though in some cases it might actually be filled. */ export function CancelledOrdersUpdater(): null { - const { chainId } = useActiveWeb3React() + const { chainId, account } = useActiveWeb3React() const cancelled = useCancelledOrders({ chainId }) @@ -38,10 +38,15 @@ export function CancelledOrdersUpdater(): null { const fulfillOrdersBatch = useFulfillOrdersBatch() const updateOrders = useCallback( - async (chainId: ChainId) => { - // Filter orders created in the last 5 min, no further + async (chainId: ChainId, account: string) => { + const lowerCaseAccount = account.toLowerCase() + // Filter orders: + // - Owned by the current connected account + // - Created in the last 5 min, no further const pending = cancelledRef.current.filter( - (order) => Date.now() - new Date(order.creationTime).getTime() < CANCELLED_ORDERS_PENDING_TIME + ({ owner, creationTime }) => + owner.toLowerCase() === lowerCaseAccount && + Date.now() - new Date(creationTime).getTime() < CANCELLED_ORDERS_PENDING_TIME ) if (pending.length === 0) { @@ -74,14 +79,14 @@ export function CancelledOrdersUpdater(): null { ) useEffect(() => { - if (!chainId) { + if (!chainId || !account) { return } - const interval = setInterval(() => updateOrders(chainId), OPERATOR_API_POLL_INTERVAL) + const interval = setInterval(() => updateOrders(chainId, account), OPERATOR_API_POLL_INTERVAL) return () => clearInterval(interval) - }, [chainId, updateOrders]) + }, [account, chainId, updateOrders]) return null } diff --git a/src/custom/state/orders/updaters/PendingOrdersUpdater.ts b/src/custom/state/orders/updaters/PendingOrdersUpdater.ts index 7f8e5dd74..1fc77f70b 100644 --- a/src/custom/state/orders/updaters/PendingOrdersUpdater.ts +++ b/src/custom/state/orders/updaters/PendingOrdersUpdater.ts @@ -36,7 +36,7 @@ function _getNewlyPreSignedOrders(allPendingOrders: Order[], signedOrdersIds: Or } export function PendingOrdersUpdater(): null { - const { chainId } = useActiveWeb3React() + const { chainId, account } = useActiveWeb3React() const pending = usePendingOrders({ chainId }) @@ -50,15 +50,19 @@ export function PendingOrdersUpdater(): null { const presignOrders = usePresignOrders() const updateOrders = useCallback( - async (chainId: ChainId) => { + async (chainId: ChainId, account: string) => { + const lowerCaseAccount = account.toLowerCase() + // Only check pending orders of current connected account + const pending = pendingRef.current.filter(({ owner }) => owner.toLowerCase() === lowerCaseAccount) + // Exit early when there are no pending orders - if (pendingRef.current.length === 0) { + if (pending.length === 0) { return } // Iterate over pending orders fetching API data const unfilteredOrdersData = await Promise.all( - pendingRef.current.map(async (orderFromStore) => fetchOrderPopupData(orderFromStore, chainId)) + pending.map(async (orderFromStore) => fetchOrderPopupData(orderFromStore, chainId)) ) // Group resolved promises by status @@ -76,7 +80,7 @@ export function PendingOrdersUpdater(): null { if (presigned.length > 0) { // Only mark as presigned the orders we were not aware of their new state const presignedOrderIds = presigned as OrderID[] - const ordersPresignaturePendingSigned = _getNewlyPreSignedOrders(pendingRef.current, presignedOrderIds) + const ordersPresignaturePendingSigned = _getNewlyPreSignedOrders(pending, presignedOrderIds) if (ordersPresignaturePendingSigned.length > 0) { presignOrders({ @@ -111,14 +115,14 @@ export function PendingOrdersUpdater(): null { ) useEffect(() => { - if (!chainId) { + if (!chainId || !account) { return } - const interval = setInterval(() => updateOrders(chainId), OPERATOR_API_POLL_INTERVAL) + const interval = setInterval(() => updateOrders(chainId, account), OPERATOR_API_POLL_INTERVAL) return () => clearInterval(interval) - }, [chainId, updateOrders]) + }, [account, chainId, updateOrders]) return null } diff --git a/src/custom/state/orders/updaters/UnfillableOrdersUpdater.ts b/src/custom/state/orders/updaters/UnfillableOrdersUpdater.ts index 995a55e0a..cb2bc6d28 100644 --- a/src/custom/state/orders/updaters/UnfillableOrdersUpdater.ts +++ b/src/custom/state/orders/updaters/UnfillableOrdersUpdater.ts @@ -51,7 +51,7 @@ async function _getOrderPrice(chainId: ChainId, order: Order) { * Updater that checks whether pending orders are still "fillable" */ export function UnfillableOrdersUpdater(): null { - const { chainId } = useActiveWeb3React() + const { chainId, account } = useActiveWeb3React() const pending = usePendingOrders({ chainId }) const setIsOrderUnfillable = useSetIsOrderUnfillable() @@ -70,11 +70,19 @@ export function UnfillableOrdersUpdater(): null { ) const updatePending = useCallback(() => { - if (!chainId || pendingRef.current.length === 0) { + if (!chainId || !account) { return } - pendingRef.current.forEach((order, index) => + const lowerCaseAccount = account.toLowerCase() + // Only check pending orders of the connected account + const pending = pendingRef.current.filter(({ owner }) => owner.toLowerCase() === lowerCaseAccount) + + if (pending.length === 0) { + return + } + + pending.forEach((order, index) => _getOrderPrice(chainId, order).then((price) => { console.debug( `[UnfillableOrdersUpdater::updateUnfillable] did we get any price? ${order.id.slice(0, 8)}|${index}`, @@ -83,7 +91,7 @@ export function UnfillableOrdersUpdater(): null { price?.amount && updateIsUnfillableFlag(chainId, order, price) }) ) - }, [chainId, updateIsUnfillableFlag]) + }, [account, chainId, updateIsUnfillableFlag]) useEffect(() => { updatePending()