Aurelia

Live wallet balances and positions

The balances and positions channels: a wallet's portfolio, its positions, or one position, sent again whenever they change.

Subscribe to balances with wallet: the wallet portfolio answer (its first 100 holdings), and again each time it changes. Subscribe to positions with wallet: the wallet positions answer for its 200 most recently traded tokens; with token too (an address, or native), position messages carry that one position. Each message replaces the one before; a new block or balancesAt alone is no change, and is not sent.

Subscribe:

{"op":"subscribe","id":"b","channel":"balances","chain":"solana","wallet":"Fm1Nzv3EcgGMW2MFHHGKjdVDbvHsMMtoRdoBDmUmsFFE"}
{"op":"subscribe","id":"q","channel":"positions","chain":"solana","wallet":"Fm1Nzv3EcgGMW2MFHHGKjdVDbvHsMMtoRdoBDmUmsFFE","token":"native"}
TriggerWhy
An indexed block moved the walletA swap it made, or an indexed transfer from or to it. Read at once, before other wallets.
Every 30 sPrices move, and some changes are not indexed: gas and BNB moved by contracts on BSC, anything outside DEX transactions on Solana.
The server's feed is back after an outageEverything followed is read again.

Balances come from the chain, so their reads are limited: a wallet's at most once every 5 s however many follow it, and at most 5 wallets a second per chain, moved wallets first. A socket holds few balances subscriptions (live.balances in GET /plans). A read that fails is tried again later, doubling the wait, and the last message stands meanwhile. Positions come from the index: a topic is read at most once a second.

Captured on a test instance: balances, trimmed to 2 holdings:

{"type":"subscribed","id":"b1","channel":"balances","chain":"evm:56","wallet":"0x3304e22ddaa22bcdc5fca2269b418046ae7b566a"}
{
  "id": "b1",
  "type": "balances",
  "data": {
    "chain": "evm:56",
    "wallet": "0x3304e22ddaa22bcdc5fca2269b418046ae7b566a",
    "indexedSince": 1790546261920,
    "labels": [
      "sniper",
      "fresh"
    ],
    "fundedBy": {
      "address": "0x8894e0a0c962cb723c1976a4421c95949be2d4e3",
      "amount": "0.25",
      "time": 1790616461920,
      "tx": "0x124aa51a8b73a7c373249b80ec4beb9fa4e80b4aa78a8bc73a64c781b3f2925d",
      "labels": []
    },
    "fundedByReason": null,
    "block": 1000748,
    "balancesAt": 1790618266812,
    "totalValueUsd": 214134,
    "pnl": {
      "realizedUsd": 59.5089770354906,
      "unrealizedUsd": 6.776263578034403e-14,
      "totalUsd": 59.50897703549067
    },
    "holdings": [
      {
        "kind": "token",
        "token": {
          "address": "0xa9fcda9bd321adeb7cbbbd30ef2dd0ed1d657777",
          "symbol": "TAX",
          "name": "Tax Token",
          "decimals": 18
        },
        "balance": "21500000",
        "priceUsd": 0.006,
        "valueUsd": 129000,
        "allocation": 0.6024265179747261,
        "thin": false,
        "position": {
          "quote": false,
          "trades": 22,
          "buys": 12,
          "sells": 10,
          "unpricedTrades": 0,
          "bought": "20118000",
          "sold": "9800",
          "open": "20108200",
          "boughtUsd": 1008,
          "soldUsd": 60,
          "avgBuyPriceUsd": 0.00005010438413361169,
          "avgSellPriceUsd": 0.006122448979591836,
          "priceUsd": 0.006,
          "priceAt": 1790618400000,
          "realizedPnlUsd": 59.5089770354906,
          "unrealizedPnlUsd": null,
          "totalPnlUsd": 59.5089770354906,
          "firstTradeAt": 1790546864920,
          "lastTradeAt": 1790618578665
        }
      },
      {
        "kind": "lp",
        "protocol": "pancakeswap-v2",
        "pool": "0x702e6533e0182381606adbe3ccbb77f682ccc58b",
        "position": null,
        "lpToken": {
          "address": "0x702e6533e0182381606adbe3ccbb77f682ccc58b",
          "balance": "2000000000000000000000",
          "supply": "100000000000000000000000",
          "share": 0.02
        },
        "tokens": [
          {
            "token": {
              "address": "0xa9fcda9bd321adeb7cbbbd30ef2dd0ed1d657777",
              "symbol": "TAX",
              "name": "Tax Token",
              "decimals": 18
            },
            "amount": "14000000",
            "fees": null,
            "raw": {
              "amount": "14000000000000000000000000",
              "fees": null
            },
            "priceUsd": 0.006,
            "valueUsd": 84000
          },
          {
            "token": {
              "address": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
              "symbol": "WBNB",
              "name": "Wrapped BNB",
              "decimals": 18
            },
            "amount": "0.14",
            "fees": null,
            "raw": {
              "amount": "140000000000000000",
              "fees": null
            },
            "priceUsd": 600,
            "valueUsd": 84.00000000000001
          }
        ],
        "range": null,
        "valueUsd": 84084,
        "feesUsd": null,
        "allocation": 0.39267001036734006,
        "thin": false
      }
    ],
    "unpriced": 0,
    "count": 6,
    "liquidity": {
      "protocols": [
        "pancakeswap-v2",
        "pancakeswap-v3",
        "uniswap-v2",
        "uniswap-v3"
      ],
      "incomplete": [],
      "notCovered": [
        {
          "protocol": "pancakeswap-infinity-cl",
          "reason": "its positions are not enumerable per owner"
        }
      ],
      "error": null
    }
  }
}

