BlockReq
返回全部文章

Rpc Tutorials

Robinhood 链上怎么听 meme / 新币发射:订阅日志与 mint 信号

用 eth_subscribe 与 eth_getLogs 回补,在 Robinhood Chain 上订阅 mint / 池子创建类 logs。只谈可观测信号——听到事件≠盈利。

BlockReq Engineering2026年9月5日10 分钟阅读

Robinhood 链上怎么听 meme / 新币发射:订阅日志与 mint 信号

「meme / 新币发射」在这篇里指 Robinhood Chain 上可观测的合约事件流(ERC-20 Transfer / mint 类 log、池子创建类事件),不是 Robinhood App 推送,也不是荐币、抢跑或刷单教战。

目标:用 BlockReq 公共 RPC,把「发射信号」做成可过滤的 logs 订阅与 HTTP 回补——看板、告警、对账用得上。听到事件 ≠ 能盈利;链上可观测只保证你看到公开事实,不保证流动性、可信度或收益。

用途Endpoint
公共 HTTPShttps://robinhood-mainnet-rpc.blockreq.com/v1/rpc/public
公共 WSSwss://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 logs vs eth_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「池子有没有真金白银进去」
任意合约自定义事件项目自己的 TokenCreatedLaunched只当你拿到 真实 ABI 并能算出 topic

建议心态:

  • 可观测 = 记录 blockNumbertxHashaddresstopicsdata
  • 不荐币 = 不点名具体 meme、不暗示「跟着买」。
  • 不操纵 = 不写抢跑路径、不刷量、不教绕过平台风控。

把「事件出现」和「要不要交易」拆开:本文只做前半段,且明确——监听本身不保证盈利

2. eth_subscribe logs vs 轮询 eth_getLogs

WSS eth_subscribelogsHTTPS 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,...)")

注意:

  1. 名字与参数类型必须与 合约 ABI 完全一致(含 indexed 不影响签名字符串本身,但会影响后面 topics 槽位)。
  2. 元组 / 结构体要按 ABI 编码规则展开;不要猜。
  3. 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
自定义 MintMint(address,uint256)0xYOUR_MINT_TOPIC换成真实 ABI 算出的值
池子 / 交易对创建PairCreated(...) / PoolCreated(...) / 项目自定义0xYOUR_PAIR_OR_POOL_CREATED_TOPIC同上
Launchpad 创建项目自定义 TokenCreated / Launched0xYOUR_LAUNCH_TOPIC同上

Mint 常见两种看法(不要混为一谈):

  1. 标准 ERC-20:很多实现把 mint 记成 Transfer(from=0x0, to=recipient, value=amount)。过滤时除了 topics[0]=Transfer,还要看 topics[1](indexed from)是否为零地址,或在客户端解码后判断。
  2. 自定义 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-demosexamples/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长期看板、告警、生产订阅
KeyDashboard 创建;永不写进公开 HTML / 仓库

实操建议:

  1. 永远窄过滤address 优先;全链 Transfer 在 meme 高峰会把 public 配额打穿。
  2. 订阅 + 回补分工 — WSS 负责实时;空窗用 HTTPS eth_getLogs,窗口别一次拉几千块。
  3. 429 / 秒断 — 降宽度、拉长回补间隔、高峰换 keyed;同一 IP 不要开十几条宽订阅。
  4. 去重txHash + logIndex Set,避免重连重放刷屏。
  5. 指数退避重连 — 浏览器休眠后必现;重连后 重新 eth_subscribe

更多:公开端点 · 套餐与定价

5. 和系列第 1 篇、Solana mint 文的分工

文章链 / 协议主信号你用来做什么
第 1 篇 · 开盘盯盘Robinhood Chain · EVM eth_subscribenewHeads(可选窄 logs)出块心跳、开盘节奏看板
本文 · mint / 发射 logs同上logs topic 过滤(Transfer / mint / 池子创建)发射与铸造类可观测事件
Solana 新 mintSolana · logsSubscribeToken Program InitializeMint*另一条链的浏览器发射监听

怎么组合(观测栈,不是交易栈):

  1. 第 1 篇的 newHeads 当「链还活着」的心跳。
  2. 本文的窄 logs 当「有没有 mint / 建池事件」的信号总线。
  3. 需要 Solana 同款发射窗时,换协议读 Solana 文——不要logsSubscribe 参数塞进 EVM client。

合规边界(与系列一致):不写抢跑、刷单、规避平台规则的教战;不荐币;不把 API Key 塞进公开 demo。 监听 meme / 新币发射 = 订阅公开可观测事件,不保证盈利

---

小结

  1. 发射信号来自 Robinhood Chain 收据 logs,不是 App 推送;听到事件不等于能赚钱。
  2. 实时用 WSS eth_subscribe logs(窄 address + topics);空窗用 HTTPS eth_getLogs 分段回补。
  3. topic0 = keccak256(事件签名);文中 Transfer 为标准示例,Mint / 池子创建请换成 该链真实合约 ABI 算出的值。
  4. Public 按 IP best-effort 限流;长期盯盘换 keyed,Key 不进 demo。
  5. 第 1 篇管 newHeads 心跳;本文管 mint / 建池类 logs;Solana 发射见 solana-new-mint-browser-logssubscribe

下一步通常是:固定工厂 / 观察地址列表 → topic 白名单落配置 → 告警 Webhook → 回补 checkpoint 落盘。仍是观测栈,不是交易栈。