Skip to main content
Building a wallet tracker used to mean writing chain-specific RPC logic for every network, normalizing token decimals, fetching prices separately, and stitching it all together. In 2026, you can skip all of that. This tutorial shows how to build a fully functional multi-chain wallet tracker in under 10 minutes using the Mobula API — one endpoint, all chains, aggregated PnL included.

What You’ll Build

A CLI wallet tracker that:
  • Fetches all token holdings across every chain (EVM + Solana)
  • Shows current USD value and 24h PnL per token
  • Displays total portfolio value and overall PnL
Time to build: ~10 minutes Lines of code: ~50 API calls needed: 1

Prerequisites


Step 1: Install the SDK

npm install @mobula_labs/sdk

Step 2: Fetch the Portfolio

import { MobulaClient } from "@mobula_labs/sdk";

const client = new MobulaClient({
  apiKey: process.env.MOBULA_API_KEY,
});

async function getWalletPortfolio(address: string) {
  const { data } = await client.wallet.portfolio({
    wallet: address,
  });

  return data;
}
That’s the entire data-fetching layer. One call returns balances, prices, and PnL across all chains.

Step 3: Display the Results

async function main() {
  const address = process.argv[2];
  if (!address) {
    console.error("Usage: ts-node tracker.ts <wallet-address>");
    process.exit(1);
  }

  console.log(`\nFetching portfolio for ${address}...\n`);

  const portfolio = await getWalletPortfolio(address);

  // Total portfolio value
  console.log(`Total Value: $${portfolio.total_wallet_balance.toFixed(2)}`);
  console.log(`24h PnL: $${portfolio.total_realized_pnl.toFixed(2)}\n`);

  // Top holdings
  console.log("Holdings:");
  console.log("─".repeat(60));

  const sorted = portfolio.assets
    .filter((a) => a.estimated_balance > 1)
    .sort((a, b) => b.estimated_balance - a.estimated_balance)
    .slice(0, 20);

  for (const asset of sorted) {
    const pnl = asset.realized_pnl ?? 0;
    const pnlStr = pnl >= 0 ? `+$${pnl.toFixed(2)}` : `-$${Math.abs(pnl).toFixed(2)}`;
    console.log(
      `${asset.asset.symbol.padEnd(12)} $${asset.estimated_balance.toFixed(2).padStart(12)}  ${pnlStr.padStart(12)}  ${asset.asset.blockchains?.[0] ?? "unknown"}`
    );
  }
}

main().catch(console.error);

Step 4: Run It

MOBULA_API_KEY=your_key ts-node tracker.ts 0xYourWalletAddress
Output:
Fetching portfolio for 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045...

Total Value: $4,821,334.12
24h PnL: +$142,891.44

Holdings:
────────────────────────────────────────────────────────────
ETH          $2,341,200.00    +$89,200.00   ethereum
USDC           $812,450.00          $0.00   base
ARB            $234,100.00    +$12,400.00   arbitrum
...

What the API Returns

The /api/2/wallet/portfolio endpoint gives you:
  • total_wallet_balance — total USD value across all chains
  • total_realized_pnl — realized PnL since first tracked transaction
  • assets[] — array of token holdings, each with:
    • asset.symbol, asset.name, asset.logo
    • token_balance — raw token amount
    • estimated_balance — USD value
    • realized_pnl, unrealized_pnl
    • asset.blockchains — which chains the token exists on

Add Historical Balance

Want to show a balance chart over time? One more call:
const history = await client.wallet.history({
  wallet: address,
  from: Date.now() - 30 * 24 * 60 * 60 * 1000, // 30 days
  to: Date.now(),
});

// history.data is an array of { timestamp, balance } points

Deploy as an API

Wrap it in a simple Express server:
import express from "express";
const app = express();

app.get("/portfolio/:address", async (req, res) => {
  const portfolio = await getWalletPortfolio(req.params.address);
  res.json(portfolio);
});

app.listen(3000);
You now have a production-ready multi-chain portfolio API.

Next Steps

  • Add DeFi positions/api/2/wallet/defi-positions for LP, lending, and staking
  • Track new wallets in real-time — subscribe via WebSocket for live balance updates
  • Label wallets/api/2/wallet/labels returns exchange labels, whale tags, and insider flags
Full API documentation → | SDK on npm →