Captured on a test instance: one position, then the wallet buys more:

{"type":"subscribed","id":"q1","channel":"positions","chain":"evm:56","wallet":"0x3304e22ddaa22bcdc5fca2269b418046ae7b566a","token":"0xa9fcda9bd321adeb7cbbbd30ef2dd0ed1d657777"}
{"id":"q1","type":"position","data":{"chain":"evm:56","wallet":"0x3304e22ddaa22bcdc5fca2269b418046ae7b566a","labels":["sniper","fresh"],"indexedSince":1790546261920,"position":{"token":{"address":"0xa9fcda9bd321adeb7cbbbd30ef2dd0ed1d657777","symbol":"TAX","name":"Tax Token","decimals":18},"quote":false,"trades":22,"buys":12,"sells":10,"unpricedTrades":0,"bought":"20118000","sold":"9800","open":"20108200","boughtUsd":1008,"soldUsd":60,"avgBuyPriceUsd":0.00005010438413361169,"avgSellPriceUsd":0.006122448979591836,"priceUsd":0.006,"priceAt":1790618400000,"realizedPnlUsd":59.5089770354906,"unrealizedPnlUsd":null,"totalPnlUsd":59.5089770354906,"firstTradeAt":1790546864920,"lastTradeAt":1790618578665}}}
{"id":"q1","type":"position","data":{"chain":"evm:56","wallet":"0x3304e22ddaa22bcdc5fca2269b418046ae7b566a","labels":["sniper","fresh"],"indexedSince":1790546261920,"position":{"token":{"address":"0xa9fcda9bd321adeb7cbbbd30ef2dd0ed1d657777","symbol":"TAX","name":"Tax Token","decimals":18},"quote":false,"trades":23,"buys":13,"sells":10,"unpricedTrades":0,"bought":"20168000","sold":"9800","open":"20158200","boughtUsd":1308,"soldUsd":60,"avgBuyPriceUsd":0.00006485521618405395,"avgSellPriceUsd":0.006122448979591836,"priceUsd":0.006,"priceAt":1790618400000,"realizedPnlUsd":59.36441888139627,"unrealizedPnlUsd":null,"totalPnlUsd":59.36441888139627,"firstTradeAt":1790546864920,"lastTradeAt":1790618628209}}}

Errors: 400 (wallet missing), 429 too_many_balances, and as the routes answer them (422, 502).

Try it in the interactive docsCreate a free account