Advanced Data Stream
Every trade and every liquidity change for the Pons tokens you name, pushed as they land. One socket covers the whole life of a token:
- On the bonding curve - each buy and sell on the Pons v2 curve, with the curve's fee and any creator or opening-snipe tax broken out.
- In Uniswap v4 after graduation - each swap in the token's pool, and each liquidity position opened or closed.
- In Uniswap V3 - the same for Pons v1 tokens, which launch straight into a 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.
This stream needs a free api key. Join the Telegram group to request one.
WS wss://api.shrine.trade/rh/api/stream/ws?key=YOUR_KEY&tokens=0x…,0x…
WS wss://api.shrine.trade/rh/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 Pons token, or both on one socket.
Copy this
- JavaScript
- Python
const KEY = "sk_…"; // your free api key
const TOKENS = ["0x94FDe7626988Ae15E406E89C2277cd1a820dfbD0"]; // any Pons tokens
const ws = new WebSocket(`wss://api.shrine.trade/rh/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} ${m.quoteSymbol} 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.
import json, websocket # pip install websocket-client
KEY = "sk_…" # your free api key
TOKENS = ["0x94FDe7626988Ae15E406E89C2277cd1a820dfbD0"] # any Pons tokens
def on_message(ws, raw):
m = json.loads(raw)
if m["type"] == "websocket_active":
print("following", len(m["tokens"]), "tokens from block", m["block"])
elif m["type"] == "trade":
print(f'{m["side"].upper()} {m["tokenAmountFormatted"]} {m["symbol"]} for {m["quoteAmountFormatted"]} {m["quoteSymbol"]} on {m["venue"]} by {m.get("origin")}')
elif m["type"] == "liquidity":
print(f'liquidity {m["action"]} {m["symbol"]} on {m["venue"]}: {m["liquidityDelta"]}')
elif m["type"] == "lagged":
print("read too slowly, missed", m["dropped"], "events")
url = f"wss://api.shrine.trade/rh/api/stream/ws?key={KEY}&tokens={','.join(TOKENS)}"
websocket.WebSocketApp(url, on_message=on_message).run_forever()
What you get
On connect, one websocket_active frame confirming what is being followed:
{
"type": "websocket_active",
"stream": "advanced",
"tokens": ["0x94FDe7626988Ae15E406E89C2277cd1a820dfbD0"],
"wallets": [],
"unknown": [],
"maxTokens": 50,
"maxWallets": 50,
"block": 57705543,
"upstream": "open"
}
unknown lists anything you asked for that the stream can't follow, with a reason: an address that isn't a Pons token, 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": "pons_curve",
"side": "buy",
"token": "0x94FDe7626988Ae15E406E89C2277cd1a820dfbD0",
"symbol": "LAPTOP",
"protocol": "PONS_V2",
"quoteToken": "0x…",
"quoteSymbol": "PLTR",
"origin": "0xf0816aa238BaA4774D41B88556292413A6059B75",
"caller": "0xEc20E594D28a17511264dc73a84cd4AA957B0ABc",
"tokenAmount": "885663926228359252587",
"tokenAmountFormatted": "885.663926228359252587",
"quoteAmount": "21060197598119",
"quoteAmountFormatted": "0.000021060197598119",
"price": "0.000000023779",
"curveFee": "210601975981",
"tax": "0",
"priceAfter": "0.000000023779",
"marketCap": "23.779",
"tokenReserve": "807536513474090402491482633",
"tokenReserveFormatted": "807536513.474090402491482633",
"quoteReserve": "2080401284608788604",
"quoteReserveFormatted": "2.080401284608788604",
"reservesSource": "curve",
"block": 55978479,
"timestamp": 1788550107,
"tx": "0xcf9c…",
"logIndex": 8
}
| Field | Meaning |
|---|---|
venue | pons_curve, uniswap_v4 (a graduated v2 token's pool) or uniswap_v3 (a v1 token's pool). |
side | buy - the quote asset went in and tokens came out. sell - the reverse. |
quoteToken / quoteSymbol | What the token is priced in: ETH (address zero), USDG, a tokenised stock. Amounts are in this. |
origin | The wallet that sent the transaction. Most trades go through a router - ours, Uniswap's, Pons's own site - 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. |
caller | Whoever called the venue: a router, or the wallet itself on a direct trade. |
tokenAmount / quoteAmount | Base units, plus a …Formatted decimal for each. On the curve these are what the curve received and paid out. |
price | Quote per token, from this trade's own two amounts. |
curveFee / tax | Curve trades only: the curve's fee and any creator or opening-snipe tax taken from the quote leg, base units. |
priceAfter | Quote per token once this trade is done: the pool's price for pool trades, this trade's own price on the curve. |
marketCap | priceAfter times the token's total supply, in the quote asset. Convert with the quote's own price if you want dollars. |
tokenReserve / quoteReserve | What the venue holds after the trade, base units plus …Formatted. On the curve, its real reserves. In a pool, the active range's virtual reserves derived from the swap's liquidity and price - what the next trade is priced against. reservesSource says which: curve or pool_virtual. |
sqrtPriceX96 / tick | Pool trades only: the pool's price after the swap, in Uniswap's own units. |
block / timestamp / tx / logIndex | Where it happened. block and logIndex together order events exactly. |
Liquidity
{
"type": "liquidity",
"venue": "uniswap_v4",
"action": "add",
"token": "0x…",
"symbol": "CONTRA",
"protocol": "PONS_V2",
"quoteToken": "0x0000000000000000000000000000000000000000",
"quoteSymbol": "ETH",
"origin": "0x…",
"caller": "0x…",
"liquidityDelta": "184467440737095516",
"tickLower": -887220,
"tickUpper": 887220,
"block": 57708240,
"timestamp": 1788779311,
"tx": "0x…",
"logIndex": 3
}
| Field | Meaning |
|---|---|
action | add or remove. |
liquidityDelta | Liquidity units added (positive) or removed (negative), in Uniswap's own measure. |
tokenAmount / quoteAmount | V3 pools report how much of each asset moved; v4 pools report only the liquidity delta, so these are absent there. |
tickLower / tickUpper | The position's price range. A full-range position on a Pons pool is the one Pons itself created at graduation. |
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, ours or Pons's site, 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 Uniswap v4 pool can only be attributed if the stream has seen that pool since it started or someone follows the token. Curve trades are always attributed. If you care about one graduated 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. The chain sees over a million trades a day. 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.
- Pons and Uniswap tokens supported. v2 (curve, then Uniswap v4) and v1 (Uniswap V3). A token that isn't a Pons launch 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.