Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.

Update orders faster #1893

Merged
merged 1 commit into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/custom/state/orders/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const ContractDeploymentBlocks: Partial<Record<ChainId, number>> = {
[ChainId.XDAI]: 13566914,
}

export const OPERATOR_API_POLL_INTERVAL = 10000 // in ms
export const PENDING_ORDERS_PRICE_CHECK_POLL_INTERVAL = 30000 // in ms
export const OPERATOR_API_POLL_INTERVAL = 2000 // in ms
export const PENDING_ORDERS_PRICE_CHECK_POLL_INTERVAL = 15000 // in ms

export const OUT_OF_MARKET_PRICE_DELTA_PERCENTAGE = new Percent(1, 100) // 1/100 => 0.01 => 1%
76 changes: 47 additions & 29 deletions src/custom/state/orders/updaters/CancelledOrdersUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export function CancelledOrdersUpdater(): null {

// Ref, so we don't rerun useEffect
const cancelledRef = useRef(cancelled)
const isUpdating = useRef(false) // TODO: Implement using SWR or retry/cancellable promises
cancelledRef.current = cancelled

const fulfillOrdersBatch = useFulfillOrdersBatch()
Expand All @@ -41,40 +42,57 @@ export function CancelledOrdersUpdater(): null {
async (chainId: ChainId, account: string) => {
const lowerCaseAccount = account.toLowerCase()
const now = Date.now()
// Filter orders:
// - Owned by the current connected account
// - Created in the last 5 min, no further
const pending = cancelledRef.current.filter(({ owner, creationTime: creationTimeString }) => {
const creationTime = new Date(creationTimeString).getTime()

return owner.toLowerCase() === lowerCaseAccount && now - creationTime < CANCELLED_ORDERS_PENDING_TIME
})

if (pending.length === 0) {
if (isUpdating.current) {
return
}

// Iterate over pending orders fetching operator order data, async
const unfilteredOrdersData = await Promise.all(
pending.map(async (orderFromStore) => fetchOrderPopupData(orderFromStore, chainId))
)

// Group resolved promises by status
// Only pick fulfilled
const { fulfilled } = unfilteredOrdersData.reduce<Record<OrderTransitionStatus, OrderLogPopupMixData[]>>(
(acc, { status, popupData }) => {
popupData && acc[status].push(popupData)
return acc
},
{ fulfilled: [], presigned: [], expired: [], cancelled: [], unknown: [], pending: [] }
)

// Bach state update fulfilled orders, if any
fulfilled.length > 0 &&
fulfillOrdersBatch({
ordersData: fulfilled as OrderFulfillmentData[],
chainId,
// const startTime = Date.now()
// console.debug('[CancelledOrdersUpdater] Checking recently canceled orders....')
try {
isUpdating.current = true

// Filter orders:
// - Owned by the current connected account
// - Created in the last 5 min, no further
const pending = cancelledRef.current.filter(({ owner, creationTime: creationTimeString }) => {
const creationTime = new Date(creationTimeString).getTime()

return owner.toLowerCase() === lowerCaseAccount && now - creationTime < CANCELLED_ORDERS_PENDING_TIME
})

if (pending.length === 0) {
// console.debug(`[CancelledOrdersUpdater] No orders are being cancelled`)
return
} /* else {
console.debug(`[CancelledOrdersUpdater] Checking ${pending.length} recently canceled orders...`)
}*/

// Iterate over pending orders fetching operator order data, async
const unfilteredOrdersData = await Promise.all(
pending.map(async (orderFromStore) => fetchOrderPopupData(orderFromStore, chainId))
)

// Group resolved promises by status
// Only pick fulfilled
const { fulfilled } = unfilteredOrdersData.reduce<Record<OrderTransitionStatus, OrderLogPopupMixData[]>>(
(acc, { status, popupData }) => {
popupData && acc[status].push(popupData)
return acc
},
{ fulfilled: [], presigned: [], expired: [], cancelled: [], unknown: [], pending: [] }
)

// Bach state update fulfilled orders, if any
fulfilled.length > 0 &&
fulfillOrdersBatch({
ordersData: fulfilled as OrderFulfillmentData[],
chainId,
})
} finally {
isUpdating.current = false
// console.debug(`[CancelledOrdersUpdater] Checked recently canceled orders in ${Date.now() - startTime}ms`)
}
},
[fulfillOrdersBatch]
)
Expand Down
38 changes: 26 additions & 12 deletions src/custom/state/orders/updaters/PendingOrdersUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,13 @@ async function _updateOrders({

// Exit early when there are no pending orders
if (pending.length === 0) {
// console.debug('[PendingOrdersUpdater] No orders to update')
return
}
} /* else {
console.debug(
`[PendingOrdersUpdater] Update ${pending.length} orders for account ${account} and network ${chainId}`
)
}*/

// Iterate over pending orders fetching API data
const unfilteredOrdersData = await Promise.all(
Expand Down Expand Up @@ -180,6 +185,7 @@ export function PendingOrdersUpdater(): null {
const { chainId, account } = useActiveWeb3React()

const pending = usePendingOrders({ chainId })
const isUpdating = useRef(false) // TODO: Implement using SWR or retry/cancellable promises

// Ref, so we don't rerun useEffect
const pendingRef = useRef(pending)
Expand All @@ -198,17 +204,25 @@ export function PendingOrdersUpdater(): null {
return []
}

return _updateOrders({
account,
chainId,
orders: pendingRef.current,
fulfillOrdersBatch,
expireOrdersBatch,
cancelOrdersBatch,
presignOrders,
updatePresignGnosisSafeTx,
getSafeInfo,
})
if (!isUpdating.current) {
isUpdating.current = true
// const startTime = Date.now()
// console.debug('[PendingOrdersUpdater] Updating orders....')
return _updateOrders({
account,
chainId,
orders: pendingRef.current,
fulfillOrdersBatch,
expireOrdersBatch,
cancelOrdersBatch,
presignOrders,
updatePresignGnosisSafeTx,
getSafeInfo,
}).finally(() => {
isUpdating.current = false
// console.debug(`[PendingOrdersUpdater] Updated orders in ${Date.now() - startTime}ms`)
})
}
},
[cancelOrdersBatch, updatePresignGnosisSafeTx, expireOrdersBatch, fulfillOrdersBatch, presignOrders, getSafeInfo]
)
Expand Down
43 changes: 29 additions & 14 deletions src/custom/state/orders/updaters/UnfillableOrdersUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export function UnfillableOrdersUpdater(): null {
// Ref, so we don't rerun useEffect
const pendingRef = useRef(pending)
pendingRef.current = pending
const isUpdating = useRef(false) // TODO: Implement using SWR or retry/cancellable promises

const updateIsUnfillableFlag = useCallback(
(chainId: ChainId, order: Order, price: Required<PriceInformation>) => {
Expand All @@ -70,27 +71,41 @@ export function UnfillableOrdersUpdater(): null {
)

const updatePending = useCallback(() => {
if (!chainId || !account) {
if (!chainId || !account || isUpdating.current) {
return
}

const lowerCaseAccount = account.toLowerCase()
// Only check pending orders of the connected account
const pending = pendingRef.current.filter(({ owner }) => owner.toLowerCase() === lowerCaseAccount)
const startTime = Date.now()
console.debug('[UnfillableOrdersUpdater] Checking new market price for orders....')
try {
isUpdating.current = true

if (pending.length === 0) {
return
}
const lowerCaseAccount = account.toLowerCase()
// Only check pending orders of the connected account
const pending = pendingRef.current.filter(({ owner }) => owner.toLowerCase() === lowerCaseAccount)

pending.forEach((order, index) =>
_getOrderPrice(chainId, order).then((price) => {
if (pending.length === 0) {
// console.debug('[UnfillableOrdersUpdater] No orders to update')
return
} else {
console.debug(
`[UnfillableOrdersUpdater::updateUnfillable] did we get any price? ${order.id.slice(0, 8)}|${index}`,
price ? price.amount : 'no :('
`[UnfillableOrdersUpdater] Checking new market price for ${pending.length} orders, account ${account} and network ${chainId}`
)
price?.amount && updateIsUnfillableFlag(chainId, order, price)
})
)
}

pending.forEach((order, index) =>
_getOrderPrice(chainId, order).then((price) => {
console.debug(
`[UnfillableOrdersUpdater::updateUnfillable] did we get any price? ${order.id.slice(0, 8)}|${index}`,
price ? price.amount : 'no :('
)
price?.amount && updateIsUnfillableFlag(chainId, order, price)
})
)
} finally {
isUpdating.current = false
console.debug(`[UnfillableOrdersUpdater] Checked canceled orders in ${Date.now() - startTime}ms`)
}
}, [account, chainId, updateIsUnfillableFlag])

useEffect(() => {
Expand Down