The portfolio tracker queries native MON balance, ERC20 token holdings, LST positions, and Euler V2 vault positions for any wallet address - all in a single pass. USD values use the cross-oracle verified price from oracles.ts.
How It Works
getPortfolio returns a complete snapshot in one call
getPortfolioSummary returns a lightweight total-only view
getLSTPositions and getEulerPositions can be called independently for partial views
Full Example
import {
getPortfolio,
getPortfolioSummary,
getNativeBalance,
getTokenBalances,
getLSTPositions,
getEulerPositions,
} from 'rampart-monad'
const WALLET = '0xYourWalletAddress' as `0x${string}`
async function trackPortfolio(address: `0x${string}`) {
const portfolio = await getPortfolio(address)
const summary = await getPortfolioSummary(address)
console.log('=== Portfolio Summary ===')
console.log(`MON Balance: ${portfolio.nativeBalance.toFixed(4)} MON`)
console.log(`Total USD: $${summary.totalUSD.toFixed(2)}`)
console.log(`Tokens: ${portfolio.tokens.length}`)
console.log('\n--- LST Positions ---')
for (const lst of portfolio.lstPositions) {
console.log(` ${lst.token}: ${lst.balance.toFixed(4)} (≈ $${lst.valueUSD.toFixed(2)})`)
}
console.log('\n--- Euler Vaults ---')
for (const pos of portfolio.eulerPositions) {
console.log(` ${pos.asset}: ${pos.supplied.toFixed(4)} supplied @ ${(pos.apr * 100).toFixed(2)}% APR`)
}
}
await trackPortfolio(WALLET)
Example Output
=== Portfolio Summary ===
MON Balance: 142.5000 MON
Total USD: $3,568.15
Tokens: 3
--- LST Positions ---
aprMON: 50.0000 (≈ $17.70)
sMON: 25.0000 (≈ $8.85)
--- Euler Vaults ---
USDC: 1000.0000 supplied @ 8.21% APR
WETH: 0.5000 supplied @ 3.14% APR
Partial Queries
If you only need a specific section, use the individual functions to reduce RPC calls:
import { getLSTPositions, getEulerPositions, getTokenBalances } from 'rampart-monad'
const address = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' as `0x${string}`
// LST holdings only
const lsts = await getLSTPositions(address)
for (const lst of lsts) {
console.log(`${lst.token}: ${lst.balance.toFixed(4)} (${lst.underlyingMON.toFixed(4)} MON)`)
}
// Euler vault positions only
const euler = await getEulerPositions(address)
for (const pos of euler) {
console.log(`Euler/${pos.asset}: ${pos.supplied.toFixed(4)} @ ${(pos.apr * 100).toFixed(2)}%`)
}
// ERC20 token balances only
const tokens = await getTokenBalances(address)
for (const tok of tokens) {
console.log(`${tok.symbol}: ${tok.balance.toFixed(4)} ($${tok.valueUSD.toFixed(2)})`)
}
Tracking Multiple Wallets
import { getPortfolioSummary } from 'rampart-monad'
const wallets = [
'0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
'0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B',
'0x742d35Cc6634C0532925a3b8D4c9F8C3b4F7c3d9',
] as const
const summaries = await Promise.all(
wallets.map(async addr => {
const summary = await getPortfolioSummary(addr as `0x${string}`)
return { address: addr, ...summary }
})
)
summaries.sort((a, b) => b.totalUSD - a.totalUSD)
console.log('Wallet leaderboard:')
for (const [i, s] of summaries.entries()) {
console.log(` ${i + 1}. ${s.address.slice(0, 10)}… $${s.totalUSD.toFixed(2)}`)
}
Real-Time Polling
import { getPortfolioSummary } from 'rampart-monad'
const address = '0xYourWalletAddress' as `0x${string}`
let previousTotal = 0
async function watchPortfolio() {
while (true) {
const summary = await getPortfolioSummary(address)
const delta = summary.totalUSD - previousTotal
const sign = delta >= 0 ? '+' : ''
const changeStr = previousTotal > 0 ? ` (${sign}$${delta.toFixed(2)})` : ''
console.log(`[${new Date().toISOString()}] $${summary.totalUSD.toFixed(2)}${changeStr}`)
previousTotal = summary.totalUSD
// Poll every 12 seconds (~30 Monad blocks)
await new Promise(r => setTimeout(r, 12_000))
}
}
await watchPortfolio()
Computing Yield on Active Positions
import { getEulerPositions } from 'rampart-monad'
const address = '0xYourWalletAddress' as `0x${string}`
const positions = await getEulerPositions(address)
let totalAnnualYield = 0
for (const pos of positions) {
const annualYield = pos.valueUSD * pos.apr
totalAnnualYield += annualYield
console.log(
`Euler/${pos.asset.padEnd(6)}: $${pos.valueUSD.toFixed(2).padStart(10)} ` +
`@ ${(pos.apr * 100).toFixed(2)}% = $${annualYield.toFixed(2)}/yr`
)
}
console.log(`\nTotal projected annual yield: $${totalAnnualYield.toFixed(2)}`)
Notes
getPortfolio makes multiple RPC calls in parallel (native balance, ERC20 balances, LST balances, Euler vault positions). Typical response time on Monad is under 1 second.
- LST
underlyingMON reflects the current redemption value at the live exchange rate - useful for comparing LST positions on an apples-to-apples basis.
- Euler positions report the current supply APR, not a historical average. APR can change every block as utilisation shifts.
- Use
getPortfolioSummary for lightweight total-only queries (e.g. dashboard widgets) - it skips detailed position fetching.