The Wallet Transfers API provides real-time monitoring of wallet-to-wallet transfers on Solana, capturing SOL and SPL token movements between addresses with transaction signatures and block information.

WebSocket Endpoint

wss://api.nolimitnodes.com/socket?apikey=YOUR_API_KEY

Subscribe

{
  "method": "dataSubscribe",
  "params": {
    "referenceId": "WALLET_TRANSFERS",
    "streams": [
      {
        "stream": "walletTransfersSubscribe",
        "params": {
          "token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
          "from_address": "optional_sender_address",
          "to_address": "optional_recipient_address"
        }
      }
    ]
  },
  "id": 1
}

Filter Parameters

from_address
string
Filter by sender wallet address.
to_address
string
Filter by recipient wallet address.
token
string
Filter by token mint address, or "Solana" for native SOL transfers.
min_amount
number
Minimum transfer amount filter.
max_amount
number
Maximum transfer amount filter.
All filter parameters are optional. Omit all to receive every wallet transfer event.

Subscription Confirmation

{
  "status": "Subscribed to wallet transfers",
  "subscription_id": "4db6df25-fa4f-4325-8652-ee3a9f9690b4",
  "stream": "walletTransfersSubscribe",
  "reference_id": "WALLET_TRANSFERS"
}

Transfer Event Response

{
  "method": "walletTransfersSubscribe",
  "subscription_id": "4db6df25-fa4f-4325-8652-ee3a9f9690b4",
  "result": {
    "from": "28fdboacCPayNxToWNfgNpkVpUuuhN9LyxfQKFt8vXjm",
    "to": "axmFmfqQwZGEUZeF3i3MqbRCDiGPfshtbdoBjk41k88",
    "amount": 1000000000,
    "token": "Solana",
    "transaction_signature": "4wBiX5Pw5QkJ7dmrZTSnqVP4axLsDNzB11f3vTHgbzcqLCKadBa48gCDoPe7CudLFHwwwnKDQMYXxCqmgFprVFAu",
    "block_num": "367222399",
    "block_time": "1758033052",
    "decimals": 9
  }
}

Response Fields

result
object

Transfer Information

  • from / to — The sender and recipient wallet addresses for the transfer.
  • amount — The raw transfer amount in the token’s smallest unit. Divide by 10^decimals for the human-readable value.
  • token — Either "Solana" for native SOL transfers or the SPL token mint address.
  • decimals — The number of decimal places for the token (9 for SOL, 6 for USDC, etc.).

Transaction Details

  • transaction_signature — Full Solana transaction signature for on-chain verification.
  • block_num / block_time — Block number and timestamp for ordering and time-based analysis. Note that these are returned as strings for this stream.

Unsubscribe

Request

{
  "method": "dataUnsubscribe",
  "params": {
    "subscriptionIds": ["4db6df25-fa4f-4325-8652-ee3a9f9690b4"],
    "referenceId": "UNSUB_REF"
  }
}

Response

{
  "status": "Unsubscribed",
  "unsubscribed_ids": ["4db6df25-fa4f-4325-8652-ee3a9f9690b4"],
  "reference_id": "UNSUB_REF"
}

Code Examples

const WebSocket = require("ws");

