跳转到主要内容
Beta — 此功能目前处于测试阶段,API 可能会有变动。
本文档介绍 ChainStream Webhook 的工作原理、配置方法和最佳实践,帮助您实现链上事件的实时推送。
Webhook 功能对所有用户开放。

工作原理

数据流程

核心特性

特性说明
实时推送事件触发后毫秒级推送
可靠投递失败自动重试
签名验证HMAC 签名防伪造
过滤规则支持事件类型过滤

支持的事件类型

目前 Webhook 支持以下事件类型(channels):
Channel描述典型用途
sol.token.createdSolana 新代币创建新币发现、早期机会
sol.token.migratedSolana 代币毕业/迁移追踪从 Pump.fun 等平台毕业的代币
更多事件类型正在开发中,敬请期待!

创建 Webhook 端点

API 端点

POST /v1/webhook/endpoint
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN

请求参数

参数类型必填描述
urlstringWebhook 回调 URL(必须是 HTTPS)
channelsarray订阅的事件类型列表
descriptionstring端点描述
disabledboolean是否禁用,默认 false
filterTypesarray过滤类型
metadataobject自定义元数据
rateLimitinteger速率限制

请求示例

{
  "url": "https://your-server.com/webhook",
  "channels": ["sol.token.created", "sol.token.migrated"],
  "description": "监控新代币和毕业代币"
}

响应示例

{
  "id": "ep_abc123",
  "url": "https://your-server.com/webhook",
  "channels": ["sol.token.created", "sol.token.migrated"],
  "description": "监控新代币和毕业代币",
  "disabled": false
}

Webhook 通知格式

Webhook 通知的数据结构与 WebSocket 推送一致。

新代币创建 (sol.token.created)

{
  "channel": "sol.token.created",
  "timestamp": 1706947200000,
  "data": {
    "a": "6p6xgHyF7AeE6TZkSmFsko444wqoP15icUSqi2jfGiPN",
    "n": "Example Token",
    "s": "EXT",
    "dec": 9,
    "cts": 1706947200000,
    "lf": {
      "pa": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
      "pf": "pump_fun",
      "pn": "Pump.fun"
    }
  }
}
字段说明
字段描述
a代币地址
n代币名称
s代币符号
dec小数位数
cts创建时间戳(毫秒)
lf.pa启动平台程序地址
lf.pf协议家族
lf.pn协议名称

代币毕业 (sol.token.migrated)

{
  "channel": "sol.token.migrated",
  "timestamp": 1706947200000,
  "data": {
    "a": "6p6xgHyF7AeE6TZkSmFsko444wqoP15icUSqi2jfGiPN",
    "n": "Example Token",
    "s": "EXT",
    "cts": 1706947200000,
    "lf": {
      "pa": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
      "pf": "pump_fun",
      "pn": "Pump.fun"
    },
    "mt": {
      "pa": "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
      "pf": "raydium",
      "pn": "Raydium"
    }
  }
}
额外字段
字段描述
mt.pa迁移目标平台程序地址
mt.pf迁移目标协议家族
mt.pn迁移目标协议名称

Webhook URL 要求

要求说明
✅ HTTPS必须使用 HTTPS 协议
✅ 公网可访问URL 必须可从公网访问
✅ 2xx 响应必须返回 2xx 状态码表示成功
✅ 响应时间应在 5 秒内响应
✅ 幂等处理需要处理重复请求

安全验证

获取 Webhook 密钥

创建端点后,通过以下 API 获取密钥:
GET /v1/webhook/endpoint/{id}/secret
响应
{
  "secret": "whsec_abcdXXX"
}

签名验证

每个 Webhook 请求都包含签名头,用于验证请求来源:
X-Webhook-Signature: <signature>
X-Webhook-Timestamp: <timestamp>

验证流程

代码示例

const crypto = require('crypto');

function verifyWebhook(req, secret) {
  const signature = req.headers['x-webhook-signature'];
  const timestamp = req.headers['x-webhook-timestamp'];
  const body = JSON.stringify(req.body);
  
  // 检查时间戳(5分钟窗口)
  const now = Date.now();
  if (Math.abs(now - parseInt(timestamp)) > 300000) {
    return false;
  }
  
  // 计算签名
  const message = `${timestamp}.${body}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');
  
  // 安全比较
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

管理 Webhook 端点

获取端点列表

GET /v1/webhook/endpoint
查询参数
参数类型描述
limitinteger每页数量(1-100,默认100)
iteratorstring分页迭代器
orderstring排序方式(ascending/descending)

获取端点详情

GET /v1/webhook/endpoint/{id}

更新端点

PATCH /v1/webhook/endpoint
{
  "endpointId": "ep_abc123",
  "channels": ["sol.token.created"],
  "description": "只监控新代币"
}

删除端点

DELETE /v1/webhook/endpoint/{id}

轮换密钥

POST /v1/webhook/endpoint/{id}/secret/rotate

最佳实践

✅ 快速响应

# 推荐:先响应,后处理
@app.route('/webhook', methods=['POST'])
def webhook():
    # 验证签名
    if not verify_webhook(request, SECRET):
        return "Invalid signature", 401
    
    # 放入队列异步处理
    queue.put(request.json)
    
    # 立即返回 200
    return "OK", 200

✅ 幂等性处理

每个事件包含唯一标识,请在服务端记录已处理的事件:
# 使用 Redis 记录已处理事件
def process_webhook(event):
    event_id = f"{event['channel']}:{event['data']['a']}:{event['timestamp']}"
    
    # 检查是否已处理
    if redis.exists(f"processed:{event_id}"):
        return {"status": "already_processed"}
    
    # 处理事件
    handle_event(event)
    
    # 标记为已处理(TTL 24小时)
    redis.setex(f"processed:{event_id}", 86400, "1")
    
    return {"status": "ok"}

✅ 安全性

始终验证签名

验证每个请求的签名

使用 HTTPS

确保传输安全

定期轮换密钥

建议每 90 天轮换

保护敏感数据

不在日志中记录敏感数据

✅ 可靠性

实现幂等性

处理重复请求

消息队列缓冲

使用队列异步处理

合理超时时间

避免长时间阻塞

完善日志

记录关键信息便于排查

常见问题

排查步骤
  1. 确认 URL 可访问 — 从公网测试 URL 是否可达
  2. 检查 HTTPS — 必须使用有效的 SSL 证书
  3. 检查端点状态 — 确认 disabled 不是 true
  4. 检查 channels — 确认订阅了正确的事件类型
这可能是重试机制导致的。请实现幂等性处理:
  1. 使用事件的唯一标识(channel + 代币地址 + 时间戳)
  2. 收到请求时先检查是否已处理
  3. 使用带 TTL 的缓存(如 Redis)存储
  1. 使用 ngrok 暴露本地服务
  2. 创建 Webhook 端点指向 ngrok URL
  3. 等待真实事件触发,或使用测试环境
  4. 查看本地服务日志

API 端点汇总

功能端点
获取端点列表GET /v1/webhook/endpoint
创建端点POST /v1/webhook/endpoint
更新端点PATCH /v1/webhook/endpoint
获取端点详情GET /v1/webhook/endpoint/{id}
删除端点DELETE /v1/webhook/endpoint/{id}
获取密钥GET /v1/webhook/endpoint/{id}/secret
轮换密钥POST /v1/webhook/endpoint/{id}/secret/rotate

相关文档