Robinhood 链上怎么听 meme / 新币发射:订阅日志与 mint 信号
「meme / 新币发射」在这篇里指 Robinhood Chain 上可观测的合约事件流(ERC-20 Transfer / mint 类 log、池子创建类事件),不是 Robinhood App 推送,也不是荐币、抢跑或刷单教战。
目标:用 BlockReq 公共 RPC,把「发射信号」做成可过滤的 logs 订阅与 HTTP 回补——看板、告警、对账用得上。听到事件 ≠ 能盈利;链上可观测只保证你看到公开事实,不保证流动性、可信度或收益。
| 用途 | Endpoint |
|---|---|
| 公共 HTTPS | https://robinhood-mainnet-rpc.blockreq.com/v1/rpc/public |
| 公共 WSS | wss://robinhood-mainnet-rpc.blockreq.com/v1/rpc/public |
| 私有 HTTPS / WSS | 把末尾 public 换成你的 {API_KEY}(不要写进 demo) |
链身份:EVM,chainId = 0x1237(十进制 4663)。文档:公开端点 · eth_subscribe · Supported Networks。
系列分工(先看清再动手)
- 第 1 篇(开盘盯盘心跳):Robinhood 开盘怎么盯:用 RPC 订阅看盘(slug
robinhood-open-watch-rpc-subscribe)——主讲eth_subscribe → newHeads,logs 只作可选窄过滤。若该文尚未上线,以同系列草稿为准。 - 本文(第 2 篇):主讲 mint / 池子创建类logs信号——eth_subscribe logsvseth_getLogs、topic 过滤方法。 - Solana 发射(另一条链):浏览器里监听 Solana 新币发射——logsSubscribe+InitializeMint*,协议不同,别混 client。
1. 发射信号从哪来(链上 logs / 创建事件,不是 App 推送)
App 推送、社媒「发射提醒」、第三方机器人 webhook——都可能延迟、漏报,或夹带营销。可验证的发射窗口来自链上收据里的 logs:
| 信号类型 | 链上通常长什么样 | 适合盯什么 |
|---|---|---|
| 代币铸造 / 首批流通 | ERC-20 Transfer,且 from == 0x0…0(常见 mint 形态);或合约自定义 Mint / Launch 事件 | 「有没有新供应冒出来」 |
| 池子创建 | DEX factory 的 PairCreated / PoolCreated 等(以该链真实 ABI 为准) | 「有没有新交易对 / 池」 |
| 流动性注入 | Mint(Uniswap V2 风格)、IncreaseLiquidity 等 | 「池子有没有真金白银进去」 |
| 任意合约自定义事件 | 项目自己的 TokenCreated、Launched… | 只当你拿到 真实 ABI 并能算出 topic |
建议心态:
- 可观测 = 记录
blockNumber、txHash、address、topics、data。 - 不荐币 = 不点名具体 meme、不暗示「跟着买」。
- 不操纵 = 不写抢跑路径、不刷量、不教绕过平台风控。
把「事件出现」和「要不要交易」拆开:本文只做前半段,且明确——监听本身不保证盈利。
2. eth_subscribe logs vs 轮询 eth_getLogs
WSS eth_subscribe → logs | HTTPS eth_getLogs | |
|---|---|---|
| 形态 | 推送:事件一上链(节点看到后)就推 | 拉取:你指定 fromBlock / toBlock |
| 延迟 | 通常更贴实时,适合发射窗口看板 | 取决于轮询间隔;适合回放与断线回补 |
| 过滤 | address + topics(与 getLogs 同语义) | 同左;还可精确控块高窗口 |
| 漏消息 | 断线空窗要自补 | 你自己控窗口;窗口过大易撞限流 |
| 限流压力 | 裸订全链 logs 极易被踢;务必窄过滤 | 高频大窗口轮询容易打满 public IP 配额 |
| 适用 | 实时发射信号流 | 对账、回补、历史扫描 |
怎么选(短):
- 发射几分钟要盯实时流 → WSS 订 窄
logs(必带address或尽量窄的topics)。 - 断线 / 浏览器休眠后 → HTTPS
eth_getLogs按块分段回补。 - 生产正确性 → 订阅负责低延迟,getLogs 负责空窗(和系列第 1 篇、常见 EVM indexer 套路一致)。
订阅请求形态:
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_subscribe",
"params": [
"logs",
{
"address": "0xYourFactoryOrTokenAddress",
"topics": ["0xYOUR_EVENT_TOPIC0"]
}
]
}
回补请求形态(POST 到 HTTPS public):
{
"jsonrpc": "2.0",
"id": 2,
"method": "eth_getLogs",
"params": [{
"fromBlock": "0xFROM",
"toBlock": "0xTO",
"address": "0xYourFactoryOrTokenAddress",
"topics": ["0xYOUR_EVENT_TOPIC0"]
}]
}
3. 如何过滤 Transfer / mint / 池子创建类 topic
3.1 通用方法:topic0 = 事件签名的 keccak256
EVM log 的 topics[0] 是 事件签名字符串 的 Keccak-256(32 字节 hex):
topic0 = keccak256("EventName(type1,type2,...)")
注意:
- 名字与参数类型必须与 合约 ABI 完全一致(含
indexed不影响签名字符串本身,但会影响后面 topics 槽位)。 - 元组 / 结构体要按 ABI 编码规则展开;不要猜。
- Robinhood Chain 上的工厂、launchpad、代币实现可能与以太坊主网同名不同字节码——务必用该链上验证过的 ABI 或本地编译产物重算,不要照搬他链地址当过滤器。
浏览器里可用 ethers / viem 算(示意):
// ethers v6
import { id } from "ethers";
const topic0 = id("Transfer(address,address,uint256)");
// => 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
3.2 示例 topic(占位 + 一个可复用标准)
| 用途 | 签名(示意) | topic0 |
|---|---|---|
ERC-20 Transfer(标准) | Transfer(address,address,uint256) | 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef |
| 自定义 Mint | Mint(address,uint256) 等 | 0xYOUR_MINT_TOPIC ← 换成真实 ABI 算出的值 |
| 池子 / 交易对创建 | PairCreated(...) / PoolCreated(...) / 项目自定义 | 0xYOUR_PAIR_OR_POOL_CREATED_TOPIC ← 同上 |
| Launchpad 创建 | 项目自定义 TokenCreated / Launched… | 0xYOUR_LAUNCH_TOPIC ← 同上 |
Mint 常见两种看法(不要混为一谈):
- 标准 ERC-20:很多实现把 mint 记成
Transfer(from=0x0, to=recipient, value=amount)。过滤时除了topics[0]=Transfer,还要看topics[1](indexedfrom)是否为零地址,或在客户端解码后判断。 - 自定义
Mint事件:必须用该代币 / 工厂 ABI 算 topic;上表的0xYOUR_MINT_TOPIC只是占位。
池子创建同理: Uniswap V2/V3 风格事件在别的链上有公开 topic,但 Robinhood 上实际 factory 地址、事件名、参数列表可能不同。正确流程是:找到你要观察的 factory / launchpad 合约 → 取 ABI → 算 topic0 → 用 该合约 address + topic 订阅。
过滤示例(Transfer + 仅作演示的 mint-from-zero 客户端判断):
const TRANSFER =
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
const ZERO_TOPIC =
"0x0000000000000000000000000000000000000000000000000000000000000000";
// 订阅:尽量带 address;全链裸订 Transfer 噪音极大
const filter = {
address: "0xYourTokenOrFactory", // 必填更稳
topics: [TRANSFER],
};
// 推送到达后:粗判「像 mint」
function looksLikeMint(log) {
return log.topics?.[0] === TRANSFER && log.topics?.[1] === ZERO_TOPIC;
}
池子创建占位(请替换):
{
"address": "0xYourDexFactoryOnRobinhood",
"topics": ["0xYOUR_PAIR_OR_POOL_CREATED_TOPIC"]
}
再次强调:示例里的
0xYOUR_*不是可抄作业的主网万能 topic;换成你目标合约 ABI 算出的真实值。本文不提供、不推荐任何具体 meme 合约地址。
3.3 浏览器可跑:窄过滤 logs(默认 public)
把下面存成 robinhood-meme-mint-listen.html,用 npx serve 打开更稳(部分浏览器对 file:// WebSocket 挑剔)。只连 public,无 Key。默认订 你填写的合约地址 上的 Transfer;勾选「仅 from=0x0」可在客户端粗滤 mint 形态。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>Robinhood Chain · mint / logs 监听</title>
<style>
body { font-family: ui-sans-serif, system-ui, sans-serif; margin: 1.5rem; max-width: 52rem; }
button { margin-right: 0.5rem; }
#status { margin: 0.75rem 0; color: #334155; }
pre { background: #0f172a; color: #e2e8f0; padding: 1rem; min-height: 16rem;
overflow: auto; font-size: 12px; border-radius: 8px; }
code { background: #f1f5f9; padding: 0.1rem 0.35rem; border-radius: 4px; }
label { display: block; margin: 0.35rem 0; }
</style>
</head>
<body>
<h1>Robinhood Chain · 听 mint / Transfer logs</h1>
<p>公共 WSS · <code>eth_subscribe → logs</code> · 仅观测,不荐币、不下单。</p>
<p>WSS:<code>wss://robinhood-mainnet-rpc.blockreq.com/v1/rpc/public</code></p>
<p>
<input id="watchAddress" placeholder="0x… 代币或工厂地址(必填)" size="48" />
</p>
<p>
<input id="topic0" placeholder="topic0(默认 ERC-20 Transfer)" size="66"
value="0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" />
</p>
<label>
<input type="checkbox" id="mintOnly" checked />
仅显示 Transfer 且 from=0x0(粗滤 mint 形态;自定义 Mint 请改 topic0)
</label>
<button id="start" type="button">Start</button>
<button id="stop" type="button" disabled>Stop</button>
<button id="clear" type="button">Clear</button>
<div id="status">Idle · 监听 = 可观测事件,不保证盈利</div>
<pre id="out"></pre>
<script>
const WSS = "wss://robinhood-mainnet-rpc.blockreq.com/v1/rpc/public";
const ZERO =
"0x0000000000000000000000000000000000000000000000000000000000000000";
const out = document.getElementById("out");
const status = document.getElementById("status");
let ws = null;
let nextId = 1;
let backoffMs = 1000;
let wantRun = false;
const seen = new Set();
function log(line) {
const t = new Date().toISOString().slice(11, 19);
out.textContent = `[${t}] ${line}\n` + out.textContent;
}
function setStatus(s) { status.textContent = s; }
function send(method, params) {
const id = nextId++;
ws.send(JSON.stringify({ jsonrpc: "2.0", id, method, params }));
return id;
}
function subscribeLogs() {
const addr = document.getElementById("watchAddress").value.trim();
const topic = document.getElementById("topic0").value.trim();
if (!/^0x[a-fA-F0-9]{40}$/.test(addr)) {
log("请填写合法合约地址(避免全链裸订)");
return false;
}
if (!/^0x[a-fA-F0-9]{64}$/.test(topic)) {
log("topic0 须为 32 字节 hex");
return false;
}
send("eth_subscribe", ["logs", { address: addr, topics: [topic] }]);
log("sent eth_subscribe logs @ " + addr + " topic0=" + topic.slice(0, 10) + "…");
return true;
}
function connect() {
if (!wantRun) return;
setStatus("connecting…");
ws = new WebSocket(WSS);
ws.onopen = () => {
backoffMs = 1000;
if (!subscribeLogs()) {
wantRun = false;
document.getElementById("start").disabled = false;
document.getElementById("stop").disabled = true;
setStatus("未订阅:地址/topic 无效");
try { ws.close(); } catch {}
return;
}
setStatus("connected · subscribed(可观测 ≠ 盈利)");
};
ws.onmessage = (ev) => {
let msg;
try { msg = JSON.parse(ev.data); } catch { return; }
if (msg.id && msg.result && typeof msg.result === "string") {
log("subscription id=" + msg.result);
return;
}
if (msg.method !== "eth_subscription") return;
const r = msg.params && msg.params.result;
if (!r || !r.transactionHash) return;
if (document.getElementById("mintOnly").checked) {
if (!(r.topics && r.topics[1] === ZERO)) return;
}
const key = r.transactionHash + ":" + r.logIndex;
if (seen.has(key)) return;
seen.add(key);
const blk = r.blockNumber ? parseInt(r.blockNumber, 16) : "?";
log(
`log #${blk} tx=${r.transactionHash.slice(0, 12)}…` +
` addr=${r.address} topics=${(r.topics || []).length}`
);
};
ws.onclose = () => {
setStatus("closed");
if (!wantRun) return;
setStatus(`reconnect in ${backoffMs}ms`);
setTimeout(connect, backoffMs);
backoffMs = Math.min(backoffMs * 2, 30000);
};
ws.onerror = () => { try { ws.close(); } catch {} };
}
document.getElementById("start").onclick = () => {
wantRun = true;
document.getElementById("start").disabled = true;
document.getElementById("stop").disabled = false;
connect();
};
document.getElementById("stop").onclick = () => {
wantRun = false;
document.getElementById("start").disabled = false;
document.getElementById("stop").disabled = true;
if (ws) try { ws.close(); } catch {}
setStatus("stopped");
};
document.getElementById("clear").onclick = () => {
out.textContent = "";
seen.clear();
};
</script>
</body>
</html>
StackBlitz 槽位:待补——示例计划落到
blockreq/blog-demos的examples/robinhood-meme-mint-listen;当前先用上方本地 HTML 跑通。
换自定义 mint / 池子创建:只改页面上的 topic0(用真实 ABI 算出)和 address(工厂或代币)。换 keyed:只改 WSS 常量,Key 放本地,不要提交公开仓库。
断线回补时,用同一 address + topics,对 HTTPS public 调 eth_getLogs,按块分段,记住最后处理的 blockNumber(与第 1 篇相同套路)。
4. BlockReq public endpoint 用法与限流
| 项 | 公共 endpoint | 私有(keyed) |
|---|---|---|
| URL | …/v1/rpc/public | …/v1/rpc/{API_KEY} |
| 限速 | Best-effort,按 IP | 按套餐 RU / req/s |
| 适合 | 学习、短时发射窗口 demo | 长期看板、告警、生产订阅 |
| Key | 无 | Dashboard 创建;永不写进公开 HTML / 仓库 |
实操建议:
- 永远窄过滤 —
address优先;全链Transfer在 meme 高峰会把 public 配额打穿。 - 订阅 + 回补分工 — WSS 负责实时;空窗用 HTTPS
eth_getLogs,窗口别一次拉几千块。 - 429 / 秒断 — 降宽度、拉长回补间隔、高峰换 keyed;同一 IP 不要开十几条宽订阅。
- 去重 —
txHash + logIndexSet,避免重连重放刷屏。 - 指数退避重连 — 浏览器休眠后必现;重连后 重新 eth_subscribe。
5. 和系列第 1 篇、Solana mint 文的分工
| 文章 | 链 / 协议 | 主信号 | 你用来做什么 |
|---|---|---|---|
| 第 1 篇 · 开盘盯盘 | Robinhood Chain · EVM eth_subscribe | newHeads(可选窄 logs) | 出块心跳、开盘节奏看板 |
| 本文 · mint / 发射 logs | 同上 | logs topic 过滤(Transfer / mint / 池子创建) | 发射与铸造类可观测事件 |
| Solana 新 mint | Solana · logsSubscribe | Token Program InitializeMint* | 另一条链的浏览器发射监听 |
怎么组合(观测栈,不是交易栈):
- 第 1 篇的
newHeads当「链还活着」的心跳。 - 本文的窄
logs当「有没有 mint / 建池事件」的信号总线。 - 需要 Solana 同款发射窗时,换协议读 Solana 文——不要把
logsSubscribe参数塞进 EVM client。
合规边界(与系列一致):不写抢跑、刷单、规避平台规则的教战;不荐币;不把 API Key 塞进公开 demo。 监听 meme / 新币发射 = 订阅公开可观测事件,不保证盈利。
---
小结
- 发射信号来自 Robinhood Chain 收据
logs,不是 App 推送;听到事件不等于能赚钱。 - 实时用 WSS
eth_subscribe logs(窄address+topics);空窗用 HTTPSeth_getLogs分段回补。 - topic0 =
keccak256(事件签名);文中 Transfer 为标准示例,Mint / 池子创建请换成 该链真实合约 ABI 算出的值。 - Public 按 IP best-effort 限流;长期盯盘换 keyed,Key 不进 demo。
- 第 1 篇管
newHeads心跳;本文管 mint / 建池类 logs;Solana 发射见 solana-new-mint-browser-logssubscribe。
下一步通常是:固定工厂 / 观察地址列表 → topic 白名单落配置 → 告警 Webhook → 回补 checkpoint 落盘。仍是观测栈,不是交易栈。