Skip to content

refactor: Simplify Monitor balance reporting and delete TokenTransferClient#3111

Merged
nicholaspai merged 14 commits intomasterfrom
npai/monitor-simplification
Mar 26, 2026
Merged

refactor: Simplify Monitor balance reporting and delete TokenTransferClient#3111
nicholaspai merged 14 commits intomasterfrom
npai/monitor-simplification

Conversation

@nicholaspai
Copy link
Copy Markdown
Member

@nicholaspai nicholaspai commented Mar 25, 2026

Summary

Major simplification of the Monitor's balance reporting and spoke pool running balance logic:

  • Delete TokenTransferClient: Removed entirely — it was only used by Monitor and added complexity by querying ERC20 Transfer events per-chain. Balance reporting now uses direct on-chain balance queries instead.
  • Rewrite reportRelayerBalances(): Replaced the old multi-pass approach (initializeBalanceReportsupdateCurrentRelayerBalancesupdateLatestAndFutureRelayerRefunds → helpers for cross-chain transfers, L2 withdrawals, pending rebalances) with a single streamlined loop that:
    • Uses getInventoryBalanceContributorTokens() to discover L2 tokens per (l1Token, chainId) pair
    • Batches all balance requests into a single parallel fetch
    • Fetches pending L2 withdrawals in parallel
    • Rolls up cross-chain transfers, pending rebalances, and upcoming refunds inline
    • Outputs an aligned ASCII table per token (instead of the old markdown format)
  • Rewrite checkSpokePoolRunningBalances()reportSpokePoolRunningBalances(): Replaced the old approach that reconstructed pool rebalance roots and computed slow fill amounts from scratch with a call to the new getLatestRunningBalances() utility, producing a clean per-token table.
  • Remove L2_ONLY_TOKENS config: The L2Token interface, l2OnlyTokens config parsing, and related reporting are deleted — L2-only tokens are now handled naturally via getInventoryBalanceContributorTokens.
  • Remove stale interfaces: BalanceType, RelayerBalanceReport, RelayerBalanceTable, RelayerBalanceCell, TokenTransfer, TransfersByChain, TransfersByTokens — all deleted.
  • Fix BaseChainAdapter monitored addresses: Changed from Address[] to { [l1Token: string]: Address[] } so adapters only query bridge events for addresses relevant to each token's pool rebalance route. This prevents unnecessary queries for hub/spoke pool addresses on chains without a route for a given token.
  • Fix AdapterManager address filtering: Hub/spoke pool addresses are now excluded from monitored addresses for tokens that don't have a pool rebalance route on that chain.
  • Fix BinanceCEXBridge decimal handling: Finalization events now use L2 token decimals instead of L1 decimals, fixing incorrect amount conversions.
  • Fix outstanding transfer matching in BaseChainAdapter: Changed from per-event amount matching (which broke when L1/L2 decimals differed) to net-amount approach: sum all deposits, subtract all finalized amounts (with decimal conversion), then attribute the net outstanding amount to the newest unfinalized events.
  • Deduplicate spoke pool addresses in MonitorClientHelper: Prevents duplicate cross-chain transfer queries when multiple chains share the same spoke pool address.
  • Add monitored relayers to adapter manager: Monitored relayer addresses are now passed to the AdapterManager so cross-chain transfer queries include relayer bridges.

Test plan

  • Updated test/Monitor.ts — removed tests for deleted methods (initializeBalanceReports, updateCurrentRelayerBalances, updateLatestAndFutureRelayerRefunds), simplified test monitor class to MockMonitor that only overrides getTokenInfo for test tokens
  • Run full test suite
  • Deploy to staging monitor and verify balance reports render correctly
  • Verify spoke pool running balance reports against production data

🤖 Generated with Claude Code

nicholaspai and others added 6 commits March 25, 2026 11:36
…inance deposit matching, and floatToBN fix

- TokenUtils: getInventoryEquivalentL1TokenAddress, getInventoryBalanceContributorTokens, isL2OnlyEquivalentToken
- RunningBalanceUtils: getLatestRunningBalances extracted for shared use
- BinanceUtils: getOutstandingBinanceDeposits for cross-L2 deposit matching, export BinanceDeposit type
- BNUtils: Fix floatToBN MAX_SAFE_INTEGER overflow via string manipulation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t, InventoryClient, TokenClient

- BundleDataApproxClient: returns values in L1 token decimals, groups deposits/refunds across
  inventory-equivalent L2 tokens, restores requireExecution param, fixes refund decimal conversion
- InventoryClient: uses getInventoryEquivalentL1TokenAddress, getInventoryBalanceContributorTokens,
  getLatestRunningBalances; adds protected getTokenInfo for test mocking
- TokenClient: uses getInventoryBalanceContributorTokens for L2 token discovery
- Test updates: alias config for USDC, L1-decimal refunds, MockInventoryClient getTokenInfo override

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- BinanceCEXBridge: rewrite getL2PendingWithdrawalAmount to correctly compute outstanding
  deposits when finalizer batches deposits from multiple L2s into single L1 withdrawal.
  Uses getOutstandingBinanceDeposits with Redis-cached deposit sender lookups.
