Context
Follow-up to #42 (position-lifecycle alerts). The four watchers added there print the collateral address as raw hex:
Collateral: \`0x5052D3Cc819f53116641e89b96Ff4cD1EE80B182\`
For an operator that's not enough context — they have to look up the address manually to know whether it's WFPS, WBTC, WETH, or something else. This matters most for the mini-lifetime and phase-2 alerts, where the collateral is the key signal for whether the alert is actionable.
What to add
Resolve token metadata (symbol, name, decimals) when constructing each alert and include them in the message:
Collateral: WFPS (Wrapped FPS, 18 dec) \`0x5052D3Cc...\`
Balance: 4 WFPS (collateralAmount with proper decimals)
Liq. Price: 1,250.00 dEURO/WFPS
Affected messages in src/monitoringV2/position.service.ts:
checkMiniLifetimeClones
checkExpiringSoon
checkExpired
checkExpiredInPhase2
Implementation sketch
Two reasonable approaches:
- Repository join: extend
PositionRepository.findUnalerted* queries to include token data via Prisma relations. Requires defining a relation between PositionState.collateral and Token.address (currently they are independent tables).
- Service-level lookup: inject
TokenService (or TokenRepository) into PositionService, fetch tokens once per cycle, build a map by address, look up while constructing alerts.
(2) is cleaner because:
- avoids schema relations on what is effectively read-only join data
- token metadata is already cached in-memory by
TokenService
- isolates the change to alert construction, no migration needed
Out of scope for this issue
- Changing the underlying alert mechanism or dedup logic
- Price formatting beyond what
formatDeuro/symbol resolution provides
- Etherscan token name (we already display
collateralName if added)
Acceptance
- All four alert messages display collateral as
<symbol> (<name>) \`` with correctly-decoded balance/price using collateral decimals.
- Build clean, no schema migration required.
Context
Follow-up to #42 (position-lifecycle alerts). The four watchers added there print the collateral address as raw hex:
For an operator that's not enough context — they have to look up the address manually to know whether it's WFPS, WBTC, WETH, or something else. This matters most for the mini-lifetime and phase-2 alerts, where the collateral is the key signal for whether the alert is actionable.
What to add
Resolve token metadata (
symbol,name,decimals) when constructing each alert and include them in the message:Affected messages in
src/monitoringV2/position.service.ts:checkMiniLifetimeClonescheckExpiringSooncheckExpiredcheckExpiredInPhase2Implementation sketch
Two reasonable approaches:
PositionRepository.findUnalerted*queries to include token data via Prisma relations. Requires defining a relation betweenPositionState.collateralandToken.address(currently they are independent tables).TokenService(orTokenRepository) intoPositionService, fetch tokens once per cycle, build a map by address, look up while constructing alerts.(2) is cleaner because:
TokenServiceOut of scope for this issue
formatDeuro/symbol resolution providescollateralNameif added)Acceptance
<symbol> (<name>) \`` with correctly-decoded balance/price using collateral decimals.