Skip to main content

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() method
  • src/app.service.ts - replayPolygon() wrapper
  • src/app.controller.ts - POST /polygon/replay route

🐛 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: TransactionDroppedError now re-throws instead of being swallowed by the internal catch, so verifyProofs can correctly push the proof to failedProofs.
  • verifyProofs: TransactionDroppedError is handled as a business event (transaction.dropped span event) without calling triggerSpanError — no longer logged as an error.
  • verifyProofs / validateProof: replaced throw new Error('Empty transaction check') with return / return false when #verifyTransaction returns null (TX still pending) — pending is not an error.
  • #verifyTransaction: guard against undefined transactionHash to prevent 0xundefined RPC calls.
  • Removed spurious console.warn for 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 new transactionHash.
  • Update DB records atomically with a type: polygon filter to avoid touching other proof systems.
  • replayPolygon now returns { newTxHash, updatedProofs } and is wrapped in a Replay-polygon OTel span.
  • Added ForgeTask.REPLAY enum value for consistent span naming.

Files Modified:

  • src/database/database.types.ts - ForgeTask.REPLAY
  • src/database/database.service.ts - getPolygonPendingProofsByTxHash(), updatePolygonTransactionHash() (with type filter)
  • 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 in verifyPolygon

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 #verifyTransaction span