WebSocket

Stream live prices, market state, accounts, blocks, and trades. It’s the same feed the uplong website uses, open to everyone, with no API key.

Connecting

wss://api.uplong.fun/ws
  • Messages are JSON text frames, in both directions.
  • Amounts are micro-USDC and prices are micro-USD, as integers: 83606360000 is $83,606.36.
  • Subscribe to as many channels as you need on one connection.

Requests

{ "method": "subscribe",   "subscription": { "type": "prices" } }
{ "method": "unsubscribe", "subscription": { "type": "prices" } }
{ "method": "subscribe",   "subscription": { "type": "account", "address": "<base58 address>" } }
{ "method": "ping" }

Every server message has the form { "channel": ..., "data": ... }. A subscribe or unsubscribe is confirmed with a subscriptionResponse echoing the request; a bad request gets an error message, and the connection stays open.

Channels

TypeSendsWhen
pricesThe live oracle price per marketWhenever a price changes, at least once a second, at most 20 a second
marketsBlock prices, open interest, pool, payout queue, feesEvery block
accountOne account’s balance, nonce, session key, positions, and queued winningsEvery block
positionsEvery open position on the exchange, largest first, each with its ownerEvery block
blocksA summary of each blockEach committed block
tradesOpens, closes, and liquidations in a blockEach committed block that has any

prices, markets, account, and positions send the current state as soon as you subscribe, so there’s nothing to fetch first.

prices

{ "channel": "prices",
  "data": { "prices": { "BTC": 83606360000, "ETH": 2533410000 }, "timestampMs": 1791746814302 } }

A market missing from prices has no fresh oracle price right now. See Oracle.

markets

An excerpt; some fields are left out (the full payload is the same as GET /markets).

{ "channel": "markets",
  "data": {
    "height": 8879, "oracleFresh": true, "chainId": "3f9a0c51d27e8b46",
    "minNotional": 10000000000, "maxSideGap": 10000000000000,
    "withdrawalFee": 1000000, "longClaimFee": 1000000,
    "pool": 211167956, "queuedProfit": 0, "queueLength": 0,
    "feesCollected": 3626227, "impactRetained": 481249157,
    "markets": [
      { "market": "BTC", "price": 83606360000, "maxLeverage": 1000,
        "openInterest": 3000000000, "longOpenInterest": 3000000000, "shortOpenInterest": 0,
        "longCap": null, "shortCap": null,
        "longRoom": 9997000000000, "shortRoom": 10003000000000 },
      { "market": "ETH", ... }
    ] } }

longRoom and shortRoom are how much new notional fits on each side right now; null is unlimited.

account

An excerpt; the full payload is the same as GET /account/:address.

{ "channel": "account",
  "data": {
    "address": "FQBE…Cj7M", "balance": 1392517066, "nonce": 49, "nextNonce": 49,
    "agent": "HLkK…NBm", "agentExpiresMs": 1791833200000,
    "longEarned": 1975000000, "longClaimed": 0,
    "positions": [
      { "id": 41, "market": "BTC", "side": "long", "margin": 10000000, "leverage": 1000,
        "notional": 10000000000, "entryPrice": 83600080000, "markPrice": 83599830000,
        "liquidationPrice": 83516480000, "unrealizedPnl": -29902, "grossPnl": -29902,
        "openedAtMs": 1791746800000 }
    ],
    "pendingClaims": [ { "positionId": 37, "remaining": 2170000, "ahead": 0 } ] } }
  • unrealizedPnl is what closing now would pay, after fees; grossPnl is before them.
  • nextNonce is the nonce to sign next. See API.
  • Up to 10 account subscriptions per connection.

positions

{ "channel": "positions",
  "data": { "height": 8879, "positions": [
    { "id": 41, "owner": "FQBE…Cj7M", "market": "BTC", "side": "long", "margin": 10000000,
      "leverage": 1000, "notional": 10000000000, "entryPrice": 83600080000,
      "markPrice": 83599830000, "liquidationPrice": 83516480000,
      "unrealizedPnl": -29902, "grossPnl": -29902, "openedAtMs": 1791746800000 }
  ] } }

blocks

{ "channel": "blocks",
  "data": { "height": 8880, "hash": "0x3d8c…f77d", "timestampMs": 1791746815303,
            "txCount": 2, "kinds": { "priceUpdate": 1, "deposit": 1 } } }

trades

{ "channel": "trades",
  "data": { "height": 6655, "events": [
    { "type": "positionOpened", "positionId": 39, "owner": "999q…MtXH", "market": "BTC",
      "side": "long", "margin": 10000000, "leverage": 50, "entryPrice": 83578225000 }
  ] } }

Events are positionOpened, positionClosed (with exitPrice, pnl after fees, grossPnl, impact, fee, profitPaid, profitQueued), and positionLiquidated (with price and marginLost).

Staying connected

  • The server sends a WebSocket ping every 30 seconds; most clients answer it on their own. Clients that can’t send ping frames, like browsers, can send { "method": "ping" } and get { "channel": "pong", "data": null }.
  • If you reconnect, subscribe again: subscriptions belong to a connection. The snapshots bring you back up to date.
  • A client that reads too slowly skips blocks rather than falling behind. Every markets and account message is a full snapshot, so the latest one is always complete; for every trade without gaps, page through GET /blocks or GET /trades.

Examples

JavaScript (browser or Node 22+)

const ws = new WebSocket("wss://api.uplong.fun/ws");

ws.onopen = () => {
  ws.send(JSON.stringify({ method: "subscribe", subscription: { type: "prices" } }));
  ws.send(JSON.stringify({ method: "subscribe", subscription: { type: "trades" } }));
};

ws.onmessage = (message) => {
  const { channel, data } = JSON.parse(message.data);
  if (channel === "prices") console.log("BTC", data.prices.BTC / 1e6);
  if (channel === "trades") for (const event of data.events) console.log(event.type, event.market);
};

Python

# pip install websockets
import asyncio, json, websockets

async def main():
    async with websockets.connect("wss://api.uplong.fun/ws") as ws:
        await ws.send(json.dumps({"method": "subscribe", "subscription": {"type": "prices"}}))
        async for raw in ws:
            message = json.loads(raw)
            if message["channel"] == "prices":
                print({market: price / 1e6 for market, price in message["data"]["prices"].items()})

asyncio.run(main())

Command line

npx wscat -c wss://api.uplong.fun/ws
> {"method":"subscribe","subscription":{"type":"blocks"}}

Wallet

Deposit USDC

Withdraw