fix: keep block scanner awake while orders await confirmation#220
Merged
Conversation
On EVM chains an order can stall forever in OrderStatusConfirming and never
fire its notify when block_offset_confirm is enabled, even though the payment
is on-chain and has far more than enough confirmations.
Block scanning is demand-driven: syncBreak() halts the forward scan once
hasLookbackOrders() finds no "receivable" orders, and receivableOrderStatuses()
only listed {Waiting, Expired}. When an order moves Waiting -> Confirming and it
is the only pending order, the scanner stops and the in-memory chainBlockNum
freezes. With block_offset_confirm enabled, tradeConfirmHandle() requires
chainBlockNum - RefBlockNum >= ConfirmedOffset, so a frozen chainBlockNum means
the order never reaches the threshold and stays Confirming indefinitely: no
notify is sent and the merchant is never credited. Low-traffic merchants hit
this on essentially every order.
Include OrderStatusConfirming in receivableOrderStatuses() so the scanner keeps
advancing while any order is awaiting confirmation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On EVM chains an order can get stuck in
OrderStatusConfirmingforever and never fire itsnotify— the payment is on-chain and has far more than enough confirmations, but the merchant is never credited. It happens whenblock_offset_confirmis enabled and the confirming order is the only pending order (typical for low-traffic merchants).Root cause
Block scanning is demand-driven.
syncBreak()halts the forward scan oncehasLookbackOrders()finds no "receivable" orders, andreceivableOrderStatuses()only returned{Waiting, Expired}:When an order transitions
Waiting → Confirmingand it is the only pending order,hasLookbackOrders()becomes false, the forward scan stops, and the in-memorychainBlockNumfreezes.With
block_offset_confirmenabled,tradeConfirmHandle()gates confirmation onchainBlockNum - RefBlockNum >= ConfirmedOffset(e.g. 40 on Polygon). A frozenchainBlockNumtherefore never reaches the threshold, so the order staysConfirmingindefinitely — no notify, merchant never credited. It does not recover across restarts, because with no waiting/expired order the scanner correctly stays idle.(With
block_offset_confirmdisabled the confirmation gate is skipped, so this only bites deployments that enable confirmations on an EVM chain — which is exactly the safe choice against reorgs.)Fix
Include
OrderStatusConfirminginreceivableOrderStatuses()so the scanner keeps advancing while any order is awaiting confirmation.Validation
Reproduced on Polygon (
block_offset_confirm=1,ConfirmedOffset=40): a lone confirming order backed by a real, on-chain-confirmed USDT transfer (500+ confirmations) stayed inConfirmingforever on an unpatched build — the scanner was idle andchainBlockNumwas frozen. With this change the scanner stays awake,chainBlockNumadvances,tradeConfirmHandle()promotes the order to success, and the notify fires.🤖 Generated with Claude Code