class WalletTransferMonitor {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.ws = null;
    this.transferCount = 0;
    this.walletGraph = {};
    this.volumeByToken = {};
  }

  connect() {
    this.ws = new WebSocket(
      `wss://api.nolimitnodes.com/socket?apikey=${this.apiKey}`
    );
    this.setupHandlers();
  }

  setupHandlers() {
    this.ws.on("open", () => {
      console.log("Connected to Wallet Transfers stream");
      this.subscribe();
    });

    this.ws.on("message", (data) => {
      const message = JSON.parse(data);
      if (message.method === "walletTransfersSubscribe") {
        this.processTransfer(message.result);
      } else {
        console.log("Info:", JSON.stringify(message));
      }
    });

    this.ws.on("error", (error) => {
      console.error("WebSocket error:", error.message);
    });

    this.ws.on("close", () => {
      console.log("Connection closed. Reconnecting in 5s...");
      setTimeout(() => this.connect(), 5000);
    });
  }

  subscribe(filters = {}) {
    this.ws.send(
      JSON.stringify({
        method: "dataSubscribe",
        params: {
          referenceId: "WALLET_TRANSFERS",
          streams: [
            {
              stream: "walletTransfersSubscribe",
              params: filters,
            },
          ],
        },
        id: 1,
      })
    );
  }

  processTransfer(tx) {
    this.transferCount++;
    const amount = tx.amount / Math.pow(10, tx.decimals);

    // Track volume by token
    if (!this.volumeByToken[tx.token]) {
      this.volumeByToken[tx.token] = { count: 0, totalAmount: 0 };
    }
    this.volumeByToken[tx.token].count++;
    this.volumeByToken[tx.token].totalAmount += amount;

    // Build wallet connection graph
    this.trackWalletConnection(tx.from, tx.to, tx.token, amount);

    console.log(`\n--- Transfer #${this.transferCount} ---`);
    console.log(`${tx.from.slice(0, 8)}... -> ${tx.to.slice(0, 8)}...`);
    console.log(`Amount: ${amount} ${tx.token === "Solana" ? "SOL" : tx.token.slice(0, 8) + "..."}`);
    console.log(`Block: ${tx.block_num} | Time: ${tx.block_time}`);
    console.log(`Tx: ${tx.transaction_signature.slice(0, 16)}...`);
  }

  trackWalletConnection(from, to, token, amount) {
    const key = `${from.slice(0, 8)}->${to.slice(0, 8)}`;
    if (!this.walletGraph[key]) {
      this.walletGraph[key] = { count: 0, tokens: {}, totalAmount: 0 };
    }
    this.walletGraph[key].count++;
    this.walletGraph[key].totalAmount += amount;

    if (!this.walletGraph[key].tokens[token]) {
      this.walletGraph[key].tokens[token] = 0;
    }
    this.walletGraph[key].tokens[token] += amount;
  }

  analyzeRelatedWallets(walletAddress) {
    const connections = Object.entries(this.walletGraph)
      .filter(([key]) => key.includes(walletAddress.slice(0, 8)))
      .sort((a, b) => b[1].count - a[1].count);

    console.log(`\nWallet connections for ${walletAddress.slice(0, 8)}...:`);
    connections.forEach(([key, data]) => {
      console.log(`  ${key}: ${data.count} transfers, total: ${data.totalAmount.toFixed(4)}`);
    });
    return connections;
  }
}

// Usage
const monitor = new WalletTransferMonitor("YOUR_API_KEY");
monitor.connect();

Use Cases

Wallet Cluster Analysis

  • Track transfer patterns between related wallets to identify wallet clusters and fund flows.
  • Build graph-based models of wallet relationships using sender/receiver connections.
  • Detect wash trading by identifying circular transfer patterns between a small set of wallets.
  • Monitor known wallets (exchanges, protocols, whales) to track capital movements.

Security Monitoring

  • Set up alerts for large transfers using min_amount to detect significant fund movements.
  • Monitor specific wallets using from_address or to_address filters for real-time notifications.
  • Track rapid outflows from a single wallet, which may indicate a compromised account.
  • Detect unusual transfer patterns such as many small transfers to a single address (dusting attacks).

Portfolio Tracking

  • Subscribe to your own wallet addresses to get real-time notifications of incoming and outgoing transfers.
  • Track specific token transfers using the token filter for portfolio management.
  • Build historical transfer records for accounting and tax reporting.
  • Monitor token distribution events by tracking transfers from known airdrop or vesting wallets.

Best Practices

  • Use filters to reduce message volume in production. Subscribing to all transfers generates high throughput.
  • Convert raw amounts to human-readable values by dividing by 10^decimals before displaying or storing.
  • Remember that block_num and block_time are returned as strings in this stream — parse them to integers for numerical operations.
  • Implement reconnection logic with exponential backoff to handle temporary connection drops.
  • Store transfer data with proper indexing on from, to, and token fields for efficient querying.
  • Set up separate subscriptions for different monitoring concerns (e.g., one for whale alerts, one for portfolio tracking) to keep processing logic clean.