Portfolio & PnL engine logo

Portfolio & PnL engine

Real-time holdings, PnL and cost basis across 9 chains.

Role
Built and own it (490 of 500 commits)
Stack
TypeScriptRabbitMQRedisPostgresAlchemyTriton

The portfolio service answers the question every trader asks first: what do I hold, and am I up? It tracks holdings, realized and unrealized PnL, and average buy price for every wallet on Boba, across 8 EVM chains and Solana, and updates as trades land.

I built the first version in Python in late 2025, then rewrote it in TypeScript as Portfolio V2 once I understood the real problem — which wasn't fetching balances, but recording each trade exactly once when several systems all see it.

Decisions

The queue is the source of truth

The execution layer signed the trade, so it knows things a wallet monitor can only guess, like whether a swap was one leg of a bridge. I made the RabbitMQ consumer the system of record. When it and the monitor disagree, the queue wins.

Late beats double-booked

A monitor and a bridge subscriber once booked the same transaction, and a $5 buy showed a −103% return. Now the monitor holds every detection for about 20 seconds and books only what no one else claimed. The hold queue lives in a Redis sorted set, so a restart can't lose a trade.

Measure, then cut

Moving a balance clamp from write time to read time made ingest order-independent and roughly tripled throughput. Worker-thread pools went the other way: profiling showed no measurable gain, so I deleted the unused one.

What I built

  • Swap detection over Alchemy WebSockets on EVM and Triton gRPC on Solana. I forked the Alchemy SDK to add Monad, ApeChain and HyperEVM.
  • A Redis claim protocol and cross-chain leg marking, so bridges through Relay and LiFi don't produce phantom trades. One shared cross-chain recording path replaced ~500 lines of duplicated logic.
  • Hourly snapshots for portfolio charts, spam and airdrop hiding, and backfill from the history service.

Performance

In local burst benchmarks the booking path handled around 1,600 trades per second across 32 wallets, with RabbitMQ publishing ~11,000 persistent messages per second at a 4.7ms p95 confirm.

Next in BobaWallet & KOL tracking

Austin, TX · —

© 2026 Guillermo Alvarez