feat-polygon-rbf-monitoring
✨ New Features
Polygon RBF — replay route for stuck transactions
Goal: Provide an operational escape hatch when a Polygon transaction is stuck in the mempool due to insufficient gas price (e.g. after a fee spike), without requiring manual intervention at the node level.
Solution: Add POST /polygon/replay which fetches the original transaction (nonce, data, gasLimit), queries Polygon Gas Station for the current fast fee, and resubmits with the same nonce — forcing a Replace-By-Fee. Protected by the existing global HMAC auth guard.
Files Modified:
src/services/polygon/polygon.service.ts-replayTransaction()methodsrc/app.service.ts-replayPolygon()wrappersrc/app.controller.ts-POST /polygon/replayroute
🐛 Bug Fixes
Polygon verification error handling — false positives in New Relic
Goal: Eliminate spurious error spans in New Relic caused by normal pending-transaction states, and fix a silent bug where dropped transactions were never marked as failed.
Solution:
#verifyTransaction:TransactionDroppedErrornow re-throws instead of being swallowed by the internal catch, soverifyProofscan correctly push the proof tofailedProofs.verifyProofs:TransactionDroppedErroris handled as a business event (transaction.droppedspan event) without callingtriggerSpanError— no longer logged as an error.verifyProofs/validateProof: replacedthrow new Error('Empty transaction check')withreturn/return falsewhen#verifyTransactionreturnsnull(TX still pending) — pending is not an error.#verifyTransaction: guard againstundefinedtransactionHashto prevent0xundefinedRPC calls.- Removed spurious
console.warnfor pending transactions.
Files Modified:
src/services/polygon/polygon.service.ts- error propagation, guard, removed false throws
⚡ Improvements
RBF — proof file and DB consistency after replay
Goal: After a Replace-By-Fee operation, ensure proof files on disk and DB records all reference the new transaction hash so the forge can verify and confirm them normally without human intervention.
Solution:
- Before updating the DB, fetch pending proofs by old TX hash and rewrite each local proof file (
proofs/<uuid>) with the newtransactionHash. - Update DB records atomically with a
type: polygonfilter to avoid touching other proof systems. replayPolygonnow returns{ newTxHash, updatedProofs }and is wrapped in aReplay-polygonOTel span.- Added
ForgeTask.REPLAYenum value for consistent span naming.
Files Modified:
src/database/database.types.ts-ForgeTask.REPLAYsrc/database/database.service.ts-getPolygonPendingProofsByTxHash(),updatePolygonTransactionHash()(withtypefilter)src/services/polygon/polygon.service.ts-updateProofFiles()src/app.service.ts-replayPolygon()full flow + OTel span
Cleanup proof files on failed transactions
Goal: Prevent orphaned proof files accumulating on disk when a proof is marked failed (TX dropped from mempool).
Solution: Call polygonService.cleanup(failedProofs) immediately after dataService.failProofs() in verifyPolygon.
Files Modified:
src/app.service.ts- cleanup call added inverifyPolygon
OpenTelemetry transaction status attribute for New Relic alerting
Goal: Enable NRQL queries to detect Polygon transactions stuck in pending state for more than a configurable duration, so an alert can be created in New Relic without any external polling.
Solution: Add bcyip:transaction.status attribute (pending / confirming / confirmed / dropped) and bcyip:transaction.hash to every #verifyTransaction span. New Relic NRQL alert query:
FROM Span SELECT count(*)
WHERE name = '#verifyTransaction'
AND bcyip.transaction.status = 'pending'
SINCE 2 hours ago
FACET bcyip.transaction.hash
Files Modified:
src/services/polygon/polygon.service.ts- status + hash attributes on#verifyTransactionspan