TradingBeats · 方法论 · 规则总文档

tb.post/0 钱包发帖协议

草案 v0 · 2026-09-20 · 参考实现已上线:https://tradingbeats.lol/api/v0/

一句话:钱包地址就是账号。连上钱包就能发帖、改帖、删帖,内容只有文字和图片。 协议只定义这一件事,其余(推荐、排序、标签、置顶、审核)都是客户端的事,不进协议。我们给第三方前端接入的,就是这一个协议和它的 API。

1. 为什么只定义这么少

2. 两层内容

层是什么谁产生有没有签名
行为帖(derived)地址的链上动作翻译成的一句话:建仓、加仓、止盈、被强平、价格大动仓位没动、保证金翻了几倍索引器从链上数据确定性生成,任何人拿同样的数据能重算出同一条没有,也不需要:它是事实,不是发言
签名帖(signed)人说的话:发帖、回复钱包签名有,任何人可以自己验

两层用同一套 id 空间互相引用:签名帖可以回复一条行为帖(parent:tb:<rid>),也可以回复另一条签名帖(parent:p:<id>),或者挂在某个地址名下(parent:hl:<地址>)。

首页上的「置顶热评」就是这么来的:帖子正文只说行为,律动账号在评论区说这张仓位该怎么读,客户端把它置顶。置顶是客户端的选择,不是协议的一部分。

3. 一条消息长什么样

钱包用 personal_sign(EIP-191)签一段人能读的文本,钱包弹窗里看到的就是要发的内容:

tb.post/0
op:create
id:-
parent:tb:3f9a1c0b7e2d
app:tradingbeats
ts:1789900000000
images:-
---
这张空单有现货对着,是对冲不是看空。
行含义
tb.post/0协议名和版本,固定
opcreate 发帖 / edit 改帖 / delete 删帖
idedit / delete 填要动的帖子 id;create 填 -
parent回复谁:p:<帖子 id>、tb:<行为帖 rid>、hl:<0x 地址>,独立帖填 -。rev:<行为帖 rid> = 地址本人对这条行为帖的修订(09-21):客户端只认作者等于这条行为帖地址的那一条,用它的正文替换系统文字并标「已编辑」;再改用 edit,delete = 恢复系统原文。行为帖本身没有删除这个操作,当时持仓也改不了
app从哪个客户端发的(builder 名或地址,≤ 60 字符)。用户自己签进去的,所以归属造不了假;没有填 -
ts毫秒时间戳。服务器只收和自己时间差 10 分钟以内的,防重放;同一条帖子的后一次操作 ts 必须更新
images逗号分隔的 https 图片地址,最多 4 张;没有填 -
--- 之后正文,最多 1,000 字,可以换行;delete 留空

七行头部顺序固定,行尾 \n,不带多余空格。

规则只有三条:

  1. 从签名恢复出来的地址就是作者,不需要注册、不需要登录态。
  2. edit / delete 的签名者必须是原帖作者。
  3. 帖子 id = sha256(消息 + 签名) 的前 16 位十六进制。消息原文和签名跟着帖子一起返回,谁都可以自己验一遍,不用信服务器。

4. API

根地址 https://tradingbeats.lol/api/v0,全部允许跨域,不需要 key。

方法路径说明
POST/posts请求体 {"msg": "<上面那段文本>", "sig": "0x…"}。发、改、删都走这一个口,op 写在签名消息里。成功返回 {ok, post}
GET/posts查询参数都可选:author(地址)、parent、app、since(毫秒,按最后修改时间)、limit(默认 200,最多 1,000)、ids(逗号分隔)。新的在前,已删的不出
GET/posts/<id>单条
POST/blobs传图:{"msg", "sig", "data": "<base64>"},消息是 tb.blob/0\nsha256:<hex>\nmime:image/png\nts:<ms>。png / jpeg / webp / gif,最大 1.5 MB,按内容哈希命名,返回 https 地址填进 images

返回的帖子:{id, author, parent, app, text, images, ts, rev, edited, msg, sig}。rev 是改过几次,edited 是最后一次改的时间。

出错返回 {ok: false, error: "<人话>"},HTTP 400。限速:同一个地址一小时 30 条。

最小接入(浏览器)

const addr = (await ethereum.request({method: 'eth_requestAccounts'}))[0];
const msg = ['tb.post/0', 'op:create', 'id:-', 'parent:-', 'app:yourapp', 'ts:' + Date.now(), 'images:-', '---', '第一条'].join('\n');
const hex = '0x' + [...new TextEncoder().encode(msg)].map(b => b.toString(16).padStart(2, '0')).join('');
const sig = await ethereum.request({method: 'personal_sign', params: [hex, addr]});
await fetch('https://tradingbeats.lol/api/v0/posts', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({msg, sig})});

读某个地址的帖子:GET /posts?author=0x…;读某条行为帖下面的评论:GET /posts?parent=tb:<rid>。

5. 第三方拿到什么

6. 明确不做的

7. 下一步(v0 之后)

8. 参考实现

pipeline/post_protocol.py(消息解析、验签、存储)+ pipeline/ethsig.py(纯标准库的 keccak256 与 secp256k1 公钥恢复,已和 ethers.js 的签名对过)+ pipeline/admin_api.py 里的 /api/v0/ 路由。首页 tradingbeats.lol 的「个人主页」发帖和每条帖子下面的留言,钱包连上以后走的就是这个协议。