- BaseChainAdapter: use getInventoryEquivalentL1TokenAddress, skip zero-amount outstanding
  transfers in getOutstandingCrossChainTransfers
- AdapterManager: minor cleanup
- MockLineaEvents: accept amount parameter for BridgingInitiatedV2/BridgingFinalizedV2
- Generic adapter tests: updated for zero-amount skip behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Client

- Monitor.reportRelayerBalances: rewritten to use getInventoryBalanceContributorTokens for
  per-chain L2 token discovery, batch-fetch all balances in parallel, produce aligned table
  per token. Adds protected getTokenInfo for test mocking. Fixes pending rebalance double-count
  by only applying to canonical L2 token.
- MonitorConfig: removes L2Token interface, l2OnlyTokens, L2_ONLY_TOKENS env var
- MonitorClientHelper: removes TokenTransferClient construction
- Delete TokenTransferClient (no longer needed)
- Delete unused BalanceType/RelayerBalanceReport/TokenTransfer interfaces

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1227d02411

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +398 to +399
if (isDefined(this.clients.rebalancerClient)) {
pendingRebalances = await this.clients.rebalancerClient.getPendingRebalances();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard pending rebalance fetch to keep monitor loop alive

This call now runs without any error handling, so a transient failure inside rebalancerClient.getPendingRebalances() (for example from an external bridge/CEX adapter) will throw out of reportRelayerBalances and abort the entire monitor iteration. The previous flow handled this path defensively and continued with zero pending rebalances, so this is a resilience regression that can suppress unrelated monitoring checks.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't error and if it does we want to know

Base automatically changed from npai/client-bundle-inventory to master March 26, 2026 15:51
@nicholaspai
Copy link
Copy Markdown
Member Author

@codex re review

@chatgpt-codex-connector
Copy link
Copy Markdown

Summary

  • Added a defensive try/catch around rebalancerClient.getPendingRebalances() inside Monitor.reportRelayerBalances(), so transient failures no longer abort the monitor iteration. The code now logs an error and continues with empty pending rebalance data. src/monitor/Monitor.tsL410-L422
  • Kept pending rebalance behavior unchanged when fetch succeeds; this is strictly a resilience guard around the fetch path. src/monitor/Monitor.tsL411-L415
  • Documentation updates were not needed for this targeted runtime hardening change (no config/interface/runtime-flow contract changed beyond error tolerance in one call path). src/monitor/Monitor.tsL405-L424

Testing

  • ⚠️ yarn test test/Monitor.ts (fails in this environment: Yarn workspace/lockfile mismatch — package not present in lockfile).

View task →

bmzig
bmzig previously approved these changes Mar 26, 2026
- MonitorClientHelper: Should filter out duplicate spoke pool address strings passed into AdapterManager
- AdapterManager: should filter out hub/spoke pool addresses from monitored addresses passed to BaseChainAdapter if the token doesn't have a pool rebalance route to that chain.
- BaseChainAdapter: computes outstanding l1->l2 transfer amount using net amount approach rather than marking off events one by one, which better supports adapters with Binance which don't have this 1:1 relationship assumption
@nicholaspai
Copy link
Copy Markdown
Member Author

@codex

@bmzig I fixed various issues here can you PTAL: fe5e120 (details in commit message)

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe5e120254

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const totalAmount = totalDepositedAmount.sub(totalFinalizedAmount);
let remainingUnfinalizedAmount = totalAmount;
if (remainingUnfinalizedAmount.gt(0)) {
for (const depositEvent of depositInitiatedEvents) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude ignored bridge tx refs when attributing outstanding hashes

The net outstanding amount is computed from deposits filtered by ignoredPendingBridgeTxnRefs, but the tx-hash attribution loop still iterates the unfiltered depositInitiatedEvents. In cases where ignored bridge txs are present, those ignored refs can be recorded as outstanding (and consume remainingUnfinalizedAmount) while real outstanding txs are omitted, which breaks diagnostics and any alerting that relies on depositTxHashes.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid, fixed this here 474a382

@nicholaspai
Copy link
Copy Markdown
Member Author

@codex @claude

@chatgpt-codex-connector
Copy link
Copy Markdown

Summary

  • Added defensive error handling around rebalancerClient.getPendingRebalances() in Monitor.reportRelayerBalances() so transient fetch failures no longer abort the monitor reporting cycle; on failure, the monitor now logs and continues with an empty pending-rebalance map. src/monitor/Monitor.tsL410-L422
  • Documentation updates were not needed for this targeted resilience fix because no config/interface/runtime contract changed beyond fallback behavior on one read path. src/monitor/Monitor.tsL405-L424
  • Committed on the current branch as fc59457 and created a follow-up PR via the make_pr tool titled “[Follow-up] Guard Monitor pending rebalance fetch failures”.

Testing

  • ⚠️ yarn test test/Monitor.ts (fails in this environment due to Yarn workspace/lockfile mismatch: package missing from lockfile).

View task →

@nicholaspai nicholaspai merged commit 4feb9dd into master Mar 26, 2026
4 checks passed
@nicholaspai nicholaspai deleted the npai/monitor-simplification branch March 26, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants