Skip to main content

Advanced Data Stream

Every trade and every liquidity change for the tokens you name, pushed as they land. One socket covers the whole life of a token, because on Arc a token has one venue for good:

  • Argus and LIFT v2 tokens: each swap in the token's Uniswap v4 pool, and each liquidity position opened or closed.
  • LIFT v1 tokens and plain listings: the same for their Uniswap v3 pool.

Use it for a strategy, a wallet tracker, volume and holder analytics, or a bot that reacts to what others do instead of only to launches. The launch feed tells you a token exists; this tells you what happens to it.

Free key, by request

This stream needs a free api key. Join the Telegram group to request one.

WS wss://api.shrine.trade/arc/api/stream/ws?key=YOUR_KEY&tokens=0x…,0x…
WS wss://api.shrine.trade/arc/api/stream/ws?key=YOUR_KEY&wallets=0x…,0x…

Follow tokens to get everything that happens to them, wallets to get everything they do on any token, or both on one socket.

Copy this

const KEY = "sk_…"; // your free api key
const TOKENS = ["0xb242508C29959aA165379BCfdb576070B24eE5A8"]; // any Argus or LIFT tokens

const ws = new WebSocket(`wss://api.shrine.trade/arc/api/stream/ws?key=${KEY}&tokens=${TOKENS.join(",")}`);

ws.onmessage = (e) => {
const m = JSON.parse(e.data);
if (m.type === "websocket_active") { console.log("following", m.tokens.length, "tokens from block", m.block); return; }
if (m.type === "trade") console.log(`${m.side.toUpperCase()} ${m.tokenAmountFormatted} ${m.symbol} for ${m.quoteAmountFormatted} USDC on ${m.venue} by ${m.origin}`);
if (m.type === "liquidity") console.log(`liquidity ${m.action} ${m.symbol} on ${m.venue}: ${m.liquidityDelta}`);
if (m.type === "lagged") console.warn("read too slowly, missed", m.dropped, "events");
};

// Change what you follow without reconnecting.
// ws.send(JSON.stringify({ subscribe: ["0x…"], unsubscribe: ["0x…"] }));

Node 22+ has WebSocket built in; older Node needs npm install ws.

What you get

On connect, one websocket_active frame confirming what is being followed:

{
"type": "websocket_active",
"stream": "advanced",
"tokens": ["0xb242508c29959Aa165379BCfdB576070b24ee5a8"],
"wallets": [],
"unknown": [],
"maxTokens": 50,
"maxWallets": 50,
"block": 22255848,
"upstream": "open"
}

unknown lists anything you asked for that the stream can't follow, with a reason: an address that is not an Argus or LIFT token and has no Uniswap pool against USDC, or not an address at all. The rest of the connection is events.

upstream is open when logs are flowing from the node and connecting while the subscription is being set up, which the first client to connect triggers; it takes a second or two. If a token you follow stays silent, check this before assuming the token is quiet.

Trades

{
"type": "trade",
"venue": "uniswap_v4",
"side": "buy",
"token": "0xb242508c29959Aa165379BCfdB576070b24ee5a8",
"symbol": "XEUS",
"protocol": "ARGUS",
"quoteToken": "0x3600000000000000000000000000000000000000",
"quoteSymbol": "USDC",
"origin": "0x702468CB17E0b46184281dfc8185BA19a43dF75C",
"caller": "0x4fcA4a51Ab4F23A7447b3284fBd7D73289A89Fb1",
"tokenAmount": "191577422625225790682028",
"tokenAmountFormatted": "191577.422625225790682028",
"quoteAmount": "495000",
"quoteAmountFormatted": "0.495",
"price": "0.000002583812",
"sqrtPriceX96": "127416838254128394112",
"tick": -406012,
"tokenReserve": "980245211035624581738236",
"tokenReserveFormatted": "980245.211035624581738236",
"quoteReserve": "2533261",
"quoteReserveFormatted": "2.533261",
"reservesSource": "pool_virtual",
"priceAfter": "0.000002584311",
"marketCap": "2584.311",
"block": 22255841,
"timestamp": 1790120094,
"tx": "0xafd16e429bd6cb0cbb401359740491a98c4acff6bb46c7a815ebf9d8fcecffd4",
"logIndex": 5
}
FieldMeaning
venueuniswap_v4 (Argus, LIFT v2, plain v4 pools) or uniswap_v3 (LIFT v1, plain v3 pools).
sidebuy: USDC went in and tokens came out. sell: the reverse.
protocolARGUS, LIFT or UNISWAP.
quoteToken / quoteSymbolAlways USDC on Arc, 6 decimals. Amounts are in it.
originThe wallet that sent the transaction. Most trades go through a router, ours or Uniswap's, so caller is a contract and origin is the person. Watch wallets by this. Missing on the rare event where the node didn't return the transaction in time.
callerWhoever called the pool: a router, or the wallet itself on a direct trade.
tokenAmount / quoteAmountBase units, plus a …Formatted decimal for each. The quote amount is what the pool saw, after the hook's fees.
priceUSDC per token, from this trade's own two amounts.
priceAfterUSDC per token once this trade is done, from the pool's price.
marketCappriceAfter times the token's total supply, in USDC.
tokenReserve / quoteReserveThe active range's virtual reserves after the trade, derived from the swap's liquidity and price, what the next trade is priced against. reservesSource is always pool_virtual on Arc.
sqrtPriceX96 / tickThe pool's price after the swap, in Uniswap's own units.
block / timestamp / tx / logIndexWhere it happened. block and logIndex together order events exactly.

Liquidity

{
"type": "liquidity",
"venue": "uniswap_v4",
"action": "add",
"token": "0x…",
"symbol": "XEUS",
"protocol": "ARGUS",
"quoteToken": "0x3600000000000000000000000000000000000000",
"quoteSymbol": "USDC",
"origin": "0x…",
"caller": "0x…",
"liquidityDelta": "184467440737095516",
"tickLower": -887200,
"tickUpper": 405400,
"block": 22255000,
"timestamp": 1790119000,
"tx": "0x…",
"logIndex": 3
}
FieldMeaning
actionadd or remove.
liquidityDeltaLiquidity units added (positive) or removed (negative), in Uniswap's own measure.
tokenAmount / quoteAmountV3 pools report how much of each asset moved; v4 pools report only the liquidity delta, so these are absent there.
tickLower / tickUpperThe position's price range. On a launchpad pool the one position is the launch itself, locked for good.

Following wallets

Pass wallets= in the URL, or send subscribeWallets, and every trade or liquidity change those wallets send comes through, whatever token it's on, with the token attributed. The match is on origin (the transaction sender) or caller, so a wallet trading through a router is still caught. Use it for copy-trading, whale watching, or following a creator's own wallet.

One limit: a wallet's swap in a pool nobody follows can only be attributed if the stream has seen that pool open since it started. If you care about one token, follow the token as well.

Control messages

Send JSON text frames to change what you follow; the reply is a subscribed message with the full current lists:

{ "subscribe": ["0x…", "0x…"], "unsubscribe": ["0x…"] }
{ "subscribeWallets": ["0x…"], "unsubscribeWallets": ["0x…"] }
{ "ping": true }

Add &pretty=1 to the URL to have every frame indented and newline-terminated, handy for watching a tape with curl.

{"type":"lagged","dropped":n} means your client read too slowly and n events were skipped rather than queued without bound. Process faster or follow fewer tokens.

Notes

  • Filtering is required. You name up to 50 tokens and 50 wallets per connection, and only their events come through. There is no "everything" mode.
  • Live. Events are pushed from a node subscription and arrive within about a second of the block, same as the launch feed.
  • Argus, LIFT and plain Uniswap tokens. Anything the trade endpoint can trade, the stream can follow. A token priced in something other than USDC is reported in unknown.
  • Limits. 50 tokens and 50 wallets per connection, one connection per key and per IP. Follow more on the one socket rather than opening a second; ask if you need more.