高级数据流
你指定的代币的每一笔交易和每一次流动性变化,上链即推送。一个 socket 覆盖代币的整个生命周期,因为在 Arc 上一个代币永远只有一个场所:
- Argus 和 LIFT v2 代币:代币 Uniswap v4 池里的每一笔 swap,以及每一个开仓或平仓的流动性头寸。
- LIFT v1 代币和普通挂牌:它们 Uniswap v3 池里的同样内容。
用它做策略、钱包追踪、成交量和持有人分析,或者一个对别人的动作而不只是对发射做出反应的机器人。发射推送 告诉你一个代币存在了;这个数据流告诉你它接下来发生了什么。
这个数据流需要一个免费的 api key。加入 Telegram 群 申请。
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…
关注代币,收到发生在它们身上的一切;关注钱包,收到它们在任何代币上做的一切;也可以在一个 socket 上同时关注两者。
复制这段
- JavaScript
- Python
const KEY = "sk_…"; // 你的免费 api key
const TOKENS = ["0xb242508C29959aA165379BCfdb576070B24eE5A8"]; // 任意 Argus 或 LIFT 代币
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("正在关注", m.tokens.length, "个代币,起始区块", m.block); return; }
if (m.type === "trade") console.log(`${m.side.toUpperCase()} ${m.tokenAmountFormatted} ${m.symbol},花费 ${m.quoteAmountFormatted} USDC,场所 ${m.venue},钱包 ${m.origin}`);
if (m.type === "liquidity") console.log(`流动性 ${m.action} ${m.symbol},场所 ${m.venue}:${m.liquidityDelta}`);
if (m.type === "lagged") console.warn("读取太慢,漏掉", m.dropped, "条事件");
};
// 不断开连接即可更改关注列表。
// ws.send(JSON.stringify({ subscribe: ["0x…"], unsubscribe: ["0x…"] }));
Node 22+ 内置 WebSocket;更老的 Node 需要 npm install ws。
import json, websocket # pip install websocket-client
KEY = "sk_…" # 你的免费 api key
TOKENS = ["0xb242508C29959aA165379BCfdb576070B24eE5A8"] # 任意 Argus 或 LIFT 代币
def on_message(ws, raw):
m = json.loads(raw)
if m["type"] == "websocket_active":
print("正在关注", len(m["tokens"]), "个代币,起始区块", m["block"])
elif m["type"] == "trade":
print(f'{m["side"].upper()} {m["tokenAmountFormatted"]} {m["symbol"]},花费 {m["quoteAmountFormatted"]} USDC,场所 {m["venue"]},钱包 {m.get("origin")}')
elif m["type"] == "liquidity":
print(f'流动性 {m["action"]} {m["symbol"]},场所 {m["venue"]}:{m["liquidityDelta"]}')
elif m["type"] == "lagged":
print("读取太慢,漏掉", m["dropped"], "条事件")
url = f"wss://api.shrine.trade/arc/api/stream/ws?key={KEY}&tokens={','.join(TOKENS)}"
websocket.WebSocketApp(url, on_message=on_message).run_forever()
你会收到什么
连接后先收到一条 websocket_active,确认正在关注的内容:
{
"type": "websocket_active",
"stream": "advanced",
"tokens": ["0xb242508c29959Aa165379BCfdB576070b24ee5a8"],
"wallets": [],
"unknown": [],
"maxTokens": 50,
"maxWallets": 50,
"block": 22255848,
"upstream": "open"
}
unknown 列出你请求但数据流无法关注的内容,并附原因:不是 Argus 或 LIFT 代币、也没有对 USDC 的 Uniswap 池的地址,或者根本不是地址。之后的连接内容全是事件。
upstream 为 open 表示节点日志正在流入,connecting 表示订阅正在建立中,由第一个连接的客户端触发,需要一两秒。如果你关注的代币一直没动静,先看这个字段,再判断是不是代币本身冷清。
交易
{
"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
}
| 字段 | 含义 |
|---|---|
venue | uniswap_v4(Argus、LIFT v2、普通 v4 池)或 uniswap_v3(LIFT v1、普通 v3 池)。 |
side | buy:USDC 进、代币出。sell:相反。 |
protocol | ARGUS、LIFT 或 UNISWAP。 |
quoteToken / quoteSymbol | 在 Arc 上永远是 USDC,6 位小数。金额以它计。 |
origin | 发送交易的钱包。大多数交易经过 router(我们的或 Uniswap 的),所以 caller 是合约,origin 才是人。按它追踪钱包。极少数情况下节点没及时返回交易,此字段缺失。 |
caller | 调用池子的一方:router,或直接交易时的钱包本身。 |
tokenAmount / quoteAmount | 最小单位,各配一个 …Formatted 十进制。quote 金额是池子看到的,已扣除 hook 的费用。 |
price | 由这笔交易自己的两个金额算出的每个代币 USDC 价格。 |
priceAfter | 这笔交易完成后每个代币的 USDC 价格,来自池子价格。 |
marketCap | priceAfter 乘以代币总供应量,以 USDC 计。 |
tokenReserve / quoteReserve | 交易后当前区间的虚拟储备,由 swap 的流动性和价格推出,下一笔交易就按它定价。在 Arc 上 reservesSource 永远是 pool_virtual。 |
sqrtPriceX96 / tick | swap 后池子的价格,Uniswap 自己的单位。 |
block / timestamp / tx / logIndex | 发生位置。block 加 logIndex 可以精确排序事件。 |
流动性
{
"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
}
| 字段 | 含义 |
|---|---|
action | add 或 remove。 |
liquidityDelta | 增加(正)或移除(负)的流动性单位,Uniswap 自己的度量。 |
tokenAmount / quoteAmount | V3 池报告两种资产各移动了多少;v4 池只报告流动性变化量,所以这里没有这两个字段。 |
tickLower / tickUpper | 头寸的价格区间。发射平台池子上唯一的头寸就是发射本身,永久锁定。 |
关注钱包
在 URL 里传 wallets=,或发送 subscribeWallets,这些钱包发出的每一笔交易或流动性变化都会推送过来,不管是哪个代币,并附上代币归属。匹配依据是 origin(交易发送者)或 caller,所以经过 router 交易的钱包也能捕获。可用于跟单、盯大户,或者跟踪创作者自己的钱包。
一个限制:钱包在没人关注的池子里的 swap,只有当数据流启动后见过该池子开池时才能归属。如果你在意某个代币,同时关注这个代币。
控制消息
发送 JSON 文本帧更改关注内容;回复是一条带完整当前列表的 subscribed 消息:
{ "subscribe": ["0x…", "0x…"], "unsubscribe": ["0x…"] }
{ "subscribeWallets": ["0x…"], "unsubscribeWallets": ["0x…"] }
{ "ping": true }
在 URL 里加 &pretty=1,每一帧都会缩进并以换行结尾,方便用 curl 盯盘。
{"type":"lagged","dropped":n} 表示你的客户端读取太慢,n 条事件被跳过而不是无限排队。处理快一点,或者少关注几个代币。