Skip to main content
This endpoint is only available to Growth and Enterprise plans.

Endpoint Details

  • URL: wss://api.mobula.io
  • Event Type: position

Subscription Format

The position endpoint allows you to subscribe to a specific wallet’s position for a particular token on a blockchain, providing real-time updates on balance changes, trades, and P&L metrics.

Subscribe to Wallet Position

{
  "type": "position",
  "authorization": "YOUR-API-KEY",
  "payload": {
    "wallet": "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437",
    "token": "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7",
    "blockchain": "evm:1",
    "subscriptionId": "cupsey-trump-position",
    "subscriptionTracking": true
  }
}

Parameters

  • wallet (required): The wallet address to track. Addresses will be automatically checksummed
  • token (required): The token contract address. Use 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE for native tokens. Addresses will be automatically checksummed
  • blockchain (optional, default: "evm:1"): Blockchain identifier (e.g., "evm:1" for Ethereum, "evm:56" for BSC, "solana" for Solana)
  • subscriptionId (optional): Custom identifier for your WebSocket connection. Auto-generated if not provided
  • subscriptionTracking (optional, default: false): Include subscription details in response logs for debugging
Native Token Tracking: To track native tokens (ETH, BNB, SOL, etc.), use the address 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE (42 ‘E’s) as the token address.

Real-Time Updates

After subscribing, you’ll receive instant updates whenever the wallet’s position changes, including:
  • Balance changes
  • New trades (buys/sells)
  • Updated P&L metrics
  • Price movements

Position Update Response

{
  "wallet": "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437",
  "token": "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7",
  "chainId": "evm:1",
  "balance": 125000.50,
  "rawBalance": "125000500000000000000000",
  "amountUSD": 156250.625,
  "buys": 5,
  "sells": 2,
  "volumeBuyToken": 150000.0,
  "volumeSellToken": 25000.0,
  "volumeBuy": 187500.0,
  "volumeSell": 31250.0,
  "avgBuyPriceUSD": 1.25,
  "avgSellPriceUSD": 1.25,
  "realizedPnlUSD": 0.0,
  "unrealizedPnlUSD": 0.0,
  "totalPnlUSD": 0.0,
  "firstDate": "2025-01-15T10:30:00.000Z",
  "lastDate": "2025-01-20T14:45:00.000Z",
  "tokenDetails": {
    "address": "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7",
    "chainId": "evm:1",
    "name": "OFFICIAL TRUMP",
    "symbol": "TRUMP",
    "decimals": 18,
    "logo": "https://example.com/trump-logo.png",
    "price": 1.25,
    "priceChange24h": 5.2,
    "liquidity": 5000000.0,
    "marketCap": 1250000000.0
  }
}

Data Model

WalletPositionData

Each position update includes:
FieldTypeDescription
walletstringChecksummed wallet address
tokenstringChecksummed token contract address
chainIdChainIdBlockchain identifier (e.g., "evm:1")
balancenumberCurrent token balance (human-readable)
rawBalancestringRaw balance in smallest unit (wei, lamports, etc.)
amountUSDnumberCurrent position value in USD
buysnumberTotal number of buy transactions
sellsnumberTotal number of sell transactions
volumeBuyTokennumberTotal tokens bought
volumeSellTokennumberTotal tokens sold
volumeBuynumberTotal USD value of buys
volumeSellnumberTotal USD value of sells
avgBuyPriceUSDnumberAverage buy price in USD
avgSellPriceUSDnumberAverage sell price in USD
realizedPnlUSDnumberRealized profit/loss from closed positions
unrealizedPnlUSDnumberUnrealized profit/loss on current holdings
totalPnlUSDnumberTotal P&L (realized + unrealized)
firstDateDate | nullDate of first transaction
lastDateDate | nullDate of most recent transaction
tokenDetailsTokenDetails | undefinedOptional enriched token metadata

TokenDetails

FieldTypeDescription
addressstringToken contract address
chainIdChainIdBlockchain identifier
namestringToken name
symbolstringToken symbol
decimalsnumberToken decimals
logostring | nullToken logo URL
pricenumberCurrent token price in USD
priceChange24hnumber | null24h price change percentage
liquiditynumber | nullTotal liquidity in USD
marketCapnumber | nullMarket capitalization in USD

Use Cases

1. Copy Trading Bots

Monitor positions of successful traders (like Cupsey) and replicate their trades in real-time.
const socket = new WebSocket("wss://api.mobula.io");

socket.addEventListener("open", () => {
  // Track Cupsey's TRUMP position
  socket.send(JSON.stringify({
    type: "position",
    authorization: "YOUR_API_KEY",
    payload: {
      wallet: "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437",
      token: "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7",
      blockchain: "evm:1",
      subscriptionTracking: true
    }
  }));
});

socket.addEventListener("message", (event) => {
  const position = JSON.parse(event.data);
  
  // Execute copy trading logic
  if (position.buys > previousBuys) {
    console.log("🟢 Cupsey bought TRUMP!");
    executeCopyTrade("buy", position);
  } else if (position.sells > previousSells) {
    console.log("🔴 Cupsey sold TRUMP!");
    executeCopyTrade("sell", position);
  }
});

2. Portfolio Tracking

Track your own positions across multiple wallets and tokens.
const positions = [
  { wallet: "YOUR_WALLET", token: "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7", blockchain: "evm:1" }, // TRUMP
  { wallet: "YOUR_WALLET", token: "0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE", blockchain: "evm:1" }, // ETH
  { wallet: "YOUR_WALLET", token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", blockchain: "evm:1" }, // USDC
];

positions.forEach((pos) => {
  socket.send(JSON.stringify({
    type: "position",
    authorization: "YOUR_API_KEY",
    payload: pos
  }));
});

socket.addEventListener("message", (event) => {
  const position = JSON.parse(event.data);
  updatePortfolioDashboard(position);
  
  // Real-time P&L tracking
  console.log(`${position.tokenDetails.symbol}: $${position.totalPnlUSD.toFixed(2)} P&L`);
});

3. Whale Watching

Monitor whale wallets for significant position changes.
const whaleWallets = [
  "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437", // Cupsey
  "0x28C6c06298d514Db089934071355E5743bf21d60", // Binance 14
  "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", // Jump Trading
];

whaleWallets.forEach((whale) => {
  socket.send(JSON.stringify({
    type: "position",
    authorization: "YOUR_API_KEY",
    payload: {
      wallet: whale,
      token: "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7", // TRUMP
      blockchain: "evm:1"
    }
  }));
});

socket.addEventListener("message", (event) => {
  const position = JSON.parse(event.data);
  
  // Alert on large trades
  if (position.amountUSD > 100000) {
    sendAlert(`🐋 Whale alert: ${position.wallet} has $${position.amountUSD.toLocaleString()} in ${position.tokenDetails.symbol}`);
  }
});

Implementation Example

TypeScript/JavaScript

import WebSocket from 'ws';

const socket = new WebSocket("wss://api.mobula.io");

socket.addEventListener("open", () => {
  console.log("✅ Connected to Mobula Position Stream");
  
  // Subscribe to Cupsey's TRUMP position
  socket.send(JSON.stringify({
    type: "position",
    authorization: "YOUR_API_KEY",
    payload: {
      wallet: "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437",
      token: "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7",
      blockchain: "evm:1",
      subscriptionId: "cupsey-trump",
      subscriptionTracking: true
    }
  }));
});

socket.addEventListener("message", (event) => {
  const position = JSON.parse(event.data);
  
  console.log("📊 Position Update:");
  console.log(`  Token: ${position.tokenDetails?.symbol}`);
  console.log(`  Balance: ${position.balance.toLocaleString()} tokens`);
  console.log(`  Value: $${position.amountUSD.toLocaleString()}`);
  console.log(`  Total P&L: $${position.totalPnlUSD.toFixed(2)}`);
  console.log(`  Unrealized P&L: $${position.unrealizedPnlUSD.toFixed(2)}`);
  console.log(`  Avg Buy Price: $${position.avgBuyPriceUSD.toFixed(4)}`);
  console.log(`  Total Buys: ${position.buys}`);
  console.log(`  Total Sells: ${position.sells}`);
});

socket.addEventListener("error", (error) => {
  console.error("❌ WebSocket error:", error);
});

socket.addEventListener("close", () => {
  console.log("🔌 WebSocket connection closed");
});

Python

import websocket
import json

def on_message(ws, message):
    position = json.loads(message)
    
    print("📊 Position Update:")
    print(f"  Token: {position['tokenDetails']['symbol']}")
    print(f"  Balance: {position['balance']:,.2f} tokens")
    print(f"  Value: ${position['amountUSD']:,.2f}")
    print(f"  Total P&L: ${position['totalPnlUSD']:,.2f}")
    print(f"  Unrealized P&L: ${position['unrealizedPnlUSD']:,.2f}")

def on_open(ws):
    print("✅ Connected to Mobula Position Stream")
    
    subscription = {
        "type": "position",
        "authorization": "YOUR_API_KEY",
        "payload": {
            "wallet": "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437",
            "token": "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7",
            "blockchain": "evm:1",
            "subscriptionId": "cupsey-trump",
            "subscriptionTracking": True
        }
    }
    
    ws.send(json.dumps(subscription))

ws = websocket.WebSocketApp(
    "wss://api.mobula.io",
    on_message=on_message,
    on_open=on_open
)

ws.run_forever()

Unsubscribing from the Stream

Unsubscribe from All Position Streams

{
  "type": "unsubscribe",
  "authorization": "YOUR-API-KEY",
  "payload": {
    "type": "position"
  }
}

Unsubscribe from Specific Subscription

{
  "type": "unsubscribe",
  "authorization": "YOUR-API-KEY",
  "payload": {
    "subscriptionId": "cupsey-trump"
  }
}

Unsubscribe from Specific Position

{
  "type": "unsubscribe",
  "authorization": "YOUR-API-KEY",
  "payload": {
    "type": "position",
    "wallet": "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437",
    "token": "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7",
    "blockchain": "evm:1"
  }
}
If you didn’t provide a subscriptionId when subscribing, one is auto-generated. To retrieve it, set "subscriptionTracking": true in the subscription payload.

Best Practices

1. Connection Management

  • Implement automatic reconnection logic with exponential backoff
  • Handle WebSocket close events gracefully
  • Ping/pong to keep connection alive

2. Rate Limiting

  • Subscribe to a reasonable number of positions per connection
  • Use multiple connections for high-volume monitoring
  • Batch subscriptions when possible

3. Error Handling

socket.addEventListener("error", (error) => {
  console.error("WebSocket error:", error);
  // Implement retry logic
  setTimeout(() => reconnect(), 5000);
});

socket.addEventListener("close", (event) => {
  if (event.code !== 1000) { // 1000 = normal closure
    console.log("Abnormal closure, reconnecting...");
    reconnect();
  }
});

4. Data Validation

Always validate incoming data before processing:
interface WalletPositionData {
  wallet: string;
  token: string;
  chainId: string;
  balance: number;
  amountUSD: number;
  totalPnlUSD: number;
  // ... other fields
}

socket.addEventListener("message", (event) => {
  try {
    const position: WalletPositionData = JSON.parse(event.data);
    
    if (!position.wallet || !position.token) {
      throw new Error("Invalid position data");
    }
    
    processPosition(position);
  } catch (error) {
    console.error("Failed to process position update:", error);
  }
});

Example: Multi-Wallet Position Dashboard

const socket = new WebSocket("wss://api.mobula.io");
const positions = new Map<string, WalletPositionData>();

socket.addEventListener("open", () => {
  // Track multiple wallets and tokens
  const subscriptions = [
    { wallet: "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437", token: "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7", blockchain: "evm:1" }, // Cupsey - TRUMP
    { wallet: "0x1AFCADB658BcBC1c17ab4E663FFADA24B5aCF437", token: "0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE", blockchain: "evm:1" }, // Cupsey - ETH
    { wallet: "YOUR_WALLET", token: "0x576e2BeD8F7b46D34016198911Cdf9886f78bea7", blockchain: "evm:1" }, // Your - TRUMP
  ];
  
  subscriptions.forEach((sub, index) => {
    socket.send(JSON.stringify({
      type: "position",
      authorization: "YOUR_API_KEY",
      payload: {
        ...sub,
        subscriptionId: `position-${index}`,
        subscriptionTracking: true
      }
    }));
  });
});

socket.addEventListener("message", (event) => {
  const position = JSON.parse(event.data);
  const key = `${position.wallet}-${position.token}-${position.chainId}`;
  
  positions.set(key, position);
  
  // Calculate total portfolio value
  let totalValue = 0;
  let totalPnl = 0;
  
  positions.forEach((pos) => {
    totalValue += pos.amountUSD;
    totalPnl += pos.totalPnlUSD;
  });
  
  console.log("\n📊 Portfolio Summary:");
  console.log(`  Total Value: $${totalValue.toLocaleString()}`);
  console.log(`  Total P&L: $${totalPnl.toFixed(2)}`);
  console.log(`  Positions: ${positions.size}`);
});

Support

Can’t find what you’re looking for? Reach out to us, response times < 